Skip to content

Commit 6c4c2d8

Browse files
ci: add centralized workflows and security scan templates
- _build-reusable.yml: reusable build with SLSA L3 attestation, SBOM, license report - scorecard.yml: reusable OpenSSF Scorecard (no badge commit) - workflow-templates/codeql.yml: CodeQL template (job key: codeql) - workflow-templates/semgrep.yml: Semgrep template (job key: semgrep) All actions SHA-pinned. Templates are reference copies — each repo copies and adapts. Status check contract names documented inline. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 3a93dd6 commit 6c4c2d8

6 files changed

Lines changed: 235 additions & 0 deletions

File tree

.github/workflow-templates/.gitkeep

Whitespace-only changes.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
2+
# Copyright (c) 2025-2026 Project Navi contributors
3+
#
4+
# STATUS CHECK CONTRACT: Job name "codeql" is required by org ruleset.
5+
# Do NOT rename without updating org rulesets.
6+
name: CodeQL
7+
8+
on:
9+
push:
10+
branches: [main]
11+
pull_request:
12+
branches: [main]
13+
schedule:
14+
- cron: "30 5 * * 1"
15+
16+
permissions: {}
17+
18+
jobs:
19+
# CONTRACT: This job name "codeql" is a required status check in org rulesets.
20+
codeql:
21+
runs-on: ubuntu-latest
22+
permissions:
23+
contents: read
24+
security-events: write
25+
steps:
26+
- name: Harden runner
27+
uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0
28+
with:
29+
egress-policy: audit
30+
31+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
32+
33+
- name: Initialize CodeQL
34+
uses: github/codeql-action/init@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5
35+
with:
36+
languages: python
37+
queries: +security-extended
38+
39+
- name: Autobuild
40+
uses: github/codeql-action/autobuild@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5
41+
42+
- name: Perform analysis
43+
uses: github/codeql-action/analyze@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5
44+
with:
45+
category: "/language:python"
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
2+
# Copyright (c) 2025-2026 Project Navi contributors
3+
#
4+
# STATUS CHECK CONTRACT: Job name "semgrep" is a required status check in org rulesets.
5+
# Do NOT rename without updating org rulesets.
6+
name: Semgrep SAST
7+
8+
on:
9+
push:
10+
branches: [main]
11+
pull_request:
12+
branches: [main]
13+
schedule:
14+
- cron: "30 5 * * 1"
15+
16+
permissions: {}
17+
18+
jobs:
19+
# CONTRACT: This job name "semgrep" is a required status check in org rulesets.
20+
semgrep:
21+
runs-on: ubuntu-latest
22+
permissions:
23+
contents: read
24+
security-events: write
25+
container:
26+
image: semgrep/semgrep@sha256:e04d2cb132288d90035db8791d64f610cb255b21e727b94db046243b30c01ae9
27+
steps:
28+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
29+
30+
- name: Run Semgrep
31+
run: semgrep scan --config p/python --config p/owasp-top-ten --sarif -o semgrep.sarif
32+
33+
- name: Upload SARIF
34+
uses: github/codeql-action/upload-sarif@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5
35+
with:
36+
sarif_file: semgrep.sarif
37+
if: always()

.github/workflows/.gitkeep

Whitespace-only changes.
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
2+
# Copyright (c) 2025-2026 Project Navi contributors
3+
name: Build
4+
5+
on:
6+
workflow_call:
7+
inputs:
8+
tag_name:
9+
description: "Git tag for the release"
10+
required: true
11+
type: string
12+
package_name:
13+
description: "Python package name for smoke test import"
14+
required: true
15+
type: string
16+
python_version:
17+
description: "Python version to build with"
18+
required: false
19+
type: string
20+
default: "3.12"
21+
22+
permissions: {}
23+
24+
jobs:
25+
build:
26+
name: Build and attest
27+
runs-on: ubuntu-latest
28+
permissions:
29+
contents: write
30+
id-token: write
31+
attestations: write
32+
steps:
33+
- name: Harden runner
34+
uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0
35+
with:
36+
egress-policy: audit
37+
38+
- name: Checkout
39+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
40+
with:
41+
fetch-depth: 0
42+
43+
- name: Set up Python
44+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
45+
with:
46+
python-version: ${{ inputs.python_version }}
47+
48+
- name: Install uv
49+
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v7.3.1
50+
51+
- name: Build package
52+
run: uv build
53+
54+
- name: Smoke test
55+
env:
56+
PKG_NAME: ${{ inputs.package_name }}
57+
run: |
58+
python -m venv .venv-smoke
59+
.venv-smoke/bin/pip install dist/*.whl
60+
.venv-smoke/bin/python -c "import $PKG_NAME"
61+
62+
- name: Generate SBOM (CycloneDX)
63+
run: |
64+
pip install cyclonedx-bom==4.7.0
65+
cyclonedx-py environment -o sbom.cdx.json --output-format json
66+
67+
- name: Generate SBOM (SPDX)
68+
uses: anchore/sbom-action@17ae1740179002c89186b61233e0f892c3118b11 # v0.23.0
69+
with:
70+
artifact-name: sbom.spdx.json
71+
output-file: sbom.spdx.json
72+
73+
- name: Generate license report
74+
run: |
75+
pip install pip-licenses==5.0.0
76+
pip-licenses --format=csv --output-file=licenses.csv
77+
pip-licenses --format=plain --output-file=licenses.txt
78+
79+
- name: Generate release notes
80+
run: |
81+
pip install git-cliff==2.8.0
82+
git cliff --latest --output RELEASE_NOTES.md || echo "No release notes generated"
83+
84+
- name: Attest build provenance
85+
uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0
86+
with:
87+
subject-path: "dist/*"
88+
89+
- name: Upload dist
90+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
91+
with:
92+
name: dist
93+
path: dist/
94+
95+
- name: Upload SBOMs
96+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
97+
with:
98+
name: sbom
99+
path: |
100+
sbom.cdx.json
101+
sbom.spdx.json
102+
103+
- name: Upload licenses
104+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
105+
with:
106+
name: licenses
107+
path: |
108+
licenses.csv
109+
licenses.txt
110+
111+
- name: Upload release notes
112+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
113+
with:
114+
name: release-notes
115+
path: RELEASE_NOTES.md

.github/workflows/scorecard.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
2+
# Copyright (c) 2025-2026 Project Navi contributors
3+
name: OpenSSF Scorecard
4+
5+
on:
6+
workflow_call:
7+
8+
permissions: {}
9+
10+
jobs:
11+
analysis:
12+
name: Scorecard analysis
13+
runs-on: ubuntu-latest
14+
permissions:
15+
contents: read
16+
security-events: write
17+
steps:
18+
- name: Harden runner
19+
uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0
20+
with:
21+
egress-policy: audit
22+
23+
- name: Checkout
24+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
25+
with:
26+
persist-credentials: false
27+
28+
- name: Run Scorecard
29+
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
30+
with:
31+
results_file: results.sarif
32+
results_format: sarif
33+
publish_results: true
34+
35+
- name: Upload SARIF
36+
uses: github/codeql-action/upload-sarif@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5
37+
with:
38+
sarif_file: results.sarif

0 commit comments

Comments
 (0)