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.
This commit is contained in:
Wolfgang Walther
2025-08-19 15:35:01 +02:00
parent 9d4fb0c40f
commit 443f30f811
5 changed files with 89 additions and 16 deletions

View File

@@ -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 }}

View File

@@ -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: {}

View File

@@ -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

72
.github/workflows/test.yml vendored Normal file
View File

@@ -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 }}

View File

@@ -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