Repository navigation
164 lines (141 loc) · 7.41 KB
/
Copy pathsupply-chain.yml
File metadata and controls
164 lines (141 loc) · 7.41 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
name: supply-chain
permissions:
contents: read
env:
CARGO_HOME: /home/runner/.cargo
RUSTUP_HOME: /home/runner/.rustup
on:
pull_request:
push:
branches: [main]
schedule:
- cron: "0 3 * * 1"
workflow_dispatch:
jobs:
supply-chain:
name: Supply chain audit
runs-on: [self-hosted, preloop-cpane]
timeout-minutes: 30
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# Full history: the policy guard diffs the merge base, which a
# shallow checkout cannot reach.
fetch-depth: 0
- name: Drop PR-shipped cargo config
run: rm -f .cargo/config .cargo/config.toml
# The guard is a script, so its cases are a script's cases: run them
# here, where a change to the guard is exercised before the step below
# decides anything. This is the only CI entry point for the suite --
# `justfile` and `ci.yml` are outside the policy set, so a recipe or a
# ci.yml step has to arrive in its own (non-policy) PR.
- name: Guard policy files (self-test)
run: bash supply-chain/tests/guard-policy-files.test.sh
- name: Guard policy files
if: github.event_name == 'pull_request'
run: |
set -euo pipefail
base="${{ github.event.pull_request.base.sha }}"
pr_head="${{ github.event.pull_request.head.sha }}"
# Ensure base and PR head are fetched for diff (fail closed on
# network/fetch error)
git fetch --no-tags origin "$base" "$pr_head"
# The script owns the rule, so a contributor can run it locally:
# supply-chain/guard-policy-files.sh <base> <head>
# It diffs the merge base against the PR head, not the merge-checkout
# HEAD: HEAD is a synthetic merge commit, and identical changes on
# both sides would cancel out of the diff and hide a policy touch.
supply-chain/guard-policy-files.sh "$base" "$pr_head"
- uses: dtolnay/rust-toolchain@b725eda525362e7cf34af9a7243cac1e3f01a7ec # stable
with:
toolchain: "1.99"
- uses: taiki-e/install-action@f7e5d7c961414b23f5b25b2da9294395d08513ad # v2.87.26
with:
tool: cargo-vet@0.10.1,cargo-audit@0.22.2,cargo-deny@0.20.2
- name: cargo vet
run: cargo vet --locked
- name: cargo audit
run: cargo audit
- name: cargo deny check all
run: cargo deny check all
node-externals:
runs-on: [self-hosted, preloop-cpane]
timeout-minutes: 30
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Audit Node externals (OSV + SBOM)
run: bash scripts/audit-node-externals.sh
- name: Upload SBOM artifact
if: ${{ !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: sbom-node-externals
path: sbom-node-externals.cdx.json
if-no-files-found: ignore
check-node-pin-parity:
runs-on: [self-hosted, preloop-cpane]
timeout-minutes: 10
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Check Node pin parity against upstream externals.sh
run: |
set -euo pipefail
runner_version="$(grep -E '^runner_version[[:space:]]*=' versions.toml | head -n1 | sed -E 's/.*"[[:space:]]*([^"]+)[[:space:]]*".*/\1/')"
if [[ -z "$runner_version" ]]; then
echo "failed to parse runner_version from versions.toml" >&2
exit 1
fi
echo "runner_version from versions.toml: $runner_version"
node20_local="$(grep -E '^node20_externals_version[[:space:]]*=' versions.toml | head -n1 | sed -E 's/.*"[[:space:]]*([^"]+)[[:space:]]*".*/\1/')"
node24_local="$(grep -E '^node24_externals_version[[:space:]]*=' versions.toml | head -n1 | sed -E 's/.*"[[:space:]]*([^"]+)[[:space:]]*".*/\1/')"
echo "Local pins: node20=$node20_local node24=$node24_local"
url="https://raw.githubusercontent.com/actions/runner/v${runner_version}/src/Misc/externals.sh"
echo "Fetching $url"
curl -fsSL --retry 3 --retry-all-errors "$url" -o /tmp/externals.sh || true
node20_upstream="$(grep -E 'NODE20_VERSION=' /tmp/externals.sh | head -n1 | sed -E 's/.*"([^"]+)".*/\1/' || true)"
node24_upstream="$(grep -E 'NODE24_VERSION=' /tmp/externals.sh | head -n1 | sed -E 's/.*"([^"]+)".*/\1/' || true)"
echo "Upstream externals.sh: NODE20_VERSION=$node20_upstream NODE24_VERSION=$node24_upstream"
# Also check v2.337.0 upstream externals (documented forward-port in docs/fidelity-gap.md)
curl -fsSL --retry 3 --retry-all-errors "https://raw.githubusercontent.com/actions/runner/v2.337.0/src/Misc/externals.sh" -o /tmp/externals_337.sh || true
node20_337="$(grep -E 'NODE20_VERSION=' /tmp/externals_337.sh | head -n1 | sed -E 's/.*"([^"]+)".*/\1/' || true)"
node24_337="$(grep -E 'NODE24_VERSION=' /tmp/externals_337.sh | head -n1 | sed -E 's/.*"([^"]+)".*/\1/' || true)"
echo "v2.337.0 externals.sh: NODE20_VERSION=$node20_337 NODE24_VERSION=$node24_337"
drift=0
if [[ "$node20_local" != "$node20_upstream" && "$node20_local" != "$node20_337" ]]; then
echo "::error::node20_externals_version drift: versions.toml=$node20_local upstream externals.sh NODE20_VERSION=$node20_upstream (runner $runner_version)"
drift=1
fi
if [[ "$node24_local" != "$node24_upstream" && "$node24_local" != "$node24_337" ]]; then
echo "::error::node24_externals_version drift: versions.toml=$node24_local upstream externals.sh NODE24_VERSION=$node24_upstream (runner $runner_version)"
drift=1
fi
# Also validate crates/preloop-runner/src/configure.rs pins if present
if [[ -f "crates/preloop-runner/src/configure.rs" ]]; then
configure_node20="$(grep -E '"node20",[[:space:]]*"v[0-9.]+"' crates/preloop-runner/src/configure.rs | head -n1 | sed -E 's/.*"v([^"]+)".*/\1/' || true)"
configure_node24="$(grep -E '"node24",[[:space:]]*"v[0-9.]+"' crates/preloop-runner/src/configure.rs | head -n1 | sed -E 's/.*"v([^"]+)".*/\1/' || true)"
if [[ -n "$configure_node20" && "$configure_node20" != "$node20_local" ]]; then
echo "::error::configure.rs node20 drift: configure.rs=v$configure_node20 vs versions.toml=$node20_local"
drift=1
fi
if [[ -n "$configure_node24" && "$configure_node24" != "$node24_local" ]]; then
echo "::error::configure.rs node24 drift: configure.rs=v$configure_node24 vs versions.toml=$node24_local"
drift=1
fi
fi
if [[ "$drift" -ne 0 ]]; then
echo "FAIL: Node pins have drifted from upstream actions/runner externals.sh" >&2
echo "Update versions.toml to match upstream, then refresh externals handling (see crates/preloop-runner/src/configure.rs and docs)." >&2
exit 1
fi
echo "Node pin parity: OK (node20=$node20_local node24=$node24_local matches runner $runner_version)"