diff --git a/.github/workflows/auto-resume-ci.yml b/.github/workflows/auto-resume-ci.yml new file mode 100644 index 00000000000000..7caa7f4b39a6cb --- /dev/null +++ b/.github/workflows/auto-resume-ci.yml @@ -0,0 +1,70 @@ +name: Auto Start CI + +on: + schedule: + # Runs every five minutes (fastest the scheduler can run). Five minutes is + # optimistic, it can take longer to run. + # To understand why `schedule` is used instead of other events, refer to + # ./doc/contributing/commit-queue.md + - cron: '*/5 * * * *' + +concurrency: ${{ github.workflow }} + +env: + NODE_VERSION: lts/* + +permissions: + contents: read + +jobs: + get-prs-for-ci: + permissions: + pull-requests: read + if: github.repository == 'nodejs/node' + runs-on: ubuntu-latest + outputs: + numbers: ${{ steps.get_prs_for_ci.outputs.numbers }} + steps: + - name: Get Pull Requests + id: get_prs_for_ci + run: > + gh pr list \ + --repo ${{ github.repository }} \ + --label 'resume-ci' \ + --json 'number' \ + -t '::set-output name=numbers::{{ range . }}{{ .number }} {{ end }}' \ + --limit 100 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + start-ci: + permissions: + contents: read + pull-requests: write + needs: get-prs-for-ci + if: needs.get-prs-for-ci.outputs.numbers != '' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + persist-credentials: false + + - name: Install Node.js + uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Install node-core-utils + run: npm install -g node-core-utils + + - name: Setup node-core-utils + run: | + ncu-config set username ${{ secrets.JENKINS_USER }} + ncu-config set token none + ncu-config set jenkins_token ${{ secrets.JENKINS_TOKEN }} + ncu-config set owner "${{ github.repository_owner }}" + ncu-config set repo "$(echo ${{ github.repository }} | cut -d/ -f2)" + + - name: Resume the CI Runs + run: ./tools/actions/resume-ci.sh ${{ needs.get-prs-for-ci.outputs.numbers }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/doc/contributing/commit-queue.md b/doc/contributing/commit-queue.md index 4730d0889e99aa..d7b3dff91889db 100644 --- a/doc/contributing/commit-queue.md +++ b/doc/contributing/commit-queue.md @@ -20,7 +20,7 @@ From a high-level, the Commit Queue works as follow: 1. Collaborators will add `commit-queue` label to pull requests ready to land 2. Every five minutes the queue will do the following for each pull request with the label: - 1. Check if the PR also has a `request-ci` label (if it has, skip this PR + 1. Check if the PR also has a `request-ci` or `resume-ci` label (if it has, skip this PR since it's pending a CI run) 2. Check if the last Jenkins CI is finished running (if it is not, skip this PR) @@ -98,7 +98,7 @@ that into a list of PR ids we can pass as arguments to The script will iterate over the pull requests. `ncu-ci` is used to check if the last CI is still pending, and calls to the GitHub API are used to check if -the PR is waiting for CI to start (`request-ci` label). The PR is skipped if CI +the PR is waiting for CI to start (`request-ci` pr `resume-ci` label). The PR is skipped if CI is pending. No other CI validation is done here since `git node land` will fail if the last CI failed. diff --git a/tools/actions/commit-queue.sh b/tools/actions/commit-queue.sh index 0df819e47ee825..2923b5ffd4bd26 100755 --- a/tools/actions/commit-queue.sh +++ b/tools/actions/commit-queue.sh @@ -38,6 +38,10 @@ for pr in "$@"; do echo "pr ${pr} skipped, waiting for CI to start" continue fi + if jq -e 'map(.name) | index("resume-ci")' < labels.json; then + echo "pr ${pr} skipped, waiting for CI to start" + continue + fi # Skip PR if CI is still running if gh pr checks "$pr" | grep -q "\spending\s"; then diff --git a/tools/actions/resume-ci.sh b/tools/actions/resume-ci.sh new file mode 100755 index 00000000000000..e3bfe6292fc23a --- /dev/null +++ b/tools/actions/resume-ci.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +set -xe + +RESUME_CI_LABEL="resume-ci" +RESUME_CI_FAILED_LABEL="resume-ci-failed" + +for pr in "$@"; do + gh pr edit "$pr" --remove-label "$RESUME_CI_LABEL" + + ci_started=yes + rm -f output; + ncu-ci resume "$pr" >output 2>&1 || ci_started=no + cat output + + if [ "$ci_started" = "no" ]; then + # Do we need to reset? + gh pr edit "$pr" --add-label "$RESUME_CI_FAILED_LABEL" + + jq -n --arg content "
Couldn't resume CI
$(cat output || true)
" > output.json + + gh pr comment "$pr" --body-file output.json + + rm output.json; + fi +done;