|
| 1 | +name: Update Nix flake |
| 2 | + |
| 3 | +# Checks whether flake.nix lags behind the latest stable GitHub release. If it |
| 4 | +# does, prefetches the new release's per-platform SRI hashes, rewrites flake.nix, |
| 5 | +# and opens a PR. |
| 6 | +# |
| 7 | +# Runs on a schedule instead of release: published because: |
| 8 | +# 1. brave-browser releases are created by an external release pipeline (not |
| 9 | +# this repo's GITHUB_TOKEN), and |
| 10 | +# 2. a daily lag-check is fully decoupled from how releases are created and |
| 11 | +# needs no PAT. |
| 12 | +# The guard `github.repository == 'brave/brave-browser'` prevents the scheduled |
| 13 | +# job from running on forks. |
| 14 | + |
| 15 | +on: |
| 16 | + schedule: |
| 17 | + - cron: "17 6 * * *" |
| 18 | + workflow_dispatch: |
| 19 | + |
| 20 | +permissions: |
| 21 | + contents: write |
| 22 | + pull-requests: write |
| 23 | + |
| 24 | +concurrency: |
| 25 | + group: nix-flake-release |
| 26 | + cancel-in-progress: true |
| 27 | + |
| 28 | +jobs: |
| 29 | + update-flake: |
| 30 | + name: Bump flake version + hashes if lagging |
| 31 | + runs-on: ubuntu-latest |
| 32 | + if: github.repository == 'brave/brave-browser' |
| 33 | + steps: |
| 34 | + - name: Checkout |
| 35 | + uses: actions/checkout@v6 |
| 36 | + with: |
| 37 | + persist-credentials: false |
| 38 | + |
| 39 | + - name: Install Nix |
| 40 | + uses: cachix/install-nix-action@v31 |
| 41 | + |
| 42 | + - name: Check for lag and rewrite flake.nix |
| 43 | + env: |
| 44 | + # system|asset-filename-template — one per line. The template uses |
| 45 | + # {VERSION} as a placeholder for the version (without the leading v). |
| 46 | + # Brave's asset naming differs between Linux (.deb) and Darwin (.zip). |
| 47 | + ASSET_MAP: | |
| 48 | + x86_64-linux|brave-browser_{VERSION}_amd64.deb |
| 49 | + aarch64-linux|brave-browser_{VERSION}_arm64.deb |
| 50 | + x86_64-darwin|brave-v{VERSION}-darwin-x64.zip |
| 51 | + aarch64-darwin|brave-v{VERSION}-darwin-arm64.zip |
| 52 | + run: | |
| 53 | + set -euo pipefail |
| 54 | + tag=$(curl -fsSL -H "Accept: application/vnd.github+json" \ |
| 55 | + "https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/latest" \ |
| 56 | + | python3 -c 'import json,sys; print(json.load(sys.stdin)["tag_name"])') |
| 57 | + latest="${tag#v}" |
| 58 | + current=$(python3 -c 'import re; s=open("flake.nix").read(); m=re.search(r"version = \"([^\"]*)\";", s); print(m.group(1))') |
| 59 | + echo "flake.nix version: $current | latest release: $latest (tag $tag)" |
| 60 | + if [ "$current" = "$latest" ]; then |
| 61 | + echo "flake.nix is up to date; nothing to do." |
| 62 | + echo "LAGGING=no" >> "$GITHUB_ENV" |
| 63 | + exit 0 |
| 64 | + fi |
| 65 | + echo "LAGGING=yes" >> "$GITHUB_ENV" |
| 66 | + echo "VERSION=$latest" >> "$GITHUB_ENV" |
| 67 | + export TAG="$tag" |
| 68 | + python3 <<'PYEOF' |
| 69 | + import os, re, subprocess |
| 70 | + tag = os.environ["TAG"] |
| 71 | + version = tag.lstrip("v") |
| 72 | + repo = os.environ["GITHUB_REPOSITORY"] |
| 73 | + asset_map = {} |
| 74 | + for line in os.environ["ASSET_MAP"].splitlines(): |
| 75 | + line = line.strip() |
| 76 | + if not line or line.startswith("#"): |
| 77 | + continue |
| 78 | + sys_, tmpl = line.split("|", 1) |
| 79 | + asset_map[sys_.strip()] = tmpl.strip() |
| 80 | + src = open("flake.nix").read() |
| 81 | + src, n = re.subn(r'version = "[^"]*";', f'version = "{version}";', src, count=1) |
| 82 | + if n != 1: |
| 83 | + raise SystemExit('could not find version = "..." in flake.nix') |
| 84 | + for sys_, tmpl in asset_map.items(): |
| 85 | + filename = tmpl.replace("{VERSION}", version) |
| 86 | + url = f"https://github.com/{repo}/releases/download/{tag}/{filename}" |
| 87 | + out = subprocess.check_output( |
| 88 | + ["nix", "store", "prefetch-file", "--json", "--hash-type", "sha256", url]) |
| 89 | + import json |
| 90 | + sri = json.loads(out)["hash"] |
| 91 | + # Replace the hash line within this system's asset block. |
| 92 | + pat = re.compile(r'("' + re.escape(sys_) + r'" = \{[^}]*\})', re.S) |
| 93 | + def repl(m): |
| 94 | + b = m.group(1) |
| 95 | + b = re.sub(r'hash = "[^"]*";', f'hash = "{sri}";', b, count=1) |
| 96 | + return b |
| 97 | + src, n = pat.subn(repl, src, count=1) |
| 98 | + if n != 1: |
| 99 | + raise SystemExit(f"could not find assets block for {sys_} in flake.nix") |
| 100 | + open("flake.nix", "w").write(src) |
| 101 | + print(f"bumped flake.nix to {version}: {list(asset_map)}") |
| 102 | + PYEOF |
| 103 | +
|
| 104 | + - name: Open PR |
| 105 | + if: env.LAGGING == 'yes' |
| 106 | + uses: peter-evans/create-pull-request@v7 |
| 107 | + with: |
| 108 | + commit-message: "chore(nix): bump flake to v${{ env.VERSION }}" |
| 109 | + title: "chore(nix): bump flake to v${{ env.VERSION }}" |
| 110 | + branch: chore/nix-flake-v${{ env.VERSION }} |
| 111 | + base: master |
| 112 | + body: | |
| 113 | + Auto-generated by the `Update Nix flake` workflow (daily lag-check). |
| 114 | + The latest stable GitHub release is v${{ env.VERSION }} but `flake.nix` was |
| 115 | + pinned to an older version. This PR bumps `version` and refreshes the per-platform SRI |
| 116 | + hashes by prefetching the new release assets. |
| 117 | +
|
| 118 | + Note: PRs opened by `GITHUB_TOKEN` do not trigger downstream workflow runs (e.g. CI), |
| 119 | + so this PR will show no checks. The diff is a 5-line hash bump with no source changes — |
| 120 | + safe to merge as-is. |
0 commit comments