workflows/{pr,push}: init

Those two workflows bundle all the main jobs in two event-specific
wrapper workflows. This enables us to do two things later on:
- Synchronize the merge commits between most of the jobs run in a PR.
- Create a single "required" job to be targeted by GitHub's "required
status checks to pass" feature.
This commit is contained in:
Wolfgang Walther
2025-06-08 12:12:06 +02:00
parent 485f3b2aaa
commit 959eed1f2a
9 changed files with 96 additions and 48 deletions

View File

@@ -29,7 +29,7 @@ Thus, it is important how to construct the group keys:
- We don't want workflows of different Pull Requests to cancel each other, so we include `github.event.pull_request.number`. The [GitHub docs](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/control-the-concurrency-of-workflows-and-jobs#example-using-a-fallback-value) show using `github.head_ref` for this purpose, but this doesn't work well with forks: Different users could have the same head branch name in their forks and run CI for their PRs at the same time.
- Sometimes, there is no `pull_request.number`. That's the case for `push` or `workflow_run` events. To ensure non-PR runs are never cancelled, we add a fallback of `github.run_id`. This is a unique value for each workflow run.
- Sometimes, there is no `pull_request.number`. To ensure non-PR runs are never cancelled, we add a fallback of `github.run_id`. This is a unique value for each workflow run.
- Of course, we run multiple workflows at the same time, so we add `github.workflow` to the key. Otherwise workflows would cancel each other.

View File

@@ -1,14 +1,10 @@
name: Build
on:
pull_request:
paths:
- .github/workflows/build.yml
pull_request_target:
concurrency:
group: build-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
workflow_call:
secrets:
CACHIX_AUTH_TOKEN:
required: true
permissions: {}

View File

@@ -1,14 +1,7 @@
name: Check
on:
pull_request:
paths:
- .github/workflows/check.yml
pull_request_target:
concurrency:
group: check-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
workflow_call:
permissions: {}

View File

@@ -1,24 +1,10 @@
name: Eval
on:
pull_request:
paths:
- .github/workflows/eval.yml
- .github/workflows/reviewers.yml # needs eval results from the same event type
pull_request_target:
push:
# Keep this synced with ci/request-reviews/dev-branches.txt
branches:
- master
- staging
- release-*
- staging-*
- haskell-updates
- python-updates
concurrency:
group: eval-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
workflow_call:
secrets:
OWNER_APP_PRIVATE_KEY:
required: false
permissions: {}
@@ -109,12 +95,12 @@ jobs:
run_id = (await github.rest.actions.listWorkflowRuns({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'eval.yml',
workflow_id: 'push.yml',
event: 'push',
head_sha: targetSha
})).data.workflow_runs[0].id
} catch {
throw new Error(`Could not find an eval.yml workflow run for ${targetSha}.`)
throw new Error(`Could not find an push.yml workflow run for ${targetSha}.`)
}
core.setOutput('targetRunId', run_id)
@@ -265,4 +251,5 @@ jobs:
needs: [prepare, outpaths]
if: needs.prepare.outputs.targetSha
uses: ./.github/workflows/reviewers.yml
secrets: inherit
secrets:
OWNER_APP_PRIVATE_KEY: ${{ secrets.OWNER_APP_PRIVATE_KEY }}

View File

@@ -147,7 +147,7 @@ jobs:
const run_id = (await github.rest.actions.listWorkflowRuns({
...context.repo,
workflow_id: 'eval.yml',
workflow_id: 'pr.yml',
event: 'pull_request_target',
// For PR events, the workflow run is still in progress with this job itself.
status: prEventCondition ? 'in_progress' : 'success',

View File

@@ -1,14 +1,7 @@
name: Lint
on:
pull_request:
paths:
- .github/workflows/lint.yml
pull_request_target:
concurrency:
group: lint-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
workflow_call:
permissions: {}

47
.github/workflows/pr.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
name: PR
on:
pull_request:
paths:
- .github/workflows/build.yml
- .github/workflows/check.yml
- .github/workflows/eval.yml
- .github/workflows/lint.yml
- .github/workflows/pr.yml
- .github/workflows/reviewers.yml # needs eval results from the same event type
pull_request_target:
concurrency:
group: pr-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
permissions: {}
jobs:
check:
name: Check
uses: ./.github/workflows/check.yml
permissions:
# cherry-picks
pull-requests: write
lint:
name: Lint
uses: ./.github/workflows/lint.yml
eval:
name: Eval
uses: ./.github/workflows/eval.yml
permissions:
# compare
issues: write
pull-requests: write
statuses: write
secrets:
OWNER_APP_PRIVATE_KEY: ${{ secrets.OWNER_APP_PRIVATE_KEY }}
build:
name: Build
uses: ./.github/workflows/build.yml
secrets:
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}

29
.github/workflows/push.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
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:
- master
- staging
- release-*
- staging-*
- haskell-updates
- python-updates
permissions: {}
jobs:
eval:
name: Eval
uses: ./.github/workflows/eval.yml
# Those are not actually used on push, but will throw an error if not set.
permissions:
# compare
issues: write
pull-requests: write
statuses: write

View File

@@ -10,6 +10,9 @@ on:
pull_request_target:
types: [ready_for_review]
workflow_call:
secrets:
OWNER_APP_PRIVATE_KEY:
required: true
concurrency:
group: reviewers-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }}
@@ -63,7 +66,7 @@ jobs:
const run_id = (await github.rest.actions.listWorkflowRuns({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'eval.yml',
workflow_id: 'pr.yml',
event: context.eventName,
head_sha: context.payload.pull_request.head.sha
})).data.workflow_runs[0].id