diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 43aebcd..4d604ed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: runs-on: ${{ matrix.platform }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install Linux dependencies if: matrix.platform == 'ubuntu-22.04' @@ -28,12 +28,12 @@ jobs: sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf - name: Setup Node - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: 22 - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@v6 - name: Setup Rust uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 54c3256..815d791 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,7 +27,7 @@ jobs: contents: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install Linux dependencies if: matrix.platform == 'ubuntu-22.04' @@ -36,12 +36,12 @@ jobs: sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf - name: Setup Node - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: 22 - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@v6 - name: Setup Rust uses: dtolnay/rust-toolchain@stable @@ -67,3 +67,19 @@ jobs: releaseDraft: true prerelease: false args: ${{ matrix.args }} + + # Publish the draft release once every platform build has succeeded. + # Keeping the build as a draft avoids exposing a half-uploaded (or partial, + # if a platform fails) release; `needs: build` requires all matrix jobs to + # pass before this runs, so a failed platform leaves the release as a draft. + publish: + needs: build + if: startsWith(github.ref, 'refs/tags/') + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Publish release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: gh release edit "${{ github.ref_name }}" --repo "${{ github.repository }}" --draft=false --latest diff --git a/CLAUDE.md b/CLAUDE.md index f4073f4..c10b2c9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -19,6 +19,28 @@ cd src-tauri && cargo test # run Rust backend tests cd src-tauri && cargo clippy # lint Rust code ``` +## Releasing & Version Bump + +When asked to **bump version** to `X.Y.Z`, do the full release flow — bumping the version files alone ships nothing; the `vX.Y.Z` tag push is what triggers a release. + +1. Update the version in all four places, keeping them in sync: + - `package.json` → `"version"` + - `src-tauri/Cargo.toml` → `version` + - `src-tauri/tauri.conf.json` → `"version"` + - `src-tauri/Cargo.lock` → the `grove` package entry (run `cargo update -p grove --precise X.Y.Z` in `src-tauri/`, or `cargo check`, to refresh it after editing `Cargo.toml`) +2. Commit on a branch and open a PR (per the branch rules): `chore: bump version to X.Y.Z`. +3. After the PR merges to `main`, create an **annotated** tag on the merge commit and push it (message convention: `Grove vX.Y.Z`): + ```bash + git tag -a vX.Y.Z -m "Grove vX.Y.Z" + git push origin vX.Y.Z + ``` +4. The tag push triggers `.github/workflows/release.yml`, which builds macOS (universal) / Linux / Windows via `tauri-action` into a **draft** GitHub release with the bundles attached. +5. **No manual publish needed** — once all three platform builds succeed, the `publish` job auto-flips the draft to a published release (marked latest). If any platform fails, the release stays a draft (safe). Watch with `gh run watch` / `gh run list --workflow=release.yml`. + +Notes: +- The tag **must** use the `v` prefix (`vX.Y.Z`); the workflow only fires on `tags: ['v*']`. +- The release build does **not** sign artifacts — the updater plugin was removed (#29). Do not re-add updater config or `TAURI_SIGNING_PRIVATE_KEY`; a malformed signing key is what broke the v0.12.0 / v0.12.1 release builds. + ## Architecture **Frontend** (`src/`): Single-page React app. All state lives in `App.tsx` — no router, no state library. `src/lib/api.ts` wraps every `@tauri-apps/api/core` `invoke()` call; `src/lib/types.ts` has the shared TypeScript types that mirror the Rust models. `src/lib/theme.tsx` provides ThemeProvider (light/dark/system); `src/lib/i18n.tsx` provides I18nProvider; `src/lib/branch-name-gen.ts` generates random branch name suggestions. Translations in `src/locales/`.