Repository navigation
198 lines (189 loc) · 9.71 KB
/
Copy pathci.yml
File metadata and controls
198 lines (189 loc) · 9.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
name: CI
on:
push:
branches: [main, develop] # develop is the integration branch; main is the release branch
pull_request:
workflow_dispatch: # dispatched onto bot branches (xmrig-bump #225) whose token-created PRs can't self-trigger
# Least privilege: every job here only reads the repo to lint/test/build — nothing publishes or
# writes. Set the floor once at the top so all jobs inherit a read-only GITHUB_TOKEN (zizmor:
# excessive-permissions).
permissions:
contents: read
jobs:
lint-yaml:
name: Lint (yamllint)
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false # zizmor: artipacked
# pipx is preinstalled on ubuntu-24.04 (same path as diff-cover/zizmor); pin the version so the
# ruleset can't drift with the runner image.
- name: Install pinned yamllint
run: pipx install "yamllint==1.38.0"
# Via `make lint-yaml` so the file set + .yamllint config live in one place and can't drift from local.
- name: Run yamllint (make lint-yaml)
run: make lint-yaml
# actionlint checks the workflows for CORRECTNESS (bad needs/refs, invalid runners, shell bugs
# in run blocks); zizmor in security.yml audits them for security. Pinned + checksum-verified,
# same discipline as the shellcheck/gitleaks installs.
- name: Install pinned actionlint
env:
ACTIONLINT_VERSION: "1.7.12"
ACTIONLINT_SHA256: "8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8"
run: |
set -euo pipefail
tarball="actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz"
curl -fsSL "https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/${tarball}" -o "$tarball"
echo "${ACTIONLINT_SHA256} ${tarball}" | sha256sum -c -
tar -xzf "$tarball" actionlint
sudo install actionlint /usr/local/bin/
actionlint --version
- name: Run actionlint (make lint-actions)
run: make lint-actions
lint-md:
name: Lint (markdownlint)
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false # zizmor: artipacked
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1
with:
node-version: "22"
package-manager-cache: false
- name: Run markdownlint (make lint-md)
run: make lint-md
lint:
name: Lint (shellcheck + shfmt)
runs-on: ubuntu-24.04
env:
SHELLCHECK_VERSION: "0.11.0"
SHELLCHECK_SHA256: "8c3be12b05d5c177a04c29e3c78ce89ac86f1595681cab149b65b97c4e227198"
SHFMT_VERSION: "3.14.1"
SHFMT_SHA256: "76e77641faa025814b77f153b29796b8e6fa2fca03e0c76a691608b86c7ea7bf"
# The file-budget gate's "ceilings only go down" half needs origin/develop to diff the budget
# against. Without this it would SKIP that half and still exit 0 — a green that proves less
# than it looks like it does — so here it is fatal instead (#407).
FILE_BUDGET_REQUIRE_BASE: "1"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false # no pushes from CI; don't leave the token in .git/config (zizmor: artipacked)
# Full history so origin/develop resolves for the file-budget gate above; the default
# shallow fetch gives the PR ref only. Paired with FILE_BUDGET_REQUIRE_BASE, so if this
# line is ever dropped the job REDS instead of quietly running half the gate.
fetch-depth: 0
# Install PINNED, checksum-verified shellcheck + shfmt instead of the runner's preinstalled
# builds, so lint/format results are reproducible and don't drift with the runner image (#6).
# Downloaded straight from the upstream releases — no `apt-get update`, avoiding the mirror
# flakiness pithead hit in its #64.
- name: Install pinned ShellCheck
run: |
set -euo pipefail
# Unpack in RUNNER_TEMP, not the workspace: the file-budget gate measures untracked,
# non-gitignored files too (that is how a new file is caught before `git add`), and an
# extracted toolchain in the repo root reads as a 674-line source file it must budget.
cd "$RUNNER_TEMP"
tarball="shellcheck-v${SHELLCHECK_VERSION}.linux.x86_64.tar.xz"
curl -fsSL "https://github.com/koalaman/shellcheck/releases/download/v${SHELLCHECK_VERSION}/${tarball}" -o "$tarball"
echo "${SHELLCHECK_SHA256} ${tarball}" | sha256sum -c -
tar -xJf "$tarball"
sudo install "shellcheck-v${SHELLCHECK_VERSION}/shellcheck" /usr/local/bin/shellcheck
shellcheck --version
- name: Install pinned shfmt
run: |
set -euo pipefail
cd "$RUNNER_TEMP" # same reason as ShellCheck above — keep the download out of the workspace
curl -fsSL "https://github.com/mvdan/sh/releases/download/v${SHFMT_VERSION}/shfmt_v${SHFMT_VERSION}_linux_amd64" -o shfmt
echo "${SHFMT_SHA256} shfmt" | sha256sum -c -
sudo install shfmt /usr/local/bin/shfmt
shfmt --version
# Lint via `make lint` so the file list lives in one place (the Makefile's SHELL_FILES) and CI
# can't drift out of sync with local `make lint` — e.g. a newly added tests/*.sh going unchecked.
- name: Run shellcheck + shfmt (make lint)
run: make lint
test:
name: Test suite
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false # zizmor: artipacked
# Ubuntu is RigForge's supported target. macOS is deprecated (#493): no Mac runner, no native
# macOS job below. The suite still exercises the Darwin code paths here via stubs (OS_TYPE=Darwin
# + faked sysctl/launchctl) — kept deliberately, since it's the only remaining regression
# coverage for the deprecated-but-still-working Darwin paths and costs nothing extra to run on
# this Ubuntu job. It proves logic only, not real macOS behavior (BSD sed/stat/date, real
# launchd) — contributors on macOS can still run `make test` locally for that.
- name: Run test suite
run: make test-suite
stock-home:
name: Stock home setup (${{ matrix.label }})
runs-on: ubuntu-24.04
timeout-minutes: 35
strategy:
fail-fast: false
matrix:
include:
- label: historical
revision: b2d4c3d9ca1da74d0e6d5ccce772d401acc8be03
expect: broken
- label: current
revision: HEAD
expect: working
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
fetch-depth: 0
- name: Verify native prerequisites
run: |
command -v git curl
systemctl --version
- name: Run documented setup beneath a private home
env:
TEST_REVISION: ${{ matrix.revision }}
TEST_EXPECTATION: ${{ matrix.expect }}
run: timeout 1800 bash tests/test-stock-home.sh "$TEST_REVISION" "$TEST_EXPECTATION"
e2e:
name: End-to-end (Docker)
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false # zizmor: artipacked
# Runs the real script end-to-end inside a disposable Ubuntu container (RigForge's documented
# Linux target), exercising the genuine Linux deploy path and /etc idempotency with real tools.
# linux.sh runs TWO passes (a fresh container each): the standard deploy, then
# RIGFORGE_APPLIANCE=1 (#348) proving the appliance contracts against a real /etc — units in
# /run/systemd/system, no package installs, no fstab/limits/logrotate writes, --runtime enables.
- name: Run end-to-end suite
run: make test-e2e
coverage:
name: Coverage (kcov + diff-cover)
runs-on: ubuntu-24.04
env:
# Pin diff-cover (the patch-coverage gate); kcov + jq are pinned inside tests/coverage.sh.
DIFF_COVER_VERSION: "10.6.0"
PATCH_COVERAGE_MIN: "90" # new/changed lines in rigforge.sh + util must be this % covered
# Diff the PR against the branch it targets (develop or main). On a push, github.base_ref is empty,
# so fall back to the pushed branch itself — that's an empty diff that trivially passes.
BASE_REF: ${{ github.base_ref || github.ref_name }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0 # diff-cover needs history to diff the PR against its base branch
persist-credentials: false # the fetch below is read-only on a public repo (zizmor: artipacked)
- name: Fetch base branch for diff-cover
run: git fetch --no-tags origin "$BASE_REF"
# Runs tests/run.sh under a digest-pinned kcov image, reports rigforge.sh + util/proposed-grub.sh
# coverage, and fails if the total drops below the committed floor (tests/coverage-floor.txt).
- name: Measure coverage (kcov) + enforce the total floor
run: make coverage
# Patch coverage is the real lever: it requires NEW/CHANGED lines to be tested, which is what keeps
# coverage from rotting. Self-contained (no Codecov) — reads the Cobertura report from kcov.
- name: Install pinned diff-cover
run: pipx install "diff-cover==${DIFF_COVER_VERSION}"
- name: Enforce patch coverage on changed lines
run: diff-cover coverage/cobertura.xml --compare-branch="origin/$BASE_REF" --fail-under="${PATCH_COVERAGE_MIN}"