From 9bea5d3844ae5c2b8d2cc88ff1c0fc111ca0ad5d Mon Sep 17 00:00:00 2001 From: Wolfgang Walther Date: Tue, 19 Aug 2025 15:35:01 +0200 Subject: [PATCH] workflows/test: init This workflow runs the PR and Push workflow files on a `pull_request` trigger. The intent is to test changes to the workflow files immediately. Previously, these were run directly from the respective workflow files. The new approach allows us to move the logic to run this only when workflow files changed from the pull_request trigger into a job. This has the advantage that older jobs are cleaned up, when the PR changes from a state of "workflow files changed" to "no workflow files changed". This can happen when changing a PR's base from staging to master, in which case changes from master would temporarily appear in the PR as changes. When these include changes to workflow files, this would trigger the PR workflow via `pull_request`. Once the base is changed, the PR is closed and re-opened, so CI runs again - but since it's on the same commit and the new run doesn't trigger `pull_request`, the results of the previous run are still kept and displayed. These results may include cancelled or failed jobs, which are impossible to recover from without another force-push. Checking this condition at run-time is only possible, because we move it into a separate workflow, turning the `pr.yml` workflow into a re-usable workflow. This will make sure to skip the whole workflow at once, when no change was detected, which will prevent the "no PR failures" job from appearing as skipped - which would imply "success" and make the PR mergeable immediately. Instead the "no PR failures" job is not shown at all for this trigger, which is generally what we want. Do the same for `push.yml` for consistency. (cherry picked from commit 443f30f811f20431079e0321fb14d6e7460f5dac) --- .github/workflows/pr.yml | 21 +++++----- .github/workflows/push.yml | 8 ++-- .github/workflows/reviewers.yml | 2 +- .github/workflows/test.yml | 72 +++++++++++++++++++++++++++++++++ ci/github-script/commits.js | 2 +- 5 files changed, 89 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 82fdd1f3aa82..a7720df7226a 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -1,17 +1,18 @@ name: PR on: - pull_request: - paths: - - .github/actions/checkout/action.yml - - .github/workflows/build.yml - - .github/workflows/check.yml - - .github/workflows/eval.yml - - .github/workflows/lint.yml - - .github/workflows/pr.yml - - .github/workflows/labels.yml - - .github/workflows/reviewers.yml # needs eval results from the same event type pull_request_target: + workflow_call: + secrets: + CACHIX_AUTH_TOKEN: + required: true + NIXPKGS_CI_APP_PRIVATE_KEY: + required: true + OWNER_APP_PRIVATE_KEY: + # The Test workflow should not actually request reviews from owners. + required: false + OWNER_RO_APP_PRIVATE_KEY: + required: true concurrency: group: pr-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }} diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index e980dbe42951..bb372f196b83 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -1,10 +1,6 @@ name: Push on: - pull_request: - paths: - - .github/workflows/push.yml - # eval is tested via pr.yml push: # Keep this synced with ci/request-reviews/dev-branches.txt branches: @@ -13,6 +9,10 @@ on: - release-* - staging-* - haskell-updates + workflow_call: + secrets: + CACHIX_AUTH_TOKEN: + required: true permissions: {} diff --git a/.github/workflows/reviewers.yml b/.github/workflows/reviewers.yml index 5c2acb55a8de..9b3de2338553 100644 --- a/.github/workflows/reviewers.yml +++ b/.github/workflows/reviewers.yml @@ -95,7 +95,7 @@ jobs: const run_id = (await github.rest.actions.listWorkflowRuns({ owner: context.repo.owner, repo: context.repo.repo, - workflow_id: 'pr.yml', + workflow_id: context.eventName === 'pull_request' ? 'test.yml' : 'pr.yml', event: context.eventName, head_sha: context.payload.pull_request.head.sha })).data.workflow_runs[0].id diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000000..a90c13c3f738 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,72 @@ +name: Test + +on: + pull_request: + +concurrency: + group: test-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }} + cancel-in-progress: true + +permissions: {} + +jobs: + prepare: + runs-on: ubuntu-24.04-arm + outputs: + pr: ${{ steps.files.outputs.pr }} + push: ${{ steps.files.outputs.push }} + steps: + - name: Determine changed files + id: files + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + with: + script: | + const files = (await github.paginate(github.rest.pulls.listFiles, { + ...context.repo, + pull_number: context.payload.pull_request.number, + per_page: 100, + })).map(file => file.filename) + + if (files.some(file => [ + '.github/actions/checkout/action.yml', + '.github/workflows/build.yml', + '.github/workflows/check.yml', + '.github/workflows/eval.yml', + '.github/workflows/labels.yml', + '.github/workflows/lint.yml', + '.github/workflows/pr.yml', + '.github/workflows/reviewers.yml', + '.github/workflows/test.yml', + ].includes(file))) core.setOutput('pr', true) + + if (files.some(file => [ + '.github/workflows/eval.yml', + '.github/workflows/push.yml', + '.github/workflows/test.yml', + ].includes(file))) core.setOutput('push', true) + + pr: + if: needs.prepare.outputs.pr + name: PR + needs: [prepare] + uses: ./.github/workflows/pr.yml + # Those are not actually used on pull_request, but will throw an error if not set. + permissions: + issues: write + pull-requests: write + statuses: write + secrets: + CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} + NIXPKGS_CI_APP_PRIVATE_KEY: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }} + OWNER_RO_APP_PRIVATE_KEY: ${{ secrets.OWNER_RO_APP_PRIVATE_KEY }} + + push: + if: needs.prepare.outputs.push + name: Push + needs: [prepare] + uses: ./.github/workflows/push.yml + # Those are not actually used on push, but will throw an error if not set. + permissions: + statuses: write + secrets: + CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} diff --git a/ci/github-script/commits.js b/ci/github-script/commits.js index 1391779e79ff..242abda88658 100644 --- a/ci/github-script/commits.js +++ b/ci/github-script/commits.js @@ -16,7 +16,7 @@ module.exports = async ({ github, context, core, dry }) => { run_id: context.runId, per_page: 100, }) - ).find(({ name }) => name === 'Check / cherry-pick').html_url + + ).find(({ name }) => name.endsWith('Check / cherry-pick')).html_url + '?pr=' + pull_number