@@ -2,13 +2,14 @@ name: CI
22
33on :
44 push :
5- branches : [main ]
5+ branches : ["**" ]
66 pull_request :
7- branches : [main]
87
98permissions :
109 contents : read
1110 security-events : write
11+ checks : write
12+ pull-requests : write
1213
1314env :
1415 CARGO_TERM_COLOR : always
5455 needs : test
5556 steps :
5657 - uses : actions/checkout@v4
58+ with :
59+ fetch-depth : 0 # full history needed for --history and --blame
5760
5861 - name : Install Rust toolchain
5962 uses : dtolnay/rust-toolchain@stable
@@ -64,33 +67,122 @@ jobs:
6467 - name : Build oxide-ci
6568 run : cargo build --release
6669
67- # Secret detection — reads .oxideci.toml to exclude test fixtures and docs
68- # that intentionally contain example/fake patterns.
69- - name : Scan for secrets and PII
70+ # ── Config validation ────────────────────────────────────────────────────
71+ - name : Validate .oxideci.toml
72+ run : ./target/release/oxide-ci check-config
73+
74+ # ── Secret + SAST scan (JS/TS/Python/Go AST) — human-readable ───────────
75+ # Reads .oxideci.toml to exclude test fixtures and docs that
76+ # intentionally contain example/fake patterns.
77+ - name : Scan for secrets, PII and dangerous patterns
7078 run : ./target/release/oxide-ci scan
7179
72- # Kubernetes lint — exits 0 when no YAML manifests are present
73- - name : Lint Kubernetes manifests
74- run : ./target/release/oxide-ci lint
80+ # ── Incremental scan — only staged/changed files ─────────────────────────
81+ - name : Scan files changed since last commit
82+ run : ./target/release/oxide-ci scan --since HEAD~1 || true
7583
76- # Dependency audit — queries OSV database for known CVEs in Cargo.lock
77- - name : Audit dependencies (OSV)
78- run : ./target/release/oxide-ci audit
84+ # ── git blame enrichment ─────────────────────────────────────────────────
85+ - name : Scan with blame enrichment
86+ run : ./target/release/oxide-ci scan --blame || true
7987
80- # Upload SARIF report so GitHub annotates PRs with any findings.
81- # Runs even if the scan step above fails (continue-on-error: true).
88+ # ── Multi-format output validation ───────────────────────────────────────
8289 - name : Generate SARIF report
8390 if : always()
8491 continue-on-error : true
8592 run : ./target/release/oxide-ci scan --format sarif > oxide-ci-results.sarif 2>/dev/null || true
8693
94+ - name : Generate JSON report
95+ if : always()
96+ continue-on-error : true
97+ run : ./target/release/oxide-ci scan --format json > oxide-ci-results.json 2>/dev/null || true
98+
99+ - name : Generate JUnit XML report
100+ if : always()
101+ continue-on-error : true
102+ run : ./target/release/oxide-ci scan --format junit > oxide-ci-results.xml 2>/dev/null || true
103+
104+ - name : Generate GitLab SAST report
105+ if : always()
106+ continue-on-error : true
107+ run : ./target/release/oxide-ci scan --format gitlab > gl-sast-report.json 2>/dev/null || true
108+
109+ # ── Upload scan artifacts ────────────────────────────────────────────────
87110 - name : Upload SARIF to GitHub Security tab
88111 if : always()
89112 uses : github/codeql-action/upload-sarif@v3
90113 with :
91114 sarif_file : oxide-ci-results.sarif
92115 continue-on-error : true
93116
117+ - name : Upload JUnit XML
118+ if : always()
119+ uses : actions/upload-artifact@v4
120+ with :
121+ name : junit-report
122+ path : oxide-ci-results.xml
123+ continue-on-error : true
124+
125+ - name : Upload GitLab SAST report
126+ if : always()
127+ uses : actions/upload-artifact@v4
128+ with :
129+ name : gitlab-sast-report
130+ path : gl-sast-report.json
131+ continue-on-error : true
132+
133+ - name : Upload JSON report
134+ if : always()
135+ uses : actions/upload-artifact@v4
136+ with :
137+ name : json-report
138+ path : oxide-ci-results.json
139+ continue-on-error : true
140+
141+ # ── GitHub Check Run annotations + PR summary comment ────────────────────
142+ # Posts per-line annotations to the Checks tab and a rich summary comment
143+ # on the PR. Only meaningful on pull_request events.
144+ - name : Post GitHub Check Run annotations and PR summary
145+ if : github.event_name == 'pull_request'
146+ env :
147+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
148+ GITHUB_REPOSITORY : ${{ github.repository }}
149+ GITHUB_SHA : ${{ github.sha }}
150+ run : ./target/release/oxide-ci scan --annotate || true
151+
152+ # ── Baseline workflow ────────────────────────────────────────────────────
153+ - name : Save scan baseline (main branch only)
154+ if : github.ref == 'refs/heads/main'
155+ run : |
156+ ./target/release/oxide-ci scan --update-baseline || true
157+ git diff --quiet .oxide-baseline.json 2>/dev/null || echo "Baseline updated"
158+
159+ - name : Gate on new findings only (PRs)
160+ if : github.event_name == 'pull_request' && hashFiles('.oxide-baseline.json') != ''
161+ run : ./target/release/oxide-ci scan --since-baseline
162+
163+ # ── Kubernetes lint — exits 0 when no YAML manifests are present ─────────
164+ - name : Lint Kubernetes manifests
165+ run : ./target/release/oxide-ci lint
166+
167+ # ── Dependency audit — queries OSV database for known CVEs ───────────────
168+ - name : Audit dependencies (OSV)
169+ run : ./target/release/oxide-ci audit
170+
171+ # ── SBOM generation (CycloneDX 1.5) ─────────────────────────────────────
172+ - name : Generate SBOM
173+ run : ./target/release/oxide-ci sbom --output sbom.json
174+
175+ - name : Upload SBOM artifact
176+ uses : actions/upload-artifact@v4
177+ with :
178+ name : sbom
179+ path : sbom.json
180+
181+ # Validate SBOM structure
182+ - name : Validate SBOM has expected fields
183+ run : |
184+ jq -e '.bomFormat == "CycloneDX" and .specVersion == "1.5" and (.components | length > 0)' sbom.json
185+
94186 # ── 4. Performance audit (Lighthouse + Reassure) ─────────────────────────────
95187 perf :
96188 name : Performance
0 commit comments