Repository navigation
123 lines (116 loc) · 4.79 KB
/
Copy pathdependency-monitoring.yml
File metadata and controls
123 lines (116 loc) · 4.79 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
# Continuous dependency-vulnerability monitoring (sq-jfer) — a daily off-peak
# scan that opens/updates a SINGLE idempotent tracking issue when an advisory
# affects the dependency tree, so a vuln disclosed between Dependabot's weekly
# sweeps is surfaced within a day.
#
# Distinct from supply-chain.yml's `audit` job: that gates PRs/pushes; this is a
# scheduled watchdog that turns findings into an actionable, deduplicated issue.
#
# Third-party actions pinned by full commit SHA.
name: dependency-monitoring
on:
# Daily, off-peak (05:13 UTC — odd minute to avoid the top-of-hour stampede).
schedule:
- cron: "13 5 * * *"
workflow_dispatch:
permissions:
contents: read
concurrency:
group: dependency-monitoring
cancel-in-progress: false
jobs:
audit:
name: cargo-deny advisories -> tracking issue
runs-on: ubuntu-latest
permissions:
contents: read
issues: write # open/update the security:dependency-vuln tracking issue
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Rust (preinstalled stable)
# CI-economy (2026-07-18 directive): the ubuntu runner image
# ships a rustup stable toolchain; the SHA-pinned action's `rustup
# toolchain install stable` re-downloads the whole toolchain whenever
# the image lags the newest release. Use the preinstalled one —
# `rustup default`/`component add` never trigger a toolchain download.
run: |
rustup default stable
rustup show active-toolchain
- name: Install cargo-deny
uses: taiki-e/install-action@183e4297cca2404691e9380e1307288dced5c82a # v2.87.25
with:
tool: cargo-deny
# Run advisories only; capture the human-readable report. `|| true` so we
# can branch on the exit code ourselves (and still fail the job at the end).
- name: Run cargo-deny advisories
id: deny
run: |
set +e
REPORT="$(python3 scripts/rust-dependency-graphs.py deny-advisories 2>&1)"
CODE=$?
echo "exit_code=$CODE" >> "$GITHUB_OUTPUT"
{
echo 'report<<DENY_EOF'
echo "$REPORT"
echo 'DENY_EOF'
} >> "$GITHUB_OUTPUT"
echo "$REPORT"
exit 0
- name: Open or update the tracking issue
if: steps.deny.outputs.exit_code != '0'
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const label = 'security:dependency-vuln';
const title = 'Dependency vulnerability advisory detected';
const report = process.env.DENY_REPORT || '(no report captured)';
const body = [
'`cargo deny check advisories` reported one or more findings on the',
'scheduled dependency-monitoring run.',
'',
`Run: ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`,
'',
'<details><summary>cargo-deny report</summary>',
'',
'```',
report,
'```',
'',
'</details>',
'',
'_This issue is maintained idempotently by `.github/workflows/dependency-monitoring.yml`._',
].join('\n');
// Ensure the label exists (ignore "already exists").
try {
await github.rest.issues.createLabel({
...context.repo, name: label, color: 'b60205',
description: 'A dependency advisory affects the tree',
});
} catch (e) {
if (e.status !== 422) throw e;
}
// Find an existing OPEN tracking issue with the label.
const existing = await github.rest.issues.listForRepo({
...context.repo, state: 'open', labels: label, per_page: 100,
});
const hit = existing.data.find(i => i.title === title);
if (hit) {
await github.rest.issues.update({
...context.repo, issue_number: hit.number, body,
});
await github.rest.issues.createComment({
...context.repo, issue_number: hit.number,
body: `Re-detected on run ${context.runId}. Body refreshed above.`,
});
} else {
await github.rest.issues.create({
...context.repo, title, body, labels: [label],
});
}
env:
DENY_REPORT: ${{ steps.deny.outputs.report }}
- name: Fail the job if advisories were found
if: steps.deny.outputs.exit_code != '0'
run: |
echo "cargo-deny advisories reported findings (exit ${{ steps.deny.outputs.exit_code }})."
exit 1