nixpkgs-bump.yml

  1name: Nixpkgs Bump PR
  2
  3# Triggers on stable release publish. Opens PR against NixOS/nixpkgs
  4# bumping pkgs/by-name/ma/matcha/package.nix to the new version.
  5# Requires:
  6#   - Fork floatpane/nixpkgs to exist
  7#   - NIXPKGS_BUMP_TOKEN secret: PAT with `repo` scope on floatpane/nixpkgs
  8#     and permission to open PRs against NixOS/nixpkgs
  9#   - Initial matcha package already merged into nixpkgs (this workflow updates, not inits)
 10
 11on:
 12  workflow_dispatch:
 13    inputs:
 14      version:
 15        description: "Version to bump to (without v prefix)"
 16        required: true
 17
 18permissions:
 19  contents: read
 20
 21jobs:
 22  bump:
 23    runs-on: ubuntu-latest
 24    steps:
 25      - name: Determine version
 26        id: ver
 27        run: |
 28          if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
 29            VERSION="${{ inputs.version }}"
 30          else
 31            TAG="${{ github.event.release.tag_name }}"
 32            VERSION="${TAG#v}"
 33          fi
 34          # Skip nightly / preview tags
 35          if [[ "$VERSION" == nightly* || "$VERSION" == preview* ]]; then
 36            echo "Skipping non-stable release: $VERSION"
 37            echo "skip=true" >> $GITHUB_OUTPUT
 38          else
 39            echo "skip=false" >> $GITHUB_OUTPUT
 40          fi
 41          echo "version=$VERSION" >> $GITHUB_OUTPUT
 42
 43      - name: Install Nix
 44        if: steps.ver.outputs.skip != 'true'
 45        uses: cachix/install-nix-action@v31
 46        with:
 47          extra_nix_config: |
 48            experimental-features = nix-command flakes
 49
 50      - name: Checkout nixpkgs fork
 51        if: steps.ver.outputs.skip != 'true'
 52        uses: actions/checkout@v6
 53        with:
 54          repository: floatpane/nixpkgs
 55          token: ${{ secrets.HOMEBREW_GITHUB_TOKEN }}
 56          path: nixpkgs
 57          fetch-depth: 0
 58
 59      - name: Sync fork with upstream master
 60        if: steps.ver.outputs.skip != 'true'
 61        working-directory: nixpkgs
 62        run: |
 63          git config user.name "Floatpane Bot"
 64          git config user.email "us@floatpane.com"
 65          git remote add upstream https://github.com/NixOS/nixpkgs.git
 66          git fetch upstream master staging
 67          git checkout master
 68          git reset --hard upstream/master
 69          git push origin master --force-with-lease
 70
 71      - name: Get current version (from master)
 72        if: steps.ver.outputs.skip != 'true'
 73        id: current
 74        working-directory: nixpkgs
 75        run: |
 76          PKG=pkgs/by-name/ma/matcha/package.nix
 77          OLD=$(grep -E '^\s*version\s*=\s*"' "$PKG" | head -1 | sed -E 's/.*"([^"]+)".*/\1/')
 78          echo "old=$OLD" >> $GITHUB_OUTPUT
 79
 80      - name: Write go overlay from staging
 81        if: steps.ver.outputs.skip != 'true'
 82        working-directory: nixpkgs
 83        run: |
 84          # master nixpkgs heavily cached. Staging has go_1_26 = 1.26.3.
 85          # Overlay swaps only go_1_26 → minimal rebuild.
 86          STAGING_REV=$(git rev-parse upstream/staging)
 87          echo "STAGING_REV=$STAGING_REV" >> $GITHUB_ENV
 88          cat > /tmp/go-overlay.nix <<EOF
 89          let
 90            staging = import (builtins.fetchTarball
 91              "https://github.com/NixOS/nixpkgs/archive/$STAGING_REV.tar.gz") {};
 92          in final: prev: {
 93            go_1_26 = staging.go_1_26;
 94            go = staging.go_1_26;
 95            buildGoModule = prev.buildGoModule.override { go = staging.go_1_26; };
 96          }
 97          EOF
 98          cat /tmp/go-overlay.nix
 99
