Skip to content

Commit 67aea39

Browse files
authored
Merge pull request #15 from deeleeramone/chore/ci-lockfiles-sbom-version-gates
chore(ci): enforce branch gates, refresh lockfiles, and ship CycloneDX SBOM
2 parents 8fe64a0 + 33b1637 commit 67aea39

17 files changed

Lines changed: 5760 additions & 16724 deletions

.github/workflows/docs.yml

Lines changed: 71 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,8 @@ on:
44
push:
55
branches:
66
- main
7-
paths:
8-
- 'pywry/docs/**'
9-
- 'pywry/**/*.py'
10-
- '.github/workflows/docs.yml'
117
pull_request:
12-
branches: [main, master, develop]
13-
paths:
14-
- 'pywry/docs/**'
15-
- 'pywry/**/*.py'
16-
- '.github/workflows/docs.yml'
8+
branches: [main, develop]
179
workflow_dispatch:
1810

1911
permissions:
@@ -24,7 +16,47 @@ concurrency:
2416
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
2517

2618
jobs:
19+
detect-doc-impact:
20+
name: Detect docs impact
21+
runs-on: ubuntu-latest
22+
permissions:
23+
contents: read
24+
outputs:
25+
should-build: ${{ steps.detect.outputs.should-build }}
26+
steps:
27+
- name: Checkout repository
28+
uses: actions/checkout@v5
29+
with:
30+
fetch-depth: 0
31+
32+
- name: Decide whether docs build is required
33+
id: detect
34+
shell: bash
35+
env:
36+
IS_PR: ${{ github.event_name == 'pull_request' }}
37+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
38+
run: |
39+
set -euo pipefail
40+
41+
if [[ "$IS_PR" != "true" ]]; then
42+
echo "should-build=true" >> "$GITHUB_OUTPUT"
43+
exit 0
44+
fi
45+
46+
git fetch --depth=1 origin "$BASE_SHA"
47+
48+
CHANGED=$(git diff --name-only "$BASE_SHA" HEAD)
49+
DOC_RELATED=$(echo "$CHANGED" | grep -E '^(pywry/docs/|pywry/.*\.py$|\.github/workflows/docs\.yml$)' || true)
50+
51+
if [[ -n "$DOC_RELATED" ]]; then
52+
echo "should-build=true" >> "$GITHUB_OUTPUT"
53+
else
54+
echo "should-build=false" >> "$GITHUB_OUTPUT"
55+
fi
56+
2757
build:
58+
if: github.event_name != 'pull_request' || needs.detect-doc-impact.outputs.should-build == 'true'
59+
needs: detect-doc-impact
2860
runs-on: ubuntu-latest
2961
steps:
3062
- uses: actions/checkout@v5
@@ -70,3 +102,33 @@ jobs:
70102
- name: Deploy to GitHub Pages
71103
id: deployment
72104
uses: actions/deploy-pages@v4
105+
106+
docs-required:
107+
name: Docs Required
108+
runs-on: ubuntu-latest
109+
if: github.event_name == 'pull_request' && always()
110+
needs:
111+
- detect-doc-impact
112+
- build
113+
permissions:
114+
contents: read
115+
steps:
116+
- name: Enforce required docs outcomes
117+
shell: bash
118+
env:
119+
SHOULD_BUILD: ${{ needs.detect-doc-impact.outputs.should-build }}
120+
BUILD_RESULT: ${{ needs.build.result }}
121+
run: |
122+
set -euo pipefail
123+
124+
if [[ "$SHOULD_BUILD" == "false" ]]; then
125+
echo "No docs-impacting changes detected; docs build intentionally skipped."
126+
exit 0
127+
fi
128+
129+
if [[ "$BUILD_RESULT" != "success" ]]; then
130+
echo "Docs build did not succeed (result: $BUILD_RESULT)"
131+
exit 1
132+
fi
133+
134+
echo "Docs validation passed."

.github/workflows/publish-pywry.yml

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,13 +439,19 @@ jobs:
439439
path: pywry/dist/*.whl
440440
retention-days: 30
441441

442+
generate-sbom:
443+
name: Generate release SBOM
444+
needs: [test]
445+
if: ${{ !cancelled() && (needs.test.result == 'success' || needs.test.result == 'skipped') }}
446+
uses: ./.github/workflows/sbom.yml
447+
442448
# =============================================================================
443449
# Step 3: Merge all artifacts into single dist
444450
# =============================================================================
445451
merge-artifacts:
446452
name: Merge artifacts
447-
needs: [build-linux-x86_64, build-linux-aarch64, build-macos-x86_64, build-macos-arm64, build-windows-amd64, build-windows-arm64]
448-
if: ${{ !cancelled() && needs.build-linux-x86_64.result == 'success' }}
453+
needs: [build-linux-x86_64, build-linux-aarch64, build-macos-x86_64, build-macos-arm64, build-windows-amd64, build-windows-arm64, generate-sbom]
454+
if: ${{ !cancelled() && needs.build-linux-x86_64.result == 'success' && needs.generate-sbom.result == 'success' }}
449455
runs-on: ubuntu-24.04
450456
defaults:
451457
run:
@@ -469,6 +475,15 @@ jobs:
469475
name: sdist
470476
path: artifacts/sdist/
471477

478+
- name: Download SBOM artifacts
479+
uses: actions/download-artifact@v8.0.1
480+
with:
481+
name: sbom
482+
path: artifacts/sbom/
483+
484+
- name: Ensure output directories exist
485+
run: mkdir -p dist
486+
472487
- name: Consolidate artifacts and fail on duplicate wheel names
473488
shell: bash
474489
run: |
@@ -522,6 +537,34 @@ jobs:
522537
print(f"Skipped {skipped_identical} identical duplicate wheel artifact(s)")
523538
PY
524539
540+
- name: Add distributed artifacts to merged SBOM
541+
shell: bash
542+
run: |
543+
test -f artifacts/sbom/sbom.cdx.json
544+
docker run --rm \
545+
-v "$PWD:/work" \
546+
-w /work \
547+
cyclonedx/cyclonedx-cli:latest \
548+
add files \
549+
--input-file artifacts/sbom/sbom.cdx.json \
550+
--input-format json \
551+
--output-format json \
552+
--output-file dist/sbom.cdx.json \
553+
--base-path dist \
554+
--include "**/*.whl" "**/*.tar.gz"
555+
556+
- name: Validate release SBOM
557+
shell: bash
558+
run: |
559+
docker run --rm \
560+
-v "$PWD:/work" \
561+
-w /work \
562+
cyclonedx/cyclonedx-cli:latest \
563+
validate \
564+
--input-file dist/sbom.cdx.json \
565+
--input-format json \
566+
--fail-on-errors
567+
525568
- name: Validate wheel archives for duplicate ZIP members
526569
shell: bash
527570
run: |
@@ -834,6 +877,12 @@ jobs:
834877
contents: write
835878

836879
steps:
880+
- name: Download dist artifacts
881+
uses: actions/download-artifact@v8.0.1
882+
with:
883+
name: dist
884+
path: dist/
885+
837886
- name: Create draft release
838887
uses: softprops/action-gh-release@v2
839888
with:
@@ -866,8 +915,14 @@ jobs:
866915
867916
- Python 3.10, 3.11, 3.12, 3.13, 3.14
868917
918+
### SBOM
919+
920+
- CycloneDX SBOM is included in this release as `sbom.cdx.json`.
921+
869922
---
870923
*This is a draft release. Wheels are published to PyPI separately.*
924+
files: |
925+
dist/*
871926
872927
# =============================================================================
873928
# Step 6: Publish to PyPI - Trusted Publisher (workflow_dispatch only)

0 commit comments

Comments
 (0)