Repository navigation
Build DKMS modules against every kernel #1250
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
emirb
wants to merge
42
commits into
master
Choose a base branch
from
ci/dkms-gate
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
42 commits
Select commit
Hold shift + click to select a range
829c880
Build every DKMS module against every kernel's headers
emirb 6db25c5
Run the DKMS check on changes to the check itself
emirb 3473638
Check only what changes, and stop on any download, checksum or archiv…
emirb 894f85d
Run the DKMS check on every pull request build and before every promo…
emirb 5a57324
Build the Apple modules only against the Asahi kernel they run on
emirb dcc26b7
Check the DKMS packages Omarchy installs from Arch too
emirb f4f2647
Check a pull request only where it has to, and report on every one
emirb e233017
Close the ways a required DKMS status could pass without checking
emirb 730ec08
Never pass a pull request whose packages the check could not see
emirb e3f6cd3
Check a pull request's kernels and DKMS modules inside its build
emirb a234ebe
Name the DKMS decision job so the result test can evaluate it
emirb 23c10cf
Fan the DKMS check out, one leg per kernel and module
emirb ff1dc1b
Show the end of make.log when a DKMS build fails
emirb 7986079
Unpack a DKMS package whole, not only its sources
emirb 09de72f
Build DKMS modules with clang for a kernel built with clang
emirb 1d976d8
Name only the kernel release when installing a kernel's headers
emirb 0ac30d7
Leave linux-aurora out of the aarch64 nvidia-open-dkms legs
emirb 596a06d
Report a known-broken DKMS package instead of failing on it
emirb bddfc39
Decide each DKMS leg's outcome on the host and summarise a run
emirb f537d0d
Show the DKMS check as one check on a pull request
emirb ea6907c
Refuse a dkms-request with a trailing newline, and packages that are …
emirb 3e8f24b
Keep a pull request's package metadata from acting on the runner or t…
emirb 9e68ee4
Name apple-ib-drv-dkms as macbook12-spi-driver-dkms's replacement
emirb 56665ae
Plan no DKMS legs for a build that ships no packages
emirb fd35d7d
Key the DKMS check by commit, and refuse a fork that changes build-pr…
emirb 3840406
Decide a DKMS build's provenance from the build run, and fail closed
emirb ae46ad9
Refuse package file names makepkg would not produce
emirb 80fc61a
Accept a fork that branched before build-pr.yml existed
emirb d231581
Collect a reused artifact only from a build this check trusts
emirb 6603382
Fail the DKMS matrix when a package cannot be read
emirb 7e3ded5
Read every page of a reused artifact's candidates
emirb 3816654
Put more untrusted artifacts in front than one page holds
emirb ce8df1a
List spark-hwmon-dkms in the DKMS registry
emirb bb1da56
Read each ARM channel's own Arch snapshot in the DKMS check
emirb 8ee5f81
Keep the DKMS registry to the packages this repository publishes
emirb 907a061
Check a promotion on the target channel as the promotion leaves it
emirb e069d8f
Merge remote-tracking branch 'origin/master' into ci/dkms-gate
emirb 0b708e4
Fail a promotion's DKMS plan when the source database cannot be read
emirb 1deb16f
Stop a promotion when the channels moved after its DKMS check
emirb df6bda7
Build DKMS modules only against Omarchy's own kernels
emirb 5fb7b1b
Give the DKMS container the kernels and package base set outside it
emirb 7f070d1
Test the kernel scope with linux-aarch64 instead of linux-n1x
emirb File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,254 @@ | ||
| name: DKMS check | ||
|
|
||
| # Builds DKMS modules against kernel headers (dkms-matrix.yml, bin/check-dkms): | ||
| # - after every pull request build ("Build changed packages"), on what the | ||
| # build would publish: a new kernel against every module, Arch's included, | ||
| # and a new module against every kernel. The pull request gets one check, | ||
| # "DKMS check: 41/45 passed", whose summary has a row per kernel and module | ||
| # and links this run, where every leg is its own job; | ||
| # - daily, on every pair on edge that has not built at its versions yet: | ||
| # Arch updates the DKMS packages Omarchy installs from it (ci/dkms-packages | ||
| # repo=) on its own schedule; | ||
| # - by hand, for a whole channel, or for a channel as a promotion into it | ||
| # would leave it (rc with what differs on edge moved in): | ||
| # gh workflow run dkms-check.yml -R omacom/omarchy-pkgs -f channel=stable | ||
| # gh workflow run dkms-check.yml -R omacom/omarchy-pkgs -f channel=rc -f from=edge | ||
| # - by hand for a pull request, the same path as after its build: | ||
| # gh workflow run dkms-check.yml -R omacom/omarchy-pkgs -f pr=1250 | ||
| # From a branch (--ref) it runs that branch's check, which is how a change | ||
| # to the check itself is proven before it merges; -f all=true checks every | ||
| # pair on the channel with the pull request's packages in place. | ||
| # promote.yml calls dkms-matrix.yml itself, on what a promotion moves. | ||
| # | ||
| # Why workflow_run and not the pull request's own workflow: every job of a | ||
| # pull_request run is a check on the pull request, about 45 of them for a | ||
| # kernel. This run's jobs attach to master's head instead, and the pull | ||
| # request gets the one check this workflow writes through the Checks API. | ||
| # | ||
| # workflow_run runs master's copy of this file with a token that could write, | ||
| # so: the only jobs that may write (checks: write, to open and close that one | ||
| # check) never check out the repository or download anything; they pass the | ||
| # event's commit and run ids and the matrix's verdict to the API through jq, | ||
| # as data. The matrix itself is read-only and runs master's tooling; the pull | ||
| # request's build is data until a leg unpacks it in a throwaway container. | ||
|
|
||
| on: | ||
| workflow_run: | ||
| workflows: [Build changed packages] | ||
| types: [completed] | ||
| schedule: | ||
| - cron: "37 5 * * *" | ||
| workflow_dispatch: | ||
| inputs: | ||
| channel: | ||
| description: Channel whose kernels and DKMS packages to check | ||
| type: choice | ||
| options: [edge, rc, stable] | ||
| default: edge | ||
| from: | ||
| description: "A promotion's source: check the channel with what differs there moved in (empty: everything)" | ||
| required: false | ||
| default: "" | ||
| from_repos: | ||
| description: Only the DKMS packages from Arch's repositories, against every kernel | ||
| type: boolean | ||
| default: false | ||
| pr: | ||
| description: "A pull request: check what its newest green build ships, and report it there as one check" | ||
| required: false | ||
| default: "" | ||
| head_sha: | ||
| description: "The commit whose build to check (default: the pull request's head)" | ||
| required: false | ||
| default: "" | ||
| all: | ||
| description: With pr or head_sha, every pair on the channel, the build's packages in place | ||
| type: boolean | ||
| default: false | ||
|
|
||
| permissions: {} | ||
|
|
||
| # One run per commit at a time: a newer build of the same commit (a label | ||
| # starts one) replaces the check in flight, which closes as cancelled. Keyed by | ||
| # commit, so a build of an older commit that finishes late, or one this | ||
| # workflow ignores (failed, cancelled, not a pull request's), never cancels the | ||
| # check of the pull request's head. | ||
| concurrency: | ||
| group: >- | ||
| dkms-check-${{ github.event_name == 'workflow_run' | ||
| && (github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' | ||
| && github.event.workflow_run.path == '.github/workflows/build-pr.yml' | ||
| && format('sha-{0}', github.event.workflow_run.head_sha) || format('ignored-{0}', github.run_id)) | ||
| || ((inputs.pr || inputs.head_sha) && format('pr-{0}-{1}', inputs.pr, inputs.head_sha)) | ||
| || format('{0}-{1}-{2}-{3}', github.event_name, github.ref, inputs.channel || 'edge', inputs.from || 'all') }} | ||
| cancel-in-progress: ${{ (github.event_name == 'workflow_run' || inputs.pr || inputs.head_sha) && true || false }} | ||
|
|
||
| jobs: | ||
| # A pull request's build: which commit and run, and the check, opened as in | ||
| # progress so the pull request shows it while the legs build. A commit the | ||
| # pull request has moved past gets no check. The build's dkms-request is | ||
| # only as good as the build-pr.yml that wrote it, and a fork's pull request | ||
| # runs its own copy: a build from a fork whose build-pr.yml differs from | ||
| # its merge base's is refused, never checked. Any API error fails this job | ||
| # before a check opens, so it fails closed. | ||
| target: | ||
| name: open the check | ||
| if: >- | ||
| (github.event_name == 'workflow_run' && github.event.workflow_run.event == 'pull_request' | ||
| && github.event.workflow_run.conclusion == 'success' | ||
| && github.event.workflow_run.path == '.github/workflows/build-pr.yml') | ||
| || (github.event_name == 'workflow_dispatch' && (inputs.pr != '' || inputs.head_sha != '')) | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 5 | ||
| permissions: | ||
| checks: write | ||
| actions: read | ||
| pull-requests: read | ||
| outputs: | ||
| head_sha: ${{ steps.open.outputs.head_sha }} | ||
| build_run: ${{ steps.open.outputs.build_run }} | ||
| check_run: ${{ steps.open.outputs.check_run }} | ||
| refused: ${{ steps.open.outputs.refused }} | ||
| steps: | ||
| # No checkout: nothing from the repository, let alone a pull request, | ||
| # runs next to this token. | ||
| - name: Find the build and open its check | ||
| id: open | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| EVENT_SHA: ${{ github.event.workflow_run.head_sha }} | ||
| EVENT_RUN: ${{ github.event.workflow_run.id }} | ||
| HEAD_OWNER: ${{ github.event.workflow_run.head_repository.owner.login }} | ||
| HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }} | ||
| PR: ${{ inputs.pr }} | ||
| SHA: ${{ inputs.head_sha }} | ||
| DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} | ||
| URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | ||
| run: | | ||
| set -euo pipefail | ||
| pr=$PR refused="" | ||
| if [[ -n $EVENT_RUN ]]; then | ||
| sha=$EVENT_SHA run=$EVENT_RUN | ||
| # The event names no pull request for a fork's; find it by its | ||
| # head. One that has moved on to a newer commit gets no check. | ||
| pr=$(gh api -X GET "repos/$GITHUB_REPOSITORY/pulls" -f state=open -f head="$HEAD_OWNER:$HEAD_BRANCH" | | ||
| jq -r --arg sha "$sha" '[.[] | select(.head.sha == $sha)][0].number // empty') | ||
| if [[ -z $pr ]]; then | ||
| echo "no open pull request has $sha as its head; nothing to check" | ||
| exit 0 | ||
| fi | ||
| else | ||
| sha=$SHA | ||
| if [[ -n $PR ]]; then | ||
| if [[ ! $PR =~ ^[0-9]+$ ]]; then | ||
| echo "::error::pr must be a pull request number" | ||
| exit 1 | ||
| fi | ||
| [[ -n $sha ]] || sha=$(gh api "repos/$GITHUB_REPOSITORY/pulls/$PR" --jq .head.sha) | ||
| fi | ||
| if [[ ! $sha =~ ^[0-9a-f]{40}$ ]]; then | ||
| echo "::error::head_sha must be a full commit hash" | ||
| exit 1 | ||
| fi | ||
| # The newest green pull request build of that commit. | ||
| run=$(gh api "repos/$GITHUB_REPOSITORY/actions/workflows/build-pr.yml/runs?head_sha=$sha&event=pull_request&status=success&per_page=1" \ | ||
| --jq '.workflow_runs[0].id // empty') | ||
| if [[ -z $run ]]; then | ||
| echo "::error::$sha has no green pull request build to check" | ||
| exit 1 | ||
| fi | ||
| fi | ||
| # A fork's pull request builds with its own build-pr.yml, which | ||
| # writes the dkms-request this check reads. Whether this build's | ||
| # copy is the base's comes from the build run itself, in every mode. | ||
| build=$(gh api "repos/$GITHUB_REPOSITORY/actions/runs/$run") | ||
| if [[ $(jq -r '.head_sha' <<<"$build") != "$sha" || $(jq -r '.path' <<<"$build") != .github/workflows/build-pr.yml ]]; then | ||
| echo "::error::run $run is not the pull request build of $sha" | ||
| exit 1 | ||
| fi | ||
| # build-pr.yml's blob at a commit, "missing" where it has none (a | ||
| # fork that branched before it existed); any other error stops here. | ||
| blob() { | ||
| local out | ||
| if out=$(gh api "repos/$GITHUB_REPOSITORY/contents/.github/workflows/build-pr.yml?ref=$1" --jq .sha 2>&1); then | ||
| echo "$out" | ||
| elif [[ $out == *"(HTTP 404)"* ]]; then | ||
| echo missing | ||
| else | ||
| echo "::error::cannot read build-pr.yml at $1" >&2 | ||
| return 1 | ||
| fi | ||
| } | ||
| if [[ $(jq -r '.head_repository.full_name // ""' <<<"$build") != "$GITHUB_REPOSITORY" ]]; then | ||
| base=$(gh api "repos/$GITHUB_REPOSITORY/compare/${DEFAULT_BRANCH}...$sha" --jq .merge_base_commit.sha) | ||
| ours=$(blob "$base") | ||
| theirs=$(blob "$sha") | ||
| if [[ ! $ours =~ ^([0-9a-f]{40}|missing)$ || $theirs != "$ours" ]]; then | ||
| refused="Not checked: this build comes from a fork whose .github/workflows/build-pr.yml differs from its merge base's, and that file writes what this check reads. Land the workflow change in a pull request of its own first." | ||
| fi | ||
| fi | ||
| check=$(jq -n --arg sha "$sha" --arg url "$URL" '{ | ||
| name: "DKMS check", head_sha: $sha, status: "in_progress", details_url: $url, | ||
| output: {title: "Building DKMS modules against kernel headers", summary: "[Open the run, with every leg](\($url))"} | ||
| }' | gh api -X POST "repos/$GITHUB_REPOSITORY/check-runs" --input - --jq .id) | ||
| echo "check run $check on $sha, for build run $run${pr:+ of pull request #$pr}" | ||
| { | ||
| echo "head_sha=$sha" | ||
| echo "build_run=$run" | ||
| echo "check_run=$check" | ||
| echo "refused=$refused" | ||
| } >>"$GITHUB_OUTPUT" | ||
|
|
||
| dkms: | ||
| name: DKMS | ||
| needs: target | ||
| # After a build only for a pull request's open check; daily and by hand | ||
| # always. | ||
| if: >- | ||
| !cancelled() && ((needs.target.result == 'success' && needs.target.outputs.check_run != '' && needs.target.outputs.refused == '') | ||
| || (github.event_name != 'workflow_run' && needs.target.result == 'skipped')) | ||
| permissions: | ||
| contents: read | ||
| actions: read | ||
| uses: ./.github/workflows/dkms-matrix.yml | ||
| with: | ||
| channel: ${{ inputs.channel || 'edge' }} | ||
| from: ${{ inputs.from || '' }} | ||
| from_repos: ${{ inputs.from_repos == true }} | ||
| all: ${{ inputs.all == true }} | ||
| build_run: ${{ needs.target.outputs.build_run || '' }} | ||
| head_sha: ${{ needs.target.outputs.head_sha || '' }} | ||
|
|
||
| # Closes the check with the matrix's verdict. A matrix that stopped before | ||
| # its summary fails the check (or cancels it), never passes it. | ||
| report: | ||
| name: close the check | ||
| needs: [target, dkms] | ||
| if: always() && needs.target.result == 'success' && needs.target.outputs.check_run != '' | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 5 | ||
| permissions: | ||
| checks: write | ||
| steps: | ||
| - name: Close the check | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| CHECK: ${{ needs.target.outputs.check_run }} | ||
| REFUSED: ${{ needs.target.outputs.refused }} | ||
| RESULT: ${{ needs.dkms.result }} | ||
| CONCLUSION: ${{ needs.dkms.outputs.conclusion }} | ||
| TITLE: ${{ needs.dkms.outputs.title }} | ||
| SUMMARY: ${{ needs.dkms.outputs.summary }} | ||
| URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | ||
| run: | | ||
| set -euo pipefail | ||
| if [[ -n $REFUSED ]]; then | ||
| CONCLUSION=failure TITLE="Not checked" SUMMARY=$REFUSED | ||
| elif [[ $RESULT == cancelled ]]; then | ||
| CONCLUSION=cancelled TITLE="Cancelled" SUMMARY="A newer build's check replaced this one. [Open the run]($URL)" | ||
| elif [[ $CONCLUSION != success && $CONCLUSION != failure ]]; then | ||
| CONCLUSION=failure TITLE="The DKMS check did not finish ($RESULT)" SUMMARY="[Open the run]($URL)" | ||
| fi | ||
| jq -n --arg c "$CONCLUSION" --arg t "$TITLE" --arg s "$SUMMARY" --arg url "$URL" \ | ||
| '{status: "completed", conclusion: $c, details_url: $url, output: {title: $t, summary: $s}}' | | ||
| gh api -X PATCH "repos/$GITHUB_REPOSITORY/check-runs/$CHECK" --input - --jq '"\(.conclusion): \(.output.title) \(.html_url)"' | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.