ci: align the pipelines with the hand-written templates

Assisted-by: GLM 5.3 Flash
This commit is contained in:
2026-09-17 20:33:18 +02:00
parent 5fddfa704b
commit 288a64ccd2
3 changed files with 55 additions and 32 deletions
+6 -5
View File
@@ -1,8 +1,10 @@
# Race, Go. Dispatched by hand, and run as part of the release gates. # Race, Go. Dispatched by hand, and never a gate on a push or a tag: the release tag is
# cut only after `just gates` has already raced the tree, so this workflow is the
# explicit second opinion, not a step of the release.
# #
# The race detector roughly doubles both time and memory, which the shared runner box # The race detector roughly doubles both time and memory, which the shared runner box
# cannot afford on every push. Locally it belongs to `just gates`, which runs it once per # cannot afford on every push. Locally it belongs to `just gates`, which runs it once per
# task; here it is an explicit decision rather than a routine. # task; here it is a decision rather than a routine.
# #
# Every step is one command, so the step that fails is the gate that failed. # Every step is one command, so the step that fails is the gate that failed.
name: Race name: Race
@@ -11,7 +13,6 @@ on:
workflow_dispatch: workflow_dispatch:
env: env:
GOAMD64: v3
# One core: parallelism buys no speed here and costs memory the box does not have. # One core: parallelism buys no speed here and costs memory the box does not have.
GOFLAGS: -p=1 GOFLAGS: -p=1
GOMAXPROCS: "2" GOMAXPROCS: "2"
@@ -19,7 +20,7 @@ env:
jobs: jobs:
race: race:
runs-on: fedora runs-on: fedora
timeout-minutes: 45 timeout-minutes: 20
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v7
@@ -33,4 +34,4 @@ jobs:
run: dnf install -y gcc run: dnf install -y gcc
- name: Race - name: Race
run: go test -race -count=1 -timeout 30m ./... run: go test -race -count=1 -timeout 10m ./...
+28 -17
View File
@@ -1,13 +1,20 @@
# Release, Go binaries. Runs on version tags (v1.2.3) pushed to main. # Release, Go binaries. Runs on version tags (v1.2.3) pushed to main.
# #
# The module sits at the repository root: the toolchain records a version only for a root
# module, measured on go1.27.1, so a build of a module in a subdirectory reports (devel)
# even at its own <module>/vX.Y.Z tag and this workflow's smoke test can never pass for
# it. A Go repository is one module at the root.
#
# The version contract these steps implement is in the `release` skill, and its point is # The version contract these steps implement is in the `release` skill, and its point is
# that nothing is injected: the toolchain records the tag into the binary's build # that nothing is injected: the toolchain records the tag into the binary's build
# information, so the build simply has to happen at the tag, which the trigger guarantees. # information, so the build simply has to happen at the tag, which the trigger guarantees.
# #
# The gates run in their own job, once, before the matrix. Putting them inside the matrix # The gates run in their own job, once, before the matrix, minus the race detector: race
# would run the whole suite and the race detector once per target on the box that also hosts # never runs on a push path or a tag, and the local gate raced this tree before the tag
# the forge. Each job validates the tag for itself rather than passing a value between jobs, # was cut. Putting the gates inside the matrix would run the whole suite once per target
# so no workflow feature has to be trusted for the version to reach the file name. # on the box that also hosts the forge. Each job validates the tag for itself rather than
# passing a value between jobs, so no workflow feature has to be trusted for the version
# to reach the file name.
name: Release name: Release
on: on:
@@ -15,7 +22,6 @@ on:
tags: ["v*"] tags: ["v*"]
env: env:
GOAMD64: v3
# The box is shared with the forge, so parallelism is bounded on purpose. The gates job # The box is shared with the forge, so parallelism is bounded on purpose. The gates job
# needs it most; the build jobs inherit it for their parallel compilation. # needs it most; the build jobs inherit it for their parallel compilation.
GOFLAGS: -p=1 GOFLAGS: -p=1
@@ -24,7 +30,7 @@ env:
jobs: jobs:
gates: gates:
runs-on: fedora runs-on: fedora
timeout-minutes: 25 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v7
@@ -33,10 +39,10 @@ jobs:
go-version-file: go.mod go-version-file: go.mod
cache: true cache: true
- name: Install Perl and gcc - name: Install Perl
# Perl for the steps below, gcc for the race detector. Both are no-ops where the # Perl for the steps below. The install is a no-op where the package
# package is already present. # is already present.
run: dnf install -y perl gcc run: dnf install -y perl
- name: Validate the tag - name: Validate the tag
env: env:
@@ -70,7 +76,7 @@ jobs:
- name: Tests - name: Tests
# The same command as in test.yml, so the floor is the same number everywhere. # The same command as in test.yml, so the floor is the same number everywhere.
run: go test -count=1 -timeout 30m -coverprofile=coverage.out -coverpkg=./arch/...,./asm/...,./ast/...,./disasm/...,./format/...,./lexer/...,./lint/...,./lsp/...,./parser/...,./token/...,./verify/... ./... run: go test -count=1 -timeout 10m -coverprofile=coverage.out ./arch/... ./asm/... ./ast/... ./disasm/... ./format/... ./lexer/... ./lint/... ./lsp/... ./parser/... ./token/... ./verify/...
- name: Coverage floor - name: Coverage floor
run: | run: |
@@ -84,9 +90,6 @@ jobs:
exit($total < 80 ? 1 : 0); exit($total < 80 ? 1 : 0);
' '
- name: Race
run: go test -race -count=1 -timeout 30m ./...
build: build:
runs-on: fedora runs-on: fedora
timeout-minutes: 25 timeout-minutes: 25
@@ -94,9 +97,12 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
# Portable targets: amd64 (v3 baseline), arm64, loong64 and riscv64 on Linux. # Portable targets: amd64, arm64, loong64 and riscv64 on Linux, at the toolchain
# No 32-bit, no wasm, no macOS, no Windows. FreeBSD waits until verify/jit.go # default level. No 32-bit, no wasm, no macOS, no Windows. FreeBSD stays out until
# ports off syscall.Mprotect, which the freebsd build does not carry. # verify/jit.go ports off syscall.Mprotect: the Go syscall package defines no
# Mprotect for freebsd, and verify/jit.go:50 calls it to drop the write bit from
# the JIT mapping, so every freebsd target fails to build with "undefined:
# syscall.Mprotect" (verified for amd64, arm64 and riscv64 on go1.27.1).
include: include:
- goos: linux - goos: linux
goarch: amd64 goarch: amd64
@@ -182,6 +188,11 @@ jobs:
timeout-minutes: 15 timeout-minutes: 15
needs: build needs: build
permissions: permissions:
# contents: read is required for the checkout: a job that declares any
# permissions gets a token scoped to exactly those, and releases: write
# alone leaves the fetch with no read access, which Gitea answers with
# a 404 "Repository not found". Verified on the instance 2026-09-16.
contents: read
releases: write releases: write
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v7
+21 -10
View File
@@ -21,16 +21,22 @@ on:
branches: [development] branches: [development]
env: env:
# Portable baseline, x86-64-v3 minimum. Other GOARCH values ignore it.
GOAMD64: v3
# One core: parallelism buys no speed here and costs memory the box does not have. # One core: parallelism buys no speed here and costs memory the box does not have.
GOFLAGS: -p=1 GOFLAGS: -p=1
GOMAXPROCS: "2" GOMAXPROCS: "2"
# A superseded run of the same ref is cancelled instead of queueing behind one that
# no longer matters. Verified on Gitea 1.27.1 on 2026-09-17: a queued run whose ref
# moved on is cancelled before it ever reaches the runner, while a run already
# dispatched there runs to completion.
concurrency:
group: ${{ gitea.workflow }}-${{ gitea.ref }}
cancel-in-progress: true
jobs: jobs:
test: test:
runs-on: fedora runs-on: fedora
timeout-minutes: 20 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v7
@@ -45,6 +51,11 @@ jobs:
# no-op where it is already present; drop this step once verified on the box. # no-op where it is already present; drop this step once verified on the box.
run: dnf install -y perl run: dnf install -y perl
# The steps follow the `gates` order of the justfile contract: build, format,
# vet, test. The vet gate is go vet and go fix -diff, two steps here.
- name: Build
run: go build ./...
- name: Format - name: Format
run: | run: |
perl -e ' perl -e '
@@ -62,14 +73,14 @@ jobs:
# Exits non-zero when it has something to rewrite, so it needs no output capture. # Exits non-zero when it has something to rewrite, so it needs no output capture.
run: go fix -diff ./... run: go fix -diff ./...
- name: Build
run: go build ./...
- name: Tests - name: Tests
# The sweep is `packages` in the project's justfile and the floor is computed over # The suite must be fast: a push pipeline that cannot finish in a few minutes moves
# the same product packages as the justfile's `coverpkg`, so the number is the one # its heavy part behind a dispatch. The inner timeout matches the job's, so a
# `just test` reports locally. # hanging test reports its own goroutine dump rather than a silent job kill.
run: go test -count=1 -timeout 30m -coverprofile=coverage.out -coverpkg=./arch/...,./asm/...,./ast/...,./disasm/...,./format/...,./lexer/...,./lint/...,./lsp/...,./parser/...,./token/...,./verify/... ./... # The pattern is `packages` in the project's justfile: the logic packages, since a
# thin cmd/ would drag the total under the floor. release.yml runs the same
# command, so the floor is the same number everywhere.
run: go test -count=1 -timeout 10m -coverprofile=coverage.out ./arch/... ./asm/... ./ast/... ./disasm/... ./format/... ./lexer/... ./lint/... ./lsp/... ./parser/... ./token/... ./verify/...
- name: Coverage floor - name: Coverage floor
run: | run: |