From 40c2f74070e21aaffa30702efda87a267b3581f6 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 1 Jun 2026 17:25:12 +0000 Subject: [PATCH 1/2] Add Homebrew release automation for copilot-cli Tag-driven release.yml publishes copilot.py as a release asset and regenerates the formula in natikgadzhi/homebrew-taps; tag.yml bumps __version__ and dispatches it. README documents brew install. https://claude.ai/code/session_01QQQNWfXFv9V9UMunBwGATJ --- .github/workflows/release.yml | 131 ++++++++++++++++++++++++++++++++++ .github/workflows/tag.yml | 78 ++++++++++++++++++++ README.md | 21 +++++- 3 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/tag.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..07f8ed7 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,131 @@ +name: Release + +# Tag-triggered release for the copilot.py uv script. Publishes copilot.py as a +# release asset (verbatim — its sha256 is just the file's hash) and regenerates +# the Homebrew formula in natikgadzhi/homebrew-taps so `brew upgrade` picks it up. +# +# Why workflow_dispatch in addition to `on: push tags`: a tag pushed with the +# default GITHUB_TOKEN does NOT start other workflows, so tag.yml dispatches this +# explicitly on the new tag ref (same pattern as the copilot-auth repo). +on: + push: + tags: ["v*"] + workflow_dispatch: + inputs: + tag: + description: "Tag to release (e.g. v0.4.0)" + required: true + +permissions: + contents: write # create the Release + upload assets + +jobs: + release: + name: Publish asset and update the tap + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Resolve version + id: version + run: | + set -euo pipefail + ref="${{ github.event.inputs.tag || github.ref_name }}" + tag="${ref#refs/tags/}" + version="${tag#v}" + if [[ ! "${version}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Could not parse a semver from tag '${tag}'." >&2 + exit 1 + fi + # The asset is copilot.py verbatim, so __version__ must match the tag — + # otherwise the published file would disagree with the release version. + script_version="$(grep -E '^__version__ = ' copilot.py | sed -E 's/.*"([^"]+)".*/\1/')" + if [[ "${script_version}" != "${version}" ]]; then + echo "__version__ (${script_version}) does not match tag (${version})." >&2 + exit 1 + fi + echo "tag=${tag}" >> "$GITHUB_OUTPUT" + echo "version=${version}" >> "$GITHUB_OUTPUT" + + - name: Compute SHA-256 + id: checksum + run: | + set -euo pipefail + sha="$(sha256sum copilot.py | awk '{print $1}')" + echo "sha256=${sha}" >> "$GITHUB_OUTPUT" + echo "copilot.py sha256=${sha}" + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ steps.version.outputs.tag }} + files: copilot.py + body: | + Install with Homebrew: + + ```sh + brew install natikgadzhi/taps/copilot-cli + copilot-cli --version + ``` + + **copilot.py sha256:** `${{ steps.checksum.outputs.sha256 }}` + + - name: Check out the Homebrew tap + uses: actions/checkout@v4 + with: + repository: natikgadzhi/homebrew-taps + token: ${{ secrets.HOMEBREW_TAP_TOKEN }} + path: tap + + - name: Regenerate the formula + env: + VERSION: ${{ steps.version.outputs.version }} + SHA256: ${{ steps.checksum.outputs.sha256 }} + run: | + set -euo pipefail + cat > tap/Formula/copilot-cli.rb <&2 + exit 1 + fi + IFS=. read -r major minor patch <<< "${current}" + case "${{ inputs.bump }}" in + major) major=$((major + 1)); minor=0; patch=0 ;; + minor) minor=$((minor + 1)); patch=0 ;; + patch) patch=$((patch + 1)) ;; + esac + next="${major}.${minor}.${patch}" + if git rev-parse "v${next}" >/dev/null 2>&1; then + echo "Tag v${next} already exists." >&2 + exit 1 + fi + echo "next=${next}" >> "$GITHUB_OUTPUT" + echo "Bumping ${current} -> ${next}" + + - name: Bump, commit, and tag + env: + NEXT: ${{ steps.version.outputs.next }} + run: | + set -euo pipefail + sed -i -E "s/(^__version__ = \")[0-9]+\.[0-9]+\.[0-9]+(\")/\1${NEXT}\2/" copilot.py + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git commit -am "Release v${NEXT}" + git tag -a "v${NEXT}" -m "Release v${NEXT}" + git push origin HEAD:main + git push origin "v${NEXT}" + + - name: Trigger release for the new tag + env: + GH_TOKEN: ${{ github.token }} + NEXT: ${{ steps.version.outputs.next }} + run: gh workflow run release.yml --field tag="v${NEXT}" diff --git a/README.md b/README.md index 531cfab..10073c5 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,28 @@ to manage) with these subcommands: | `export` | Read the SQLite DB and emit `accounts.{csv,md}` + `categories.{csv,md}`. | | `stats` | Print row counts, the latest transaction, and the last sync time. | +## Install + +Install with Homebrew — this pulls in `uv` and puts a `copilot-cli` command on +your PATH, so you never have to type `uv run copilot.py` again: + +```sh +brew install natikgadzhi/taps/copilot-cli +copilot-cli --version +``` + +`copilot-cli` is a thin wrapper around the same `copilot.py` uv script (deps are +still resolved and cached by uv on first run), so it's a drop-in replacement for +`uv run copilot.py` everywhere below: `copilot-cli sync`, `copilot-cli stats`, +and so on. + +Prefer to run from a clone? Install [uv](https://docs.astral.sh/uv/getting-started/installation/) +and use `uv run copilot.py …` directly — no install step needed. + ## Setup -1. Install [uv](https://docs.astral.sh/uv/getting-started/installation/). +1. Install [uv](https://docs.astral.sh/uv/getting-started/installation/) (or + `brew install natikgadzhi/taps/copilot-cli`, which bundles it). 2. Provide two secrets — the Firebase `FIREBASE_API_KEY` and `COPILOT_REFRESH_TOKEN` — by **either** of: From 58aac5b8d2136c686bc42f4b4edd85a844e336fc Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 1 Jun 2026 17:29:45 +0000 Subject: [PATCH 2/2] Use HOMEBREW_TAP_GITHUB_TOKEN for tap pushes https://claude.ai/code/session_01QQQNWfXFv9V9UMunBwGATJ --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 07f8ed7..9772698 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -74,7 +74,7 @@ jobs: uses: actions/checkout@v4 with: repository: natikgadzhi/homebrew-taps - token: ${{ secrets.HOMEBREW_TAP_TOKEN }} + token: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }} path: tap - name: Regenerate the formula