-
Notifications
You must be signed in to change notification settings - Fork 308
138 lines (123 loc) · 4.73 KB
/
Copy pathrelease.yml
File metadata and controls
138 lines (123 loc) · 4.73 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
name: "Publish to PyPI"
on:
workflow_dispatch:
inputs:
version:
description: 'Version to release (must match a git tag, e.g., 0.2.1)'
required: true
type: string
permissions:
contents: read
jobs:
pypi-publish:
name: Upload release to PyPI
runs-on: ubuntu-latest
defaults:
run:
shell: bash
environment:
name: pypi
url: https://pypi.org/p/cisco-ai-skill-scanner
permissions:
id-token: write
contents: write # needed to create/update the GitHub release assets
attestations: write # needed to store build provenance and SBOM attestations
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ inputs.version }}
fetch-depth: 0
- name: Install uv
uses: astral-sh/setup-uv@v6.7.0
- name: Install Python 3.12
run: uv python install 3.12
- name: Build
run: uv build
# Export a hash-pinned requirements.txt so plain `pip` users can reproduce
# the same locked tree without needing uv. Kept outside dist/ so the PyPI
# publish step doesn't try to upload it as a distribution.
- name: Export hash-pinned requirements.txt
run: |
mkdir -p release-assets
uv export \
--frozen \
--no-dev \
--all-extras \
--no-emit-project \
--output-file release-assets/requirements.txt
# SBOM is generated from the frozen export above so all release artifacts
# describe one locked tree. The project version is dynamic (VCS-derived),
# so it is stamped from the workflow input.
- name: Generate CycloneDX SBOM
env:
VERSION: ${{ inputs.version }}
run: |
uv sync --frozen --only-group sbom
# --output-reproducible omits the serialNumber required by actions/attest.
uv run --no-sync cyclonedx-py requirements \
release-assets/requirements.txt \
--pyproject pyproject.toml \
--output-file release-assets/sbom.cdx.json
jq --arg v "$VERSION" \
'.metadata.component.version = $v
| .metadata.component.purl = "pkg:pypi/cisco-ai-skill-scanner@\($v)"' \
release-assets/sbom.cdx.json > sbom.tmp
mv sbom.tmp release-assets/sbom.cdx.json
jq -e \
'.bomFormat == "CycloneDX"
and (.serialNumber | type == "string" and length > 0)
and (.specVersion | type == "string" and length > 0)' \
release-assets/sbom.cdx.json >/dev/null
- name: Attest build provenance
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
with:
subject-path: |
dist/*
release-assets/*
- name: Attest SBOM
uses: actions/attest-sbom@c604332985a26aa8cf1bdc465b92731239ec6b9e # v4.1.0
with:
subject-path: dist/*
sbom-path: release-assets/sbom.cdx.json
- name: Check GitHub release state
id: release-state
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ inputs.version }}
run: |
if gh release view "$VERSION" --json isDraft --jq '.isDraft' >/tmp/release-is-draft; then
is_draft="$(</tmp/release-is-draft)"
echo "exists=true" >> "$GITHUB_OUTPUT"
echo "draft=$is_draft" >> "$GITHUB_OUTPUT"
if [[ "$is_draft" == "false" ]]; then
echo "published=true" >> "$GITHUB_OUTPUT"
echo "::warning::GitHub release $VERSION is already published. Immutable releases cannot accept new assets, so release asset upload will be skipped."
else
echo "published=false" >> "$GITHUB_OUTPUT"
fi
else
echo "exists=false" >> "$GITHUB_OUTPUT"
echo "draft=false" >> "$GITHUB_OUTPUT"
echo "published=false" >> "$GITHUB_OUTPUT"
fi
- name: Attach requirements.txt and SBOM to draft GitHub release
if: steps.release-state.outputs.published != 'true'
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ inputs.version }}
files: |
release-assets/requirements.txt
release-assets/sbom.cdx.json
fail_on_unmatched_files: true
draft: true
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
skip-existing: true
- name: Publish GitHub release
if: steps.release-state.outputs.published != 'true'
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ inputs.version }}
run: gh release edit "$VERSION" --draft=false