100      - name: Create bump branch
101        if: steps.ver.outputs.skip != 'true'
102        working-directory: nixpkgs
103        run: |
104          BRANCH="matcha-${{ steps.ver.outputs.version }}"
105          git checkout -b "$BRANCH"
106          echo "BRANCH=$BRANCH" >> $GITHUB_ENV
107
108      - name: Bump version and reset hashes
109        if: steps.ver.outputs.skip != 'true'
110        working-directory: nixpkgs
111        run: |
112          PKG=pkgs/by-name/ma/matcha/package.nix
113          NEW="${{ steps.ver.outputs.version }}"
114          # Replace version line
115          sed -i -E "s/(version\s*=\s*\")[^\"]+(\")/\1$NEW\2/" "$PKG"
116          # Reset src hash + vendorHash to fakeHash so nix build prints real ones
117          sed -i -E 's|hash = "sha256-[A-Za-z0-9+/=]+"|hash = lib.fakeHash|' "$PKG"
118          sed -i -E 's|vendorHash = "sha256-[A-Za-z0-9+/=]+"|vendorHash = lib.fakeHash|' "$PKG"
119
120      - name: Prefetch src hash (no build)
121        if: steps.ver.outputs.skip != 'true'
122        id: src_hash
123        working-directory: nixpkgs
124        run: |
125          NEW="${{ steps.ver.outputs.version }}"
126          URL="https://github.com/floatpane/matcha/archive/refs/tags/v$NEW.tar.gz"
127          # --unpack matches fetchFromGitHub (NAR hash of unpacked tarball)
128          BASE32=$(nix-prefetch-url --unpack "$URL")
129          HASH=$(nix hash to-sri --type sha256 "$BASE32")
130          echo "Resolved SRI hash: $HASH"
131          echo "hash=$HASH" >> $GITHUB_OUTPUT
132          sed -i -E "s|hash = lib.fakeHash|hash = \"$HASH\"|" pkgs/by-name/ma/matcha/package.nix
133
134      - name: Build to extract vendorHash
135        if: steps.ver.outputs.skip != 'true'
136        working-directory: nixpkgs
137        run: |
138          set +e
139          nix-build ./. -A matcha --no-out-link \
140            --arg overlays "[ (import /tmp/go-overlay.nix) ]" \
141            2>&1 | tee /tmp/build-vendor.log
142          HASH=$(grep -oE 'got:[[:space:]]+sha256-[A-Za-z0-9+/=]+' /tmp/build-vendor.log | head -1 | awk '{print $2}')
143          if [ -z "$HASH" ]; then
144            echo "Failed to extract vendorHash"; exit 1
145          fi
146          sed -i -E "s|vendorHash = lib.fakeHash|vendorHash = \"$HASH\"|" pkgs/by-name/ma/matcha/package.nix
147
148      - name: Final build (sanity check)
149        if: steps.ver.outputs.skip != 'true'
150        working-directory: nixpkgs
151        run: |
152          nix-build ./. -A matcha --no-out-link \
153            --arg overlays "[ (import /tmp/go-overlay.nix) ]"
154
155      - name: Commit and push
156        if: steps.ver.outputs.skip != 'true'
157        working-directory: nixpkgs
158        run: |
159          git add pkgs/by-name/ma/matcha/package.nix
160          git commit -m "matcha: ${{ steps.current.outputs.old }} -> ${{ steps.ver.outputs.version }}"
161          git push -u origin "$BRANCH" --force-with-lease
162
163      - name: Open PR against NixOS/nixpkgs
164        if: steps.ver.outputs.skip != 'true'
165        env:
166          GH_TOKEN: ${{ secrets.HOMEBREW_GITHUB_TOKEN }}
167        working-directory: nixpkgs
168        run: |
169          BODY=$(cat <<EOF
170          ## Description
171
172          Automated version bump for \`matcha\` email client.
173
174          - Old: ${{ steps.current.outputs.old }}
175          - New: ${{ steps.ver.outputs.version }}
176          - Upstream release: https://github.com/floatpane/matcha/releases/tag/v${{ steps.ver.outputs.version }}
177
178          ## Things done
179
180          - Built on \`x86_64-linux\` via GitHub Actions
181          - Hashes regenerated from upstream tarball
182          - No package metadata changes beyond version + hashes
183
184          cc maintainer for review.
185          EOF
186          )
187          gh pr create \
188            --repo NixOS/nixpkgs \
189            --base master \
190            --head "floatpane:$BRANCH" \
191            --title "matcha: ${{ steps.current.outputs.old }} -> ${{ steps.ver.outputs.version }}" \
192            --body "$BODY"