diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1b9ac6..d7bdae1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -222,7 +222,7 @@ jobs: - name: Check version.txt matches Cargo.toml workspace version run: | set -euo pipefail - CARGO_VERSION=$(grep -A1 'x-release-please-version' Cargo.toml | tail -1 | sed 's/.*"\(.*\)".*/\1/') + CARGO_VERSION=$(grep '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/') TXT_VERSION=$(cat version.txt | tr -d '[:space:]') if [[ "$CARGO_VERSION" != "$TXT_VERSION" ]]; then echo "::error::version.txt ($TXT_VERSION) does not match Cargo.toml workspace version ($CARGO_VERSION)" diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 7f7cf81..9e39a9e 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -6,11 +6,10 @@ name: release-please # last release. Merging that PR creates a GitHub Release and a v{X.Y.Z} # tag. # -# The downstream workflows trigger off the GitHub Release publish event -# (release.yml → crates.io, npm-build-publish.yml → npm) rather than the -# tag push. This avoids the GitHub Actions limitation where tags pushed -# by GITHUB_TOKEN don't fire `on: push: tags:` workflows — which would -# otherwise require a custom PAT. +# Uses a fine-grained PAT (RELEASE_PLEASE_TOKEN) instead of the default +# GITHUB_TOKEN so that PRs and tags created by this workflow trigger +# downstream CI and publish workflows. With GITHUB_TOKEN, GitHub +# suppresses workflow triggers on events it creates (anti-recursion). # # Maintainers don't run anything by hand: # 1. Land conventional-commit PRs into main. @@ -35,3 +34,4 @@ jobs: with: config-file: release-please-config.json manifest-file: .release-please-manifest.json + token: ${{ secrets.RELEASE_PLEASE_TOKEN }} diff --git a/Cargo.toml b/Cargo.toml index e6081c7..e47af42 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,6 @@ members = [ ] [workspace.package] -# x-release-please-version version = "0.1.2" edition = "2021" rust-version = "1.81" diff --git a/docs/GITHUB_OPERATIONS.md b/docs/GITHUB_OPERATIONS.md index d04c524..9c173e3 100644 --- a/docs/GITHUB_OPERATIONS.md +++ b/docs/GITHUB_OPERATIONS.md @@ -329,10 +329,86 @@ The workflow's regex validator rejects malformed tag names, and | Secret | Used by | Scope | |---|---|---| +| `RELEASE_PLEASE_TOKEN` | [release-please.yml](../.github/workflows/release-please.yml) | Fine-grained PAT; triggers CI on release-please PRs/tags (see below) | | `CARGO_REGISTRY_TOKEN` | [release.yml](../.github/workflows/release.yml) `publish` job | `cargo publish` to crates.io | | `NPM_TOKEN` | [npm-build-publish.yml](../.github/workflows/npm-build-publish.yml) `publish-npm` job | `npm publish` to npmjs.org | | `GITHUB_TOKEN` | Every workflow | Auto-provided by GitHub Actions; used to post releases, download artifacts, verify CI status | +### Why release-please needs a PAT + +GitHub Actions suppresses workflow triggers on events created by +`GITHUB_TOKEN` (anti-recursion protection). Without a PAT, PRs opened +by release-please don't trigger CI, and tags it pushes don't trigger +`release.yml` or `npm-build-publish.yml`. The workaround is a +fine-grained PAT stored as `RELEASE_PLEASE_TOKEN`. + +### Option A: Fine-grained PAT (current setup) + +1. Go to **Settings → Developer settings → Personal access tokens → + Fine-grained tokens → Generate new token**. +2. Configure: + - **Token name:** `release-please-hyper-api-rust` + - **Expiration:** 90 days (set a calendar reminder to rotate) + - **Resource owner:** `tableau` + - **Repository access:** Only select → `tableau/hyper-api-rust` + - **Permissions → Repository:** + - Contents: Read and write + - Pull requests: Read and write +3. Click "Generate token" and copy it. +4. Add it as a repo secret: + ```bash + gh secret set RELEASE_PLEASE_TOKEN --repo tableau/hyper-api-rust + ``` +5. The [release-please workflow](../.github/workflows/release-please.yml) + references this secret via `token: ${{ secrets.RELEASE_PLEASE_TOKEN }}`. + +**Rotation:** when the PAT expires, generate a new one with the same +settings and update the secret. Release-please will fail with a 401 +until the secret is refreshed — CI on `main` pushes will still show the +failure clearly. + +### Option B: GitHub App token (recommended for larger teams) + +A GitHub App token isn't tied to any individual's account and never +expires (tokens are minted per-run). Preferred for org-owned repos or +when multiple maintainers need the pipeline to work independently. + +1. **Create a GitHub App** (org-level: Settings → Developer settings → + GitHub Apps → New): + - **Name:** `hyper-api-rust-release-please` + - **Permissions → Repository:** + - Contents: Read and write + - Pull requests: Read and write + - No webhook URL needed (uncheck "Active" under Webhook) + - Generate a private key and download it +2. **Install the App** on `tableau/hyper-api-rust` (or all repos in the + org if you want it shared). +3. **Store credentials** as repo secrets: + ```bash + gh secret set APP_ID --repo tableau/hyper-api-rust # numeric App ID + gh secret set APP_PRIVATE_KEY --repo tableau/hyper-api-rust # PEM file contents + ``` +4. **Update the workflow** to mint a short-lived token each run: + ```yaml + jobs: + release-please: + runs-on: ubuntu-latest + steps: + - uses: actions/create-github-app-token@v2 + id: app-token + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + - uses: googleapis/release-please-action@v5 + with: + config-file: release-please-config.json + manifest-file: .release-please-manifest.json + token: ${{ steps.app-token.outputs.token }} + ``` + +This mints a token scoped to the installation that expires in 1 hour — +no rotation needed, no personal account dependency. + ## Issue & PR templates There are no `.github/ISSUE_TEMPLATE/` or `.github/pull_request_template.md` diff --git a/hyperdb-api-core/Cargo.toml b/hyperdb-api-core/Cargo.toml index 774c8cd..fc0c1e5 100644 --- a/hyperdb-api-core/Cargo.toml +++ b/hyperdb-api-core/Cargo.toml @@ -64,8 +64,9 @@ serde = { workspace = true } serde_json = { workspace = true } # Salesforce OAuth authentication (optional, via standalone crate) -# x-release-please-version +# x-release-please-start-version hyperdb-api-salesforce = { path = "../hyperdb-api-salesforce", version = "=0.1.2", optional = true } +# x-release-please-end # Arrow parsing for catalog operations (optional, used by authenticated_client) arrow = { version = "58.0", optional = true } diff --git a/hyperdb-api/Cargo.toml b/hyperdb-api/Cargo.toml index cd13f04..baba39d 100644 --- a/hyperdb-api/Cargo.toml +++ b/hyperdb-api/Cargo.toml @@ -13,8 +13,9 @@ categories = ["database"] autobenches = false [dependencies] -# x-release-please-version +# x-release-please-start-version hyperdb-api-core = { path = "../hyperdb-api-core", version = "=0.1.2" } +# x-release-please-end bytes = { workspace = true } thiserror = { workspace = true } tracing = { workspace = true } diff --git a/release-please-config.json b/release-please-config.json index bfb9ee2..1e8869c 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -27,7 +27,7 @@ "component": "hyper-api-rust", "changelog-path": "CHANGELOG.md", "extra-files": [ - { "type": "generic", "path": "Cargo.toml" }, + { "type": "toml", "path": "Cargo.toml", "jsonpath": "$.workspace.package.version" }, { "type": "generic", "path": "hyperdb-api-core/Cargo.toml" }, { "type": "generic", "path": "hyperdb-api/Cargo.toml" }, {