/ .github / workflows / cd-publish.yml
cd-publish.yml
  1  name: "CD: Build & Publish"
  2  
  3  on:
  4    workflow_dispatch:
  5      inputs:
  6        version:
  7          description: "Version"
  8          required: true
  9          type: string
 10        prerelease:
 11          description: "Mark as prerelease"
 12          required: false
 13          default: false
 14          type: boolean
 15  
 16  jobs:
 17    version:
 18      name: Bump Version & Tag
 19      runs-on: ubuntu-latest
 20      permissions:
 21        contents: write
 22      steps:
 23        - name: "[INIT] Get privileged app token"
 24          id: app-token
 25          uses: actions/create-github-app-token@v2
 26          with:
 27            app-id: ${{ vars.APP_ID }}
 28            private-key: ${{ secrets.APP_KEY }}
 29  
 30        - name: "[INIT] Checkout"
 31          uses: actions/checkout@v6
 32          with:
 33            fetch-depth: 0
 34            token: ${{ steps.app-token.outputs.token }}
 35  
 36        - name: "[INIT] Git Config"
 37          run: |
 38            git config user.name "github-actions[bot]"
 39            git config user.email "github-actions[bot]@users.noreply.github.com"
 40  
 41        - name: "[INIT] Install Nix"
 42          uses: cachix/install-nix-action@v31
 43          with:
 44            nix_path: nixpkgs=channel:nixos-unstable
 45  
 46        - name: "[INIT] Setup Cachix"
 47          uses: cachix/cachix-action@v16
 48          with:
 49            name: amperser
 50            authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
 51  
 52        - name: "[VERSION] Bump & Commit"
 53          run: |
 54            nix develop --command uv version ${{ github.event.inputs.version }}
 55            nix develop --command git-cliff -c cliff.toml -u \
 56            --tag v${{ github.event.inputs.version }} \
 57            -p CHANGELOG.md
 58  
 59            git commit -am "chore: prepare release v${{ github.event.inputs.version }}" --no-verify || echo "no changes to commit"
 60  
 61        - name: "[GIT] Create tag"
 62          run: |
 63            git tag v${{ github.event.inputs.version }}
 64            git push origin HEAD --tags
 65  
 66    build:
 67      name: Build Artifacts
 68      runs-on: ubuntu-latest
 69      needs: [version]
 70      permissions:
 71        contents: read
 72        id-token: write
 73        attestations: write
 74      steps:
 75        - name: "[INIT] Checkout"
 76          uses: actions/checkout@v6
 77          with:
 78            fetch-depth: 0
 79  
 80        - name: "[INIT] Install Nix"
 81          uses: cachix/install-nix-action@v31
 82          with:
 83            nix_path: nixpkgs=channel:nixos-unstable
 84  
 85        - name: "[INIT] Setup Cachix"
 86          uses: cachix/cachix-action@v16
 87          with:
 88            name: amperser
 89            authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
 90  
 91        - name: "[BUILD] Wheel"
 92          run: |
 93            mkdir -p dist
 94            nix build -L .#wheel
 95            cp result/*.whl dist/
 96  
 97  
 98        - name: "[BUILD] Source dist"
 99          run: |
100            nix build -L .#sdist
101            cp result/*.tar.gz dist/
102  
103        - name: "[CHANGELOG] Generate release notes"
104          run: |
105            nix develop --command git-cliff -c cliff.toml \
106              --latest --verbose \
107              -o dist/RELEASE_NOTES.md
108  
109        - name: "[VERIFY] Provenance"
110          uses: actions/attest-build-provenance@v3
111          with:
112            subject-path: 'dist/*'
113  
114        - name: "[UPLOAD] Artifacts"
115          uses: actions/upload-artifact@v6
116          with:
117            name: dist-artifacts
118            path: dist/
119            if-no-files-found: error
120  
121    github-release:
122      name: GitHub Release
123      runs-on: ubuntu-latest
124      needs: [build]
125      permissions:
126        contents: write
127      steps:
128        - name: "[INIT] Checkout"
129          uses: actions/checkout@v6
130          with:
131            fetch-depth: 0
132  
133        - name: "[DOWNLOAD] Artifacts"
134          uses: actions/download-artifact@v7
135          with:
136            name: dist-artifacts
137            path: dist/
138  
139        - name: "[INPUT] Get input"
140          id: input
141          run: |
142            echo "tag=v${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
143            echo "version=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
144            echo "prerelease=${{ github.event.inputs.prerelease }}" >> $GITHUB_OUTPUT
145  
146        - name: "[INIT] Move release notes"
147          run: mv dist/RELEASE_NOTES.md ./RELEASE_NOTES.md
148  
149        - name: "[RELEASE] Create GitHub release"
150          uses: softprops/action-gh-release@v2
151          with:
152            name: Release ${{ steps.input.outputs.tag }}
153            tag_name: ${{ steps.input.outputs.tag }}
154            prerelease: ${{ steps.input.outputs.prerelease }}
155            body_path: ./RELEASE_NOTES.md
156            files: dist/*
157  
158    pypi-publish:
159      name: Publish to PyPI
160      runs-on: ubuntu-latest
161      needs: [build]
162      environment: release
163      permissions:
164        id-token: write
165      steps:
166        - name: "[DOWNLOAD] Artifacts"
167          uses: actions/download-artifact@v7
168          with:
169            name: dist-artifacts
170            path: dist/
171  
172        - name: "[INIT] Remove release notes"
173          run: rm dist/RELEASE_NOTES.md
174  
175        - name: "[PUBLISH] PyPI"
176          uses: pypa/gh-action-pypi-publish@release/v1