Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions .github/workflows/actionlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,39 @@ on:
paths:
- ".github/workflows/**"

concurrency:
group: actionlint-${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
actionlint:
name: Lint workflows
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
env:
# Bump both values together; the checksum is in the release's
# actionlint_<version>_checksums.txt.
ACTIONLINT_VERSION: 1.7.12
ACTIONLINT_SHA256: 8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8
steps:
- name: Check out repository
- name: Check out workflows
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
sparse-checkout: .github

# The prebuilt release binary replaces the rhysd/actionlint Docker
# action, which rebuilt its image on every run. The runner image
# already provides shellcheck, which actionlint uses for `run:` scripts.
- name: Install actionlint
run: |
set -euo pipefail
archive="$RUNNER_TEMP/actionlint.tar.gz"
curl -fsSL --retry 3 -o "$archive" \
"https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz"
echo "${ACTIONLINT_SHA256} ${archive}" | sha256sum --check --strict
tar -xzf "$archive" -C "$RUNNER_TEMP" actionlint

- name: Run actionlint
uses: rhysd/actionlint@914e7df21a07ef503a81201c76d2b11c789d3fca # v1.7.12
run: '"$RUNNER_TEMP/actionlint" -color'
6 changes: 6 additions & 0 deletions .github/workflows/rust-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,16 @@ on:
required: false
type: boolean
default: true
skip:
description: Skip the job, for a change that touches no code; a skipped job still reports its check name as passing
required: false
type: boolean
default: false

jobs:
rust-quality:
name: Quality
if: ${{ !inputs.skip }}
runs-on: ${{ inputs.runs-on }}
timeout-minutes: ${{ inputs.timeout-minutes }}
permissions:
Expand Down
40 changes: 40 additions & 0 deletions docs/ci-platform.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,43 @@ release.
Rust quality cache policy follows `docs/rust-ci.md`: compatible jobs restore one
stable family, only successful `main` quality runs save it, failed jobs do not
save it, and release/tag workflows do not use the quality cache.

## Run speed

These rules keep a CI run short without removing a check.

- **Cancel superseded pull request runs only.** Give the CI workflow
`concurrency.group: ci-${{ github.event.pull_request.number || github.sha }}`
and `cancel-in-progress: ${{ github.event_name == 'pull_request' }}`. A push
to `main` gets a unique group, so every `main` commit keeps a complete run;
the release gate depends on that. A workflow that also reacts to title or
label events adds a separate group suffix for them, so they cannot cancel a
running suite.
- **Filter documentation-only changes inside the workflow, not with `on.paths`.**
A workflow skipped by `paths` or `paths-ignore` never reports its checks, and
a required check that never reports blocks the merge. A `changes` job built on
`dorny/paths-filter` with `predicate-quantifier: every` computes `code`;
callers pass `skip: ${{ needs.changes.outputs.code != 'true' }}` to
`rust-quality.yml` or put `if: needs.changes.outputs.code == 'true'` on their
own jobs. A skipped job reports its check name as skipped, which counts as
passing for a required check. The release gate accepts only `success`, so it
must never depend on a check that a release commit can skip: a release commit
changes `Cargo.toml`, which is code. A repository with no required check may
filter with `paths-ignore` instead.
- **Do not chain jobs that exchange no data.** Drop a `needs` that only orders
jobs. Keep `needs` for artifacts and outputs, and for the aggregate job.
- **Count jobs.** A free organization runs 20 jobs at once, and 5 of them on
macOS. A run that starts more jobs than that queues the rest, so merge many
small jobs into one job with a loop, or into a few shards.
- **Put checks that do not depend on the operating system on Ubuntu.** Use macOS
and Windows only for installers, packaging, and platform runtime behavior.
- **Prefer prebuilt tools.** Download a checksum-pinned release binary, or use an
install action that downloads one. Do not run `cargo install` or `go install`
in a job. `actionlint.yml` installs the release binary and verifies its
SHA-256.
- **Keep `cargo test`.** `cargo nextest` was measured on the hosted runners and
was slower for opy-rs (52 s to 149 s) and athena (40 s to 65 s), because it
starts one process per test.
- **Optimize a dependency that dominates a debug test.** A
`[profile.dev.package.<crate>]` `opt-level` entry costs one cached compile and
can remove minutes of test time; Wright sets one for `workshop-rs`.
Loading