|
7 | 7 | workflow_dispatch: |
8 | 8 |
|
9 | 9 | permissions: |
10 | | - contents: write # Required for creating releases |
11 | | - issues: write |
12 | | - pull-requests: write |
13 | | - statuses: write |
14 | | - checks: write |
15 | | - id-token: write # Required for generating build attestations |
16 | | - |
17 | | -concurrency: |
18 | | - group: release-workflow |
19 | | - cancel-in-progress: true |
| 10 | + contents: read |
20 | 11 |
|
21 | 12 | jobs: |
22 | | - semantic-release: |
23 | | - if: ${{ github.ref == 'refs/heads/main' }} |
| 13 | + release: |
24 | 14 | runs-on: ubuntu-latest |
| 15 | + concurrency: |
| 16 | + group: ${{ github.workflow }}-release-${{ github.ref_name }} |
| 17 | + cancel-in-progress: false |
| 18 | + |
| 19 | + permissions: |
| 20 | + contents: write |
| 21 | + issues: write |
| 22 | + pull-requests: write |
| 23 | + |
| 24 | + outputs: |
| 25 | + released: ${{ steps.release.outputs.released }} |
| 26 | + version: ${{ steps.release.outputs.version }} |
| 27 | + tag: ${{ steps.release.outputs.tag }} |
| 28 | + |
25 | 29 | steps: |
26 | | - - uses: actions/checkout@v4 |
| 30 | + - name: Setup | Checkout Repository |
| 31 | + uses: actions/checkout@v4 |
27 | 32 | with: |
28 | 33 | fetch-depth: 0 |
29 | 34 | token: ${{ secrets.GITHUB_TOKEN }} |
30 | | - - name: Set up Python |
| 35 | + |
| 36 | + - name: Setup | Python |
31 | 37 | uses: actions/setup-python@v5 |
32 | 38 | with: |
33 | 39 | python-version: 3.11 |
34 | | - - name: Install Dependencies |
| 40 | + |
| 41 | + - name: Setup | Install Dependencies |
35 | 42 | run: | |
36 | 43 | pip install poetry |
37 | 44 | poetry install --with dev |
38 | | - - name: Configure Git for semantic-release |
39 | | - run: | |
40 | | - git config --global user.name "github-actions[bot]" |
41 | | - git config --global user.email "github-actions[bot]@users.noreply.github.com" |
42 | | - git config --global commit.gpgsign false # Disable signing for automated commits |
43 | | - - name: Python Semantic Release |
| 45 | +
|
| 46 | + - name: Action | Semantic Version Release |
| 47 | + id: release |
44 | 48 | uses: python-semantic-release/python-semantic-release@v10.0.2 |
45 | 49 | with: |
46 | 50 | github_token: ${{ secrets.GITHUB_TOKEN }} |
47 | | - changelog: true # Generate changelog |
48 | | - vcs_release: true # Create a release on GitHub |
49 | | - tag: true # Tag the release |
50 | | - push: true # Push changes back to the repository |
51 | | - commit: true # Commit changes |
| 51 | + git_committer_name: "github-actions[bot]" |
| 52 | + git_committer_email: "github-actions[bot]@users.noreply.github.com" |
| 53 | + |
| 54 | + - name: Publish | Upload to GitHub Release Assets |
| 55 | + uses: python-semantic-release/publish-action@v10.0.2 |
| 56 | + if: steps.release.outputs.released == 'true' |
| 57 | + with: |
| 58 | + github_token: ${{ secrets.GITHUB_TOKEN }} |
| 59 | + tag: ${{ steps.release.outputs.tag }} |
| 60 | + |
| 61 | + - name: Publish to TestPyPI |
| 62 | + if: steps.release.outputs.released == 'true' |
| 63 | + env: |
| 64 | + POETRY_PYPI_TOKEN_TESTPYPI: ${{ secrets.TEST_PYPI_API_TOKEN }} |
| 65 | + run: | |
| 66 | + poetry config repositories.testpypi https://test.pypi.org/legacy/ |
| 67 | + poetry publish --repository testpypi |
| 68 | +
|
| 69 | + - name: Create convenience Git tags |
| 70 | + if: steps.release.outputs.released == 'true' |
| 71 | + run: | |
| 72 | + # Extract version components for convenience tagging |
| 73 | + VERSION=${{ steps.release.outputs.version }} |
| 74 | + MAJOR=$(echo "$VERSION" | cut -d. -f1) |
| 75 | + MINOR=$(echo "$VERSION" | cut -d. -f2) |
| 76 | +
|
| 77 | + # Create/update convenience tags to match Docker tagging strategy |
| 78 | + git tag -f "v$MAJOR" ${{ steps.release.outputs.tag }} |
| 79 | + git tag -f "v$MAJOR.$MINOR" ${{ steps.release.outputs.tag }} |
| 80 | +
|
| 81 | + # Push convenience tags |
| 82 | + git push origin "v$MAJOR" --force |
| 83 | + git push origin "v$MAJOR.$MINOR" --force |
52 | 84 |
|
| 85 | + echo "Created convenience tags: v$MAJOR, v$MAJOR.$MINOR" |
53 | 86 |
|
54 | 87 | sbom-generation: |
55 | | - needs: semantic-release # Ensure this runs after the semantic-release job |
56 | | - if: ${{ github.ref == 'refs/heads/main' }} |
| 88 | + needs: release |
| 89 | + if: needs.release.outputs.released == 'true' |
57 | 90 | runs-on: ubuntu-latest |
58 | 91 | permissions: |
59 | 92 | contents: write |
60 | 93 | actions: read |
61 | 94 | security-events: write |
| 95 | + |
62 | 96 | steps: |
63 | 97 | - uses: actions/checkout@v4 |
64 | 98 | with: |
65 | 99 | fetch-depth: 0 |
66 | | - ref: ${{ github.head_ref || github.ref_name }} |
67 | | - - name: Get version |
68 | | - id: version |
69 | | - run: | |
70 | | - # Get version from pyproject.toml after semantic-release updated it |
71 | | - VERSION=$(grep '^version =' pyproject.toml | sed 's/version = "\(.*\)"/\1/') |
72 | | - echo "version=$VERSION" >> $GITHUB_OUTPUT |
73 | | - echo "Version: $VERSION" |
| 100 | + ref: ${{ needs.release.outputs.tag }} |
| 101 | + |
74 | 102 | - name: Generate SBOM |
75 | 103 | uses: anchore/sbom-action@v0.17.6 |
76 | 104 | with: |
77 | | - path: . # Generate SBOM for the entire repository |
78 | | - artifact-name: sbom.spdx.json # Name of the generated SBOM file |
79 | | - format: spdx-json # Use SPDX format for SBOM |
80 | | - dependency-snapshot: true # Include dependency snapshot (non-breaking warning) |
81 | | - upload-release-assets: true # Automatically upload to GitHub release |
| 105 | + path: . |
| 106 | + artifact-name: sbom.spdx.json |
| 107 | + format: spdx-json |
| 108 | + dependency-snapshot: true |
| 109 | + upload-release-assets: true |
82 | 110 | github-token: ${{ secrets.GITHUB_TOKEN }} |
83 | 111 |
|
84 | | - publish: |
85 | | - needs: semantic-release |
86 | | - if: ${{ github.ref == 'refs/heads/main' }} |
| 112 | + docker-artifacts: |
| 113 | + needs: release |
| 114 | + if: needs.release.outputs.released == 'true' |
87 | 115 | runs-on: ubuntu-latest |
| 116 | + permissions: |
| 117 | + contents: write |
| 118 | + |
88 | 119 | steps: |
89 | 120 | - uses: actions/checkout@v4 |
90 | 121 | with: |
91 | 122 | fetch-depth: 0 |
92 | | - ref: ${{ github.head_ref || github.ref_name }} |
93 | | - - name: Get version |
94 | | - id: version |
95 | | - run: | |
96 | | - # Get version from pyproject.toml after semantic-release updated it |
97 | | - VERSION=$(grep '^version =' pyproject.toml | sed 's/version = "\(.*\)"/\1/') |
98 | | - echo "version=$VERSION" >> $GITHUB_OUTPUT |
99 | | - echo "Version: $VERSION" |
| 123 | + ref: ${{ needs.release.outputs.tag }} |
| 124 | + |
100 | 125 | - name: Set up Docker Buildx |
101 | 126 | uses: docker/setup-buildx-action@v3 |
102 | | - - name: Build Docker image as tar |
103 | | - run: | |
104 | | - docker build -t network-reputation-check:v${{ steps.version.outputs.version }} . |
105 | | - docker save network-reputation-check:v${{ steps.version.outputs.version }} -o network-reputation-check-v${{ steps.version.outputs.version }}.tar |
| 127 | + |
| 128 | + - name: Extract metadata |
| 129 | + id: meta |
| 130 | + uses: docker/metadata-action@v5 |
| 131 | + with: |
| 132 | + images: network-reputation-check |
| 133 | + tags: | |
| 134 | + type=semver,pattern={{version}},value=${{ needs.release.outputs.version }} |
| 135 | + type=semver,pattern={{major}}.{{minor}},value=${{ needs.release.outputs.version }} |
| 136 | + type=semver,pattern={{major}},value=${{ needs.release.outputs.version }} |
| 137 | + type=raw,value=latest |
| 138 | + labels: | |
| 139 | + org.opencontainers.image.title=Network Reputation Check Action |
| 140 | + org.opencontainers.image.description=${{ github.event.repository.description }} |
| 141 | +
|
| 142 | + - name: Build Docker image |
| 143 | + id: build |
| 144 | + uses: docker/build-push-action@v6 |
| 145 | + with: |
| 146 | + context: . |
| 147 | + push: false |
| 148 | + tags: ${{ steps.meta.outputs.tags }} |
| 149 | + labels: ${{ steps.meta.outputs.labels }} |
| 150 | + outputs: type=docker,dest=network-reputation-check-${{ needs.release.outputs.version }}.tar |
| 151 | + |
106 | 152 | - name: Upload Docker tar to GitHub release |
107 | 153 | uses: softprops/action-gh-release@v2 |
108 | 154 | with: |
109 | | - tag_name: v${{ steps.version.outputs.version }} |
110 | | - files: network-reputation-check-v${{ steps.version.outputs.version }}.tar |
| 155 | + tag_name: ${{ needs.release.outputs.tag }} |
| 156 | + files: network-reputation-check-${{ needs.release.outputs.version }}.tar |
111 | 157 | draft: false |
112 | 158 | prerelease: false |
113 | | - - name: Set up Python for TestPyPI publishing |
114 | | - uses: actions/setup-python@v5 |
115 | | - with: |
116 | | - python-version: 3.11 |
117 | | - - name: Install Poetry and publish to TestPyPI |
118 | | - env: |
119 | | - POETRY_PYPI_TOKEN_TESTPYPI: ${{ secrets.TEST_PYPI_API_TOKEN }} |
120 | | - run: | |
121 | | - pip install poetry |
122 | | - poetry config repositories.testpypi https://test.pypi.org/legacy/ |
123 | | - poetry build # Build fresh since semantic-release built in different environment |
124 | | - poetry publish --repository testpypi |
|
0 commit comments