mirror of
https://github.com/cypress-io/cypress.git
synced 2026-02-21 14:41:00 -06:00
chore: remove / replace circleci polling jobs (#28605)
* remove-percy-funalize-polling run ci * remove wait-on-circle-jobs * remove polling
This commit is contained in:
@@ -57,7 +57,6 @@ linuxArm64WorkflowFilters: &linux-arm64-workflow-filters
|
||||
- equal: [ 'update-v8-snapshot-cache-on-develop', << pipeline.git.branch >> ]
|
||||
- equal: [ 'feature/experimental-retries', << pipeline.git.branch >> ]
|
||||
- equal: [ 'chore/update_webpack_deps_to_latest_webpack4_compat', << pipeline.git.branch >> ]
|
||||
- equal: [ 'chore/bump_loaders_and_optimize_webpack', << pipeline.git.branch >> ]
|
||||
- equal: [ 'lerna-optimize-tasks', << pipeline.git.branch >> ]
|
||||
- matches:
|
||||
pattern: /^release\/\d+\.\d+\.\d+$/
|
||||
@@ -1134,17 +1133,6 @@ commands:
|
||||
<<parameters.command>>
|
||||
- store-npm-logs
|
||||
|
||||
wait-on-circle-jobs:
|
||||
description: Polls certain Circle CI jobs until they finish
|
||||
parameters:
|
||||
job-names:
|
||||
description: comma separated list of circle ci job names to wait for
|
||||
type: string
|
||||
steps:
|
||||
- run:
|
||||
name: "Waiting on Circle CI jobs: <<parameters.job-names>>"
|
||||
command: node ./scripts/wait-on-circle-jobs.js --job-names="<<parameters.job-names>>"
|
||||
|
||||
check-if-binary-exists:
|
||||
steps:
|
||||
- run:
|
||||
@@ -1407,9 +1395,7 @@ jobs:
|
||||
name: Check TS Types
|
||||
command: NODE_OPTIONS=--max_old_space_size=4096 yarn check-ts --concurrency=1
|
||||
|
||||
|
||||
# a special job that keeps polling Circle and when all
|
||||
# individual jobs are finished, it closes the Percy build
|
||||
# a special job that closes the Percy build started by the required jobs
|
||||
percy-finalize:
|
||||
<<: *defaults
|
||||
resource_class: small
|
||||
@@ -1421,8 +1407,8 @@ jobs:
|
||||
- restore_cached_workspace
|
||||
- run:
|
||||
# if this is an external pull request, the environment variables
|
||||
# are NOT set for security reasons, thus no need to poll -
|
||||
# and no need to finalize Percy, since there will be no visual tests
|
||||
# are NOT set for security reasons, thus no need to to finalize Percy,
|
||||
# since there will be no visual tests
|
||||
name: Check if <<parameters.required_env_var>> is set
|
||||
command: |
|
||||
if [[ -v <<parameters.required_env_var>> ]]; then
|
||||
@@ -1431,18 +1417,6 @@ jobs:
|
||||
echo "This is an external PR, cannot access other services"
|
||||
circleci-agent step halt
|
||||
fi
|
||||
- wait-on-circle-jobs:
|
||||
job-names: >
|
||||
cli-visual-tests,
|
||||
reporter-integration-tests,
|
||||
run-app-component-tests-chrome,
|
||||
run-app-integration-tests-chrome,
|
||||
run-frontend-shared-component-tests-chrome,
|
||||
run-launchpad-component-tests-chrome,
|
||||
run-launchpad-integration-tests-chrome,
|
||||
run-reporter-component-tests-chrome,
|
||||
run-webpack-dev-server-integration-tests,
|
||||
run-vite-dev-server-integration-tests
|
||||
- run:
|
||||
# Sometimes, even though all the circle jobs have finished, Percy times out during `build:finalize`
|
||||
# If all other jobs finish but `build:finalize` fails, we retry it once
|
||||
@@ -1451,25 +1425,12 @@ jobs:
|
||||
PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_WORKSPACE_ID \
|
||||
yarn percy build:finalize || yarn percy build:finalize
|
||||
|
||||
# a special job that keeps polling Circle and when all
|
||||
# pipeline workflows are finished, it moves forward with the binary release
|
||||
trigger-binary-release-workflow:
|
||||
ready-to-release:
|
||||
<<: *defaults
|
||||
resource_class: small
|
||||
parameters:
|
||||
<<: *defaultsParameters
|
||||
steps:
|
||||
- restore_cached_workspace
|
||||
- run:
|
||||
name: 'Determine if Release Workflow should be triggered'
|
||||
command: |
|
||||
if [[ "$CIRCLE_BRANCH" != "develop" ]]; then
|
||||
echo "Only move forward with the release when running on develop."
|
||||
circleci-agent step halt
|
||||
fi
|
||||
- run:
|
||||
name: "Wait for other Circle CI workflows to finish"
|
||||
command: CIRCLE_PIPELINE_ID="<<pipeline.id>>" node ./scripts/wait-on-circle-workflows.js
|
||||
- run:
|
||||
name: Ready to release
|
||||
command: echo 'Ready to release'
|
||||
@@ -2191,7 +2152,7 @@ jobs:
|
||||
<<: *defaultsParameters
|
||||
resource_class:
|
||||
type: string
|
||||
default: xlarge
|
||||
default: small
|
||||
resource_class: << parameters.resource_class >>
|
||||
steps:
|
||||
- maybe_skip_binary_jobs
|
||||
@@ -2640,10 +2601,19 @@ linux-x64-workflow: &linux-x64-workflow
|
||||
requires:
|
||||
- build
|
||||
- percy-finalize:
|
||||
context: [test-runner:poll-circle-workflow, test-runner:percy]
|
||||
required_env_var: PERCY_TOKEN # skips job if not defined (external PR)
|
||||
context: test-runner:percy
|
||||
required_env_var: PERCY_TOKEN
|
||||
requires:
|
||||
- build
|
||||
- cli-visual-tests
|
||||
- reporter-integration-tests
|
||||
- run-app-component-tests-chrome
|
||||
- run-app-integration-tests-chrome
|
||||
- run-frontend-shared-component-tests-chrome
|
||||
- run-launchpad-component-tests-chrome
|
||||
- run-launchpad-integration-tests-chrome
|
||||
- run-reporter-component-tests-chrome
|
||||
- run-webpack-dev-server-integration-tests
|
||||
- run-vite-dev-server-integration-tests
|
||||
- lint-types:
|
||||
requires:
|
||||
- build
|
||||
@@ -2800,16 +2770,15 @@ linux-x64-workflow: &linux-x64-workflow
|
||||
- v8-integration-tests:
|
||||
requires:
|
||||
- system-tests-node-modules-install
|
||||
# This release definition must be updated with any new jobs
|
||||
# Any attempts to automate this are welcome
|
||||
# If CircleCI provided an "after all" hook, then this wouldn't be necessary
|
||||
- trigger-binary-release-workflow:
|
||||
context: test-runner:poll-circle-workflow
|
||||
|
||||
- ready-to-release:
|
||||
# <<: *mainBuildFilters
|
||||
requires:
|
||||
- build
|
||||
- check-ts
|
||||
- npm-angular
|
||||
- npm-eslint-plugin-dev
|
||||
- npm-puppeteer-unit-tests
|
||||
- npm-puppeteer-cypress-tests
|
||||
- npm-react
|
||||
- npm-mount-utils
|
||||
- npm-vue
|
||||
@@ -2826,11 +2795,13 @@ linux-x64-workflow: &linux-x64-workflow
|
||||
- driver-integration-tests-chrome
|
||||
- driver-integration-tests-chrome-beta
|
||||
- driver-integration-tests-electron
|
||||
- driver-integration-tests-webkit
|
||||
- driver-integration-memory-tests
|
||||
- system-tests-non-root
|
||||
- system-tests-firefox
|
||||
- system-tests-electron
|
||||
- system-tests-chrome
|
||||
- system-tests-webkit
|
||||
- server-performance-tests
|
||||
- server-integration-tests
|
||||
- server-unit-tests
|
||||
@@ -2844,67 +2815,13 @@ linux-x64-workflow: &linux-x64-workflow
|
||||
- test-kitchensink
|
||||
- unit-tests
|
||||
- verify-release-readiness
|
||||
- cli-visual-tests
|
||||
- reporter-integration-tests
|
||||
- run-app-component-tests-chrome
|
||||
- run-app-integration-tests-chrome
|
||||
- run-frontend-shared-component-tests-chrome
|
||||
- run-launchpad-component-tests-chrome
|
||||
- run-launchpad-integration-tests-chrome
|
||||
- run-reporter-component-tests-chrome
|
||||
- npm-puppeteer-unit-tests
|
||||
- npm-puppeteer-cypress-tests
|
||||
- run-webpack-dev-server-integration-tests
|
||||
- run-vite-dev-server-integration-tests
|
||||
- v8-integration-tests
|
||||
|
||||
- npm-release:
|
||||
<<: *mainBuildFilters
|
||||
context: test-runner:npm-release
|
||||
requires:
|
||||
- build
|
||||
- check-ts
|
||||
- npm-angular
|
||||
- npm-eslint-plugin-dev
|
||||
- npm-react
|
||||
- npm-mount-utils
|
||||
- npm-vue
|
||||
- npm-webpack-batteries-included-preprocessor
|
||||
- npm-webpack-preprocessor
|
||||
- npm-vite-dev-server
|
||||
- npm-vite-plugin-cypress-esm
|
||||
- npm-webpack-dev-server
|
||||
- npm-cypress-schematic
|
||||
- lint-types
|
||||
- linux-lint
|
||||
- percy-finalize
|
||||
- driver-integration-tests-firefox
|
||||
- driver-integration-tests-chrome
|
||||
- driver-integration-tests-chrome-beta
|
||||
- driver-integration-tests-electron
|
||||
- driver-integration-memory-tests
|
||||
- system-tests-non-root
|
||||
- system-tests-firefox
|
||||
- system-tests-electron
|
||||
- system-tests-chrome
|
||||
- server-performance-tests
|
||||
- server-integration-tests
|
||||
- server-unit-tests
|
||||
- test-kitchensink
|
||||
- unit-tests
|
||||
- verify-release-readiness
|
||||
- cli-visual-tests
|
||||
- reporter-integration-tests
|
||||
- run-app-component-tests-chrome
|
||||
- run-app-integration-tests-chrome
|
||||
- run-frontend-shared-component-tests-chrome
|
||||
- run-launchpad-component-tests-chrome
|
||||
- run-launchpad-integration-tests-chrome
|
||||
- run-reporter-component-tests-chrome
|
||||
- npm-puppeteer-unit-tests
|
||||
- npm-puppeteer-cypress-tests
|
||||
- run-webpack-dev-server-integration-tests
|
||||
- run-vite-dev-server-integration-tests
|
||||
- v8-integration-tests
|
||||
- ready-to-release
|
||||
|
||||
- create-and-trigger-packaging-artifacts:
|
||||
context:
|
||||
@@ -3015,7 +2932,6 @@ linux-x64-contributor-workflow: &linux-x64-contributor-workflow
|
||||
- build:
|
||||
requires:
|
||||
- node_modules_install
|
||||
|
||||
# In subsequent jobs, we use some contexts that are restricted to members of the Cypress organization.
|
||||
# This job will allow for a Cypress member to approve and run the rest of the restricted jobs in the pipeline after the contributor code has been reviewed.
|
||||
- contributor-pr:
|
||||
@@ -3031,10 +2947,19 @@ linux-x64-contributor-workflow: &linux-x64-contributor-workflow
|
||||
requires:
|
||||
- build
|
||||
- percy-finalize:
|
||||
context: [test-runner:poll-circle-workflow, test-runner:percy]
|
||||
context: test-runner:percy
|
||||
required_env_var: PERCY_TOKEN # skips job if not defined (external PR)
|
||||
requires:
|
||||
- contributor-pr
|
||||
- cli-visual-tests
|
||||
- reporter-integration-tests
|
||||
- run-app-component-tests-chrome
|
||||
- run-app-integration-tests-chrome
|
||||
- run-frontend-shared-component-tests-chrome
|
||||
- run-launchpad-component-tests-chrome
|
||||
- run-launchpad-integration-tests-chrome
|
||||
- run-reporter-component-tests-chrome
|
||||
- run-webpack-dev-server-integration-tests
|
||||
- run-vite-dev-server-integration-tests
|
||||
- lint-types:
|
||||
requires:
|
||||
- build
|
||||
@@ -3191,13 +3116,9 @@ linux-x64-contributor-workflow: &linux-x64-contributor-workflow
|
||||
- v8-integration-tests:
|
||||
requires:
|
||||
- system-tests-node-modules-install
|
||||
# This release definition must be updated with any new jobs
|
||||
# Any attempts to automate this are welcome
|
||||
# If CircleCI provided an "after all" hook, then this wouldn't be necessary
|
||||
- trigger-binary-release-workflow:
|
||||
context: test-runner:poll-circle-workflow
|
||||
|
||||
- ready-to-release:
|
||||
requires:
|
||||
- build
|
||||
- check-ts
|
||||
- npm-angular
|
||||
- npm-eslint-plugin-dev
|
||||
@@ -3219,11 +3140,13 @@ linux-x64-contributor-workflow: &linux-x64-contributor-workflow
|
||||
- driver-integration-tests-chrome
|
||||
- driver-integration-tests-chrome-beta
|
||||
- driver-integration-tests-electron
|
||||
- driver-integration-tests-webkit
|
||||
- driver-integration-memory-tests
|
||||
- system-tests-non-root
|
||||
- system-tests-firefox
|
||||
- system-tests-electron
|
||||
- system-tests-chrome
|
||||
- system-tests-webkit
|
||||
- server-performance-tests
|
||||
- server-integration-tests
|
||||
- server-unit-tests
|
||||
@@ -3237,63 +3160,12 @@ linux-x64-contributor-workflow: &linux-x64-contributor-workflow
|
||||
- test-kitchensink
|
||||
- unit-tests
|
||||
- verify-release-readiness
|
||||
- cli-visual-tests
|
||||
- reporter-integration-tests
|
||||
- run-app-component-tests-chrome
|
||||
- run-app-integration-tests-chrome
|
||||
- run-frontend-shared-component-tests-chrome
|
||||
- run-launchpad-component-tests-chrome
|
||||
- run-launchpad-integration-tests-chrome
|
||||
- run-reporter-component-tests-chrome
|
||||
- run-webpack-dev-server-integration-tests
|
||||
- run-vite-dev-server-integration-tests
|
||||
- v8-integration-tests
|
||||
|
||||
- npm-release:
|
||||
context: test-runner:npm-release
|
||||
requires:
|
||||
- build
|
||||
- check-ts
|
||||
- npm-angular
|
||||
- npm-eslint-plugin-dev
|
||||
- npm-react
|
||||
- npm-mount-utils
|
||||
- npm-vue
|
||||
- npm-webpack-batteries-included-preprocessor
|
||||
- npm-webpack-preprocessor
|
||||
- npm-vite-dev-server
|
||||
- npm-vite-plugin-cypress-esm
|
||||
- npm-webpack-dev-server
|
||||
- npm-cypress-schematic
|
||||
- lint-types
|
||||
- linux-lint
|
||||
- percy-finalize
|
||||
- driver-integration-tests-firefox
|
||||
- driver-integration-tests-chrome
|
||||
- driver-integration-tests-chrome-beta
|
||||
- driver-integration-tests-electron
|
||||
- driver-integration-memory-tests
|
||||
- system-tests-non-root
|
||||
- system-tests-firefox
|
||||
- system-tests-electron
|
||||
- system-tests-chrome
|
||||
- server-performance-tests
|
||||
- server-integration-tests
|
||||
- server-unit-tests
|
||||
- test-kitchensink
|
||||
- unit-tests
|
||||
- verify-release-readiness
|
||||
- cli-visual-tests
|
||||
- reporter-integration-tests
|
||||
- run-app-component-tests-chrome
|
||||
- run-app-integration-tests-chrome
|
||||
- run-frontend-shared-component-tests-chrome
|
||||
- run-launchpad-component-tests-chrome
|
||||
- run-launchpad-integration-tests-chrome
|
||||
- run-reporter-component-tests-chrome
|
||||
- run-webpack-dev-server-integration-tests
|
||||
- run-vite-dev-server-integration-tests
|
||||
- v8-integration-tests
|
||||
- ready-to-release
|
||||
|
||||
- create-and-trigger-packaging-artifacts:
|
||||
context: [test-runner:upload, test-runner:build-binary, publish-binary]
|
||||
@@ -3427,19 +3299,16 @@ linux-arm64-workflow: &linux-arm64-workflow
|
||||
- linux-arm64-wait-for-binary-publish
|
||||
|
||||
- v8-integration-tests:
|
||||
name: linux-arm64-v8-integration-tests
|
||||
executor: linux-arm64
|
||||
resource_class: arm.medium
|
||||
requires:
|
||||
- linux-arm64-build
|
||||
- driver-integration-memory-tests:
|
||||
name: linux-arm64-driver-integration-memory-tests
|
||||
executor: linux-arm64
|
||||
resource_class: arm.medium
|
||||
requires:
|
||||
- linux-arm64-build
|
||||
- server-unit-tests-cloud-environment:
|
||||
name: linux-arm64-server-unit-tests-cloud-environment
|
||||
executor: linux-arm64
|
||||
resource_class: arm.medium
|
||||
requires:
|
||||
|
||||
@@ -162,7 +162,6 @@
|
||||
"fs-extra": "9.1.0",
|
||||
"getenv": "^1.0.0",
|
||||
"glob": "7.1.6",
|
||||
"got": "11.8.6",
|
||||
"graphql": "^15.5.1",
|
||||
"graphql-executor": "0.0.23",
|
||||
"gulp": "4.0.2",
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
const _ = require('lodash')
|
||||
const minimist = require('minimist')
|
||||
const Promise = require('bluebird')
|
||||
const retry = require('bluebird-retry')
|
||||
const got = require('got')
|
||||
// always print the debug logs
|
||||
const debug = require('debug')('*')
|
||||
|
||||
const { seconds, minutes } = require('./utils')
|
||||
|
||||
// we expect CircleCI to set the current polling job name
|
||||
const jobName = process.env.CIRCLE_JOB || 'wait-on-circle-jobs'
|
||||
|
||||
const workflowId = process.env.CIRCLE_WORKFLOW_ID
|
||||
|
||||
const getAuth = () => `${process.env.CIRCLE_TOKEN}:`
|
||||
|
||||
const verifyCI = () => {
|
||||
if (!process.env.CIRCLE_TOKEN) {
|
||||
console.error('Cannot find CIRCLE_TOKEN')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (!process.env.CIRCLE_WORKFLOW_ID) {
|
||||
console.error('Cannot find CIRCLE_WORKFLOW_ID')
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Job status
|
||||
* - blocked (has not run yet)
|
||||
* - running (currently running)
|
||||
* - failed | success
|
||||
*/
|
||||
const getJobStatus = async (workflowId) => {
|
||||
const auth = getAuth()
|
||||
// typo at https://circleci.com/docs/2.0/api-intro/
|
||||
// to retrieve all jobs, the url is "/workflow/:id/job"
|
||||
const url = `https://${auth}@circleci.com/api/v2/workflow/${workflowId}/job`
|
||||
const response = await got(url).json()
|
||||
|
||||
// returns something like
|
||||
// {
|
||||
// next_page_token: null,
|
||||
// items: [
|
||||
// {
|
||||
// dependencies: [],
|
||||
// job_number: 400959,
|
||||
// id: '7021bcc7-90c1-47d9-bf99-c0372a4f8f49',
|
||||
// started_at: '2020-07-20T19:45:46Z',
|
||||
// name: 'build',
|
||||
// project_slug: 'gh/cypress-io/cypress',
|
||||
// status: 'success',
|
||||
// type: 'build',
|
||||
// stopped_at: '2020-07-20T19:50:07Z'
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
return response
|
||||
}
|
||||
|
||||
const waitForAllJobs = async (jobNames, workflowId) => {
|
||||
let response
|
||||
|
||||
try {
|
||||
response = await getJobStatus(workflowId)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
// if a job is pending, its status will be "blocked"
|
||||
const blockedJobs = _.filter(response.items, { status: 'blocked' })
|
||||
const failedJobs = _.filter(response.items, { status: 'failed' })
|
||||
const runningJobs = _.filter(response.items, { status: 'running' })
|
||||
const successfulJobNames = _.filter(response.items, { status: 'success' }).map((w) => w.name)
|
||||
|
||||
const blockedJobNames = _.map(blockedJobs, 'name')
|
||||
const runningJobNames = _.map(runningJobs, 'name')
|
||||
const failedJobNames = _.map(failedJobs, 'name')
|
||||
|
||||
debug('failed jobs %o', _.map(failedJobs, 'name'))
|
||||
debug('blocked jobs %o', blockedJobNames)
|
||||
debug('running jobs %o', runningJobNames)
|
||||
|
||||
if (_.intersection(jobNames, failedJobNames).length) {
|
||||
console.error('At least one failing job has prevented percy-finalize from running', failedJobs)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const waitOnJobsOnlyJobLeft = !runningJobs.length || (runningJobs.length === 1 && runningJobs[0].name === jobName)
|
||||
const allWaitForJobsWereSuccessful = _.intersection(jobNames, successfulJobNames).length === jobNames.length
|
||||
|
||||
if (waitOnJobsOnlyJobLeft && allWaitForJobsWereSuccessful) {
|
||||
// there are no more jobs to run, or this is the last running job
|
||||
console.log('all jobs are done, finishing this job')
|
||||
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
const futureOrRunning = _.union(blockedJobs, runningJobNames)
|
||||
const jobsToWaitFor = _.intersection(jobNames, futureOrRunning)
|
||||
|
||||
// logging something every time this runs will avoid CI timing out if there is no activity for 10 mins.
|
||||
console.log(`waiting for ${jobsToWaitFor.length} jobs to finish, jobs outstanding:\n - `, jobsToWaitFor.join('\n - '))
|
||||
|
||||
debug('jobs to wait for %o', jobsToWaitFor)
|
||||
|
||||
if (!jobsToWaitFor.length && allWaitForJobsWereSuccessful) {
|
||||
console.log('No more jobs to wait for and all jobs were successful!')
|
||||
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
return Promise.reject(new Error('Jobs have not finished'))
|
||||
}
|
||||
|
||||
const main = () => {
|
||||
verifyCI()
|
||||
|
||||
const args = minimist(process.argv.slice(2), { boolean: false })
|
||||
|
||||
const jobNames = _
|
||||
.chain(args['job-names'])
|
||||
.split(',')
|
||||
.without('true')
|
||||
.map(_.trim)
|
||||
.compact()
|
||||
.value()
|
||||
|
||||
if (!jobNames.length) {
|
||||
console.error('Missing argument: --job-names')
|
||||
console.error('You must pass a comma separated list of Circle CI job names to wait for.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
debug('received circle jobs: %o', jobNames)
|
||||
|
||||
// https://github.com/demmer/bluebird-retry
|
||||
retry(waitForAllJobs.bind(null, jobNames, workflowId), {
|
||||
timeout: minutes(30), // max time for this job
|
||||
interval: seconds(30), // poll intervals
|
||||
max_interval: seconds(30),
|
||||
}).then(() => {
|
||||
console.log('all done')
|
||||
}, (err) => {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
|
||||
// execute main function if called from command line
|
||||
if (require.main === module) {
|
||||
main()
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
|
||||
const _ = require('lodash')
|
||||
const Promise = require('bluebird')
|
||||
const retry = require('bluebird-retry')
|
||||
const got = require('got')
|
||||
|
||||
const { seconds, minutes } = require('./utils')
|
||||
|
||||
const WORKFLOW_NAMES = [
|
||||
'darwin-arm64',
|
||||
'darwin-x64',
|
||||
'linux-arm64',
|
||||
// 'linux-x64', this is the workflow validating this check so leaved commented out
|
||||
'windows',
|
||||
'setup-workflow',
|
||||
]
|
||||
|
||||
const pipelineId = process.env.CIRCLE_PIPELINE_ID // pulled from <pipeline.id> circleci parameter
|
||||
|
||||
const getAuth = () => `${process.env.CIRCLE_TOKEN}:`
|
||||
|
||||
const verifyCI = () => {
|
||||
if (!process.env.CIRCLE_TOKEN) {
|
||||
console.error('Cannot find CIRCLE_TOKEN')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (!process.env.CIRCLE_PIPELINE_ID) {
|
||||
console.error('Cannot find CIRCLE_WORKFLOW_ID')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (process.env.CIRCLE_BRANCH !== 'develop') {
|
||||
console.error('Only move forward with the release when running on develop.')
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
const getWorkflows = async () => {
|
||||
const auth = getAuth()
|
||||
// typo at https://circleci.com/docs/2.0/api-intro/
|
||||
// to retrieve all jobs, the url is "/pipeline/:id/workflow"
|
||||
const url = `https://${auth}@circleci.com/api/v2/pipeline/${pipelineId}/workflow`
|
||||
const response = await got(url).json()
|
||||
|
||||
// returns something like
|
||||
// {
|
||||
// "items": [
|
||||
// {
|
||||
// "pipeline_id": "5034460f-c7c4-4c43-9457-de07e2029e7b",
|
||||
// "canceled_by": "026a6d28-c22e-4aab-a8b4-bd7131a8ea35",
|
||||
// "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
// "name": "build-and-test",
|
||||
// "project_slug": "gh/CircleCI-Public/api-preview-docs",
|
||||
// "errored_by": "c6e40f70-a80a-4ccc-af88-8d985a7bc622",
|
||||
// "tag": "setup",
|
||||
// "status": "success",
|
||||
// "started_by": "03987f6a-4c27-4dc1-b6ab-c7e83bb3e713",
|
||||
// "pipeline_number": "25",
|
||||
// "created_at": "2019-08-24T14:15:22Z",
|
||||
// "stopped_at": "2019-08-24T14:15:22Z"
|
||||
// }
|
||||
// ],
|
||||
// "next_page_token": "string"
|
||||
// }
|
||||
return response.items
|
||||
}
|
||||
|
||||
const waitForAllWorkflows = async () => {
|
||||
let workflows
|
||||
|
||||
try {
|
||||
workflows = await getWorkflows()
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
workflows.sort((a, b) => {
|
||||
const dateA = new Date(a.created_at)
|
||||
const dateB = new Date(b.created_at)
|
||||
|
||||
return dateB - dateA
|
||||
})
|
||||
|
||||
workflows = _.uniqBy(workflows, 'name')
|
||||
|
||||
_.remove(workflows, (w) => w.name === 'linux-x64') // this is the workflow that is running this job
|
||||
|
||||
console.log('workflows', workflows)
|
||||
|
||||
const missingWorkflows = WORKFLOW_NAMES.filter((w) => !_.find(workflows, { name: w }))
|
||||
|
||||
if (missingWorkflows.length) {
|
||||
console.error('The following', missingWorkflows.length, 'workflows are required to release and have not been started:\n -', missingWorkflows.join('\n - '))
|
||||
console.error('Failing early rather than wait for pipelines to finish.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
// determine workflow states
|
||||
// https://circleci.com/docs/workflows/#states
|
||||
|
||||
// in-progress workflows
|
||||
const runningWorkflows = _.filter(workflows, (w) => {
|
||||
return ['running', 'on hold'].includes(w.status)
|
||||
}).map((w) => w.name)
|
||||
|
||||
// failing workflows
|
||||
const failingWorkflows = _.filter(workflows, { status: 'failing' }).map((w) => w.name)
|
||||
|
||||
// failed workflows
|
||||
const failedWorkflows = _.filter(workflows, (w) => {
|
||||
return ['failed', 'canceled', 'not run', 'needs setup'].includes(w.status)
|
||||
}).map((w) => w.name)
|
||||
|
||||
if (_.intersection(WORKFLOW_NAMES, failingWorkflows).length) {
|
||||
console.log('failingWorkflows', failingWorkflows)
|
||||
|
||||
console.error('At least one workflow is failing, which has prevented the release from kicking off', failingWorkflows)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (_.intersection(WORKFLOW_NAMES, failedWorkflows).length) {
|
||||
console.log('failedWorkflows', failedWorkflows)
|
||||
|
||||
console.error('At least one workflow failed, which has prevented the release from kicking off', failedWorkflows)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const workflowsToWaitFor = _.intersection(WORKFLOW_NAMES, runningWorkflows)
|
||||
|
||||
if (!workflowsToWaitFor.length) {
|
||||
console.log('All workflows have finished and passed!')
|
||||
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
// logging something every time this runs will avoid CI timing out if there is no activity for 10 mins.
|
||||
console.log(`waiting for ${workflowsToWaitFor.length} workflows to finish:\n - `, workflowsToWaitFor.join('\n - '))
|
||||
|
||||
return Promise.reject(new Error('One or more workflows has not finished...'))
|
||||
}
|
||||
|
||||
const main = () => {
|
||||
verifyCI()
|
||||
|
||||
// https://github.com/demmer/bluebird-retry
|
||||
retry(waitForAllWorkflows.bind(null), {
|
||||
timeout: minutes(95), // max time for this job
|
||||
interval: seconds(90), // poll intervals
|
||||
max_interval: seconds(90),
|
||||
}).then(() => {
|
||||
console.log('all done')
|
||||
}, (err) => {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
|
||||
// execute main function if called from command line
|
||||
if (require.main === module) {
|
||||
main()
|
||||
}
|
||||
@@ -16187,7 +16187,7 @@ gopd@^1.0.1:
|
||||
dependencies:
|
||||
get-intrinsic "^1.1.3"
|
||||
|
||||
got@11.8.6, got@^11.7.0, got@^11.8.5:
|
||||
got@^11.7.0, got@^11.8.5:
|
||||
version "11.8.6"
|
||||
resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a"
|
||||
integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==
|
||||
|
||||
Reference in New Issue
Block a user