UNPKG

@ledgerhq/live-common

Version:
161 lines • 5.82 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.waitForSpeculosReady = waitForSpeculosReady; exports.createSpeculosDeviceCI = createSpeculosDeviceCI; exports.releaseSpeculosDeviceCI = releaseSpeculosDeviceCI; const axios_1 = __importDefault(require("axios")); const speculos_transport_1 = require("@ledgerhq/speculos-transport"); const https_1 = __importDefault(require("https")); const index_1 = require("./index"); const uuid_1 = require("uuid"); const { GITHUB_TOKEN, SPECULOS_IMAGE_TAG } = process.env; const GIT_API_URL = "https://api.github.com/repos/LedgerHQ/actions/actions/"; const START_WORKFLOW_ID = "workflows/161487603/dispatches"; const STOP_WORKFLOW_ID = "workflows/161487604/dispatches"; const GITHUB_REF = "main"; const getSpeculosAddress = (runId) => `https://${runId}.speculos.aws.stg.ldg-tech.com`; const speculosPort = 443; function uniqueId() { return (0, uuid_1.v4)(); } function slugify(name) { return name .toLowerCase() .trim() .replace(/[^a-z0-9]+/g, "-") .replace(/^-+|-+$/g, ""); } /** * Helper function to make API requests with error handling */ async function githubApiRequest({ method = "POST", urlSuffix, data, params, }) { const url = `${GIT_API_URL}${urlSuffix}`; try { const response = await (0, axios_1.default)({ method, url, headers: { Authorization: `Bearer ${GITHUB_TOKEN}`, Accept: "application/vnd.github+json", "X-GitHub-Api-Version": "2022-11-28", }, data, params, }); return response.data; } catch (error) { console.warn(`API Request failed: ${method} ${url}`, (0, index_1.sanitizeError)(error)); throw (0, index_1.sanitizeError)(error); } } function waitForSpeculosReady(deviceId, { interval = 2_000, timeout = 150_000 } = {}) { return new Promise((resolve, reject) => { const startTime = Date.now(); let currentRequest = null; const url = getSpeculosAddress(deviceId); function cleanup() { if (currentRequest) { currentRequest.destroy(); currentRequest = null; } } function check() { cleanup(); currentRequest = https_1.default.get(url, { timeout: 10000 }, res => { if (res.statusCode && res.statusCode >= 200 && res.statusCode < 400) { process.env.SPECULOS_ADDRESS = url; cleanup(); console.warn(`Speculos is ready at ${url}`); resolve(true); } else { console.warn(`Speculos not ready yet, status: ${res.statusCode}`); retry(); } }); currentRequest.on("error", error => { console.error(`Request error: ${error.message}`); retry(); }); currentRequest.on("timeout", () => { console.error("Request timeout"); retry(); }); } function retry() { if (Date.now() - startTime >= timeout) { cleanup(); reject(new Error(`Timeout: ${url} did not become available within ${timeout}ms`)); } else { setTimeout(check, interval); } } check(); }); } function createStartPayload(deviceParams, runId) { const { model, firmware, appName, appVersion, dependencies } = deviceParams; let additional_args = "-p"; if (dependencies?.length) { additional_args = [ additional_args, ...new Set(dependencies.map(dep => `-l ${dep.name}:/apps/${(0, speculos_transport_1.conventionalAppSubpath)(model, firmware, dep.name, dep.appVersion ?? appVersion)}`)), ].join(" "); } return { ref: GITHUB_REF, inputs: { speculos_version: SPECULOS_IMAGE_TAG?.split(":")[1] || "master", coin_app: appName, coin_app_version: appVersion, device: speculos_transport_1.reverseModelMap[model], device_os_version: firmware, run_id: runId, additional_args, }, }; } async function createSpeculosDeviceCI(deviceParams) { const runId = `${slugify(deviceParams.appName)}-${uniqueId()}`; try { const data = createStartPayload(deviceParams, runId); await githubApiRequest({ urlSuffix: START_WORKFLOW_ID, data }); return { id: runId, port: speculosPort, appName: deviceParams.appName, appVersion: deviceParams.appVersion, dependencies: deviceParams.dependencies, }; } catch (error) { console.warn(`Failed to create remote Speculos ${deviceParams.appName}:${deviceParams.appVersion}:`, (0, index_1.sanitizeError)(error)); return { id: runId, port: 0, appName: deviceParams.appName, appVersion: deviceParams.appVersion, dependencies: deviceParams.dependencies, }; } } async function releaseSpeculosDeviceCI(runId) { const data = { ref: GITHUB_REF, inputs: { run_id: runId.toString(), }, }; try { await githubApiRequest({ urlSuffix: STOP_WORKFLOW_ID, data }); } catch (error) { console.warn(`Failed to release remote Speculos ${runId}:`, (0, index_1.sanitizeError)(error)); } } //# sourceMappingURL=speculosCI.js.map