Files
cypress/scripts/binary/get-published-artifacts.js
Adam Stone-Lord fe6f72f6c7 chore: fix get-published-artifact script (#27610)
* chore: fix get-published-artifact scripts [run ci]

* update unit test, check linux-arm workflow [run ci]

* circle workflow getting cached?
2023-08-21 12:34:56 -05:00

172 lines
4.7 KiB
JavaScript

const fs = require('fs-extra')
const rp = require('@cypress/request-promise')
const util = require('util')
const exec = require('child_process').exec
const minimist = require('minimist')
const chalk = require('chalk')
const execPromise = util.promisify(exec)
const getArtifactJobName = (platformKey) => {
if (platformKey === 'linux-x64') {
return 'linux-amd-publish-binary'
}
return 'publish-binary'
}
const urlPaths = [
'~/cypress/binary-url.json',
'~/cypress/npm-package-url.json',
]
const archivePaths = [
'~/cypress/cypress.zip',
'~/cypress/cypress.tgz',
]
function getRequestOptions (url) {
return {
method: 'GET',
url,
headers: { 'Circle-Token': process.env.CIRCLE_TOKEN },
}
}
function getPipelineId (pipelineInfoFilePath) {
const data = fs.readFileSync(pipelineInfoFilePath)
const parsedPipelineId = JSON.parse(data).id
if (!parsedPipelineId) {
throw new Error(`error retrieving pipeline id from ${pipelineInfoFilePath}`)
}
return parsedPipelineId
}
async function getWorkflows (pipelineId) {
const response = await rp(getRequestOptions(`https://circleci.com/api/v2/pipeline/${pipelineId}/workflow`))
const parsed = JSON.parse(response)
if (parsed.items.length === 0) {
throw new Error(`did not find any workflows in pipeline ${pipelineId}`)
}
if (parsed.items.length > 1) {
console.log(parsed.items)
throw new Error(`expected pipeline ${pipelineId} to only have one workflow, but it had many`)
}
return parsed.items
}
async function getWorkflowJobs (workflowId) {
const response = await rp(getRequestOptions(`https://circleci.com/api/v2/workflow/${workflowId}/job`))
const parsed = JSON.parse(response)
if (parsed.items.length === 0) {
throw new Error(`did not find any jobs in workflow ${workflowId}`)
}
return parsed.items
}
async function getJobArtifacts (jobNumber) {
const response = await rp(getRequestOptions(`https://circleci.com/api/v2/project/github/cypress-io/cypress-publish-binary/${jobNumber}/artifacts`))
const parsed = JSON.parse(response)
if (parsed.items.length === 0) {
throw new Error(`did not find any artifacts for job ${jobNumber}`)
}
return parsed.items
}
async function downloadArtifact (url, path) {
try {
console.log(`Downloading artifact from ${chalk.cyan(url)} \n to path ${chalk.cyan(path)}...`)
await execPromise(`curl -L --url ${url} --header 'Circle-Token: ${process.env.CIRCLE_TOKEN}' --header 'content-type: application/json' -o ${path}`)
} catch (error) {
throw new Error(`failed to fetch artifact from URL ${url}: ${error}`)
}
}
async function run (args) {
const options = minimist(args)
const artifactJobName = getArtifactJobName(options.platformKey)
const pipelineInfoFilePath = options.pipelineInfo
if (!pipelineInfoFilePath) {
throw new Error('--pipelineInfo must be provided as a parameter')
}
console.log(`Parsing pipeline info from ${chalk.cyan(pipelineInfoFilePath)}...`)
const pipelineId = module.exports.getPipelineId(pipelineInfoFilePath)
console.log(`Getting workflows from pipeline ${chalk.cyan(pipelineId)}...`)
const workflows = await module.exports.getWorkflows(pipelineId)
const workflow = workflows[0]
if (workflow.status !== 'success') {
console.error(chalk.red(`\nThe ${chalk.cyan(workflow.name)} workflow that we triggered in the ${chalk.cyan('cypress-publish-binary')} project did not succeed.\n
Status: ${chalk.red(workflow.status)} \n
Check the workflow logs to see why it failed
${chalk.cyan.underline(`https://app.circleci.com/pipelines/workflows/${workflow.id}`)}
`))
process.exitCode = 1
return
}
console.log(`Getting jobs from workflow ${chalk.cyan(workflow.name)}...`)
const jobs = await module.exports.getWorkflowJobs(workflow.id)
const job = jobs.find((job) => job.name === artifactJobName)
if (!job) {
throw new Error(`unable to find job in workflow ${workflow.name} named ${artifactJobName}`)
}
const artifacts = await module.exports.getJobArtifacts(job.job_number)
let artifactPaths
if (process.env.SHOULD_PERSIST_ARTIFACTS) {
artifactPaths = [...urlPaths, ...archivePaths]
} else {
// If we didn't persist the artifacts to the registry, then we only want the build artifacts, no URLs.
artifactPaths = [...archivePaths]
}
const filteredArtifacts = artifacts.filter((artifact) => artifactPaths.includes(artifact.path))
await Promise.all(filteredArtifacts.map(({ url, path }) => {
return module.exports.downloadArtifact(url, path)
}))
console.log('Artifacts successfully downloaded ✅')
}
module.exports = {
getPipelineId,
getWorkflows,
getWorkflowJobs,
getJobArtifacts,
downloadArtifact,
run,
}
if (!module.parent) {
run(process.argv)
}