From a55a2c83321c1775cbd0f8ccc4d480f0e24dfc19 Mon Sep 17 00:00:00 2001 From: Wagner Costa Date: Fri, 28 Aug 2026 21:11:02 -0300 Subject: [PATCH] chore(ci): Automate releases with release-please and add the npm badge --- .github/workflows/release-please.yml | 56 ++++++++++++++++++++++++++++ .release-please-manifest.json | 3 ++ AGENTS.md | 6 ++- README.md | 2 + docs/runbooks/release.md | 43 ++++++++++++--------- release-please-config.json | 9 +++++ 6 files changed, 100 insertions(+), 19 deletions(-) create mode 100644 .github/workflows/release-please.yml create mode 100644 .release-please-manifest.json create mode 100644 release-please-config.json diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml new file mode 100644 index 0000000..f91b928 --- /dev/null +++ b/.github/workflows/release-please.yml @@ -0,0 +1,56 @@ +name: Release Please + +# Automates versioning and publishing from conventional commits: +# 1. Every push to main updates a "Release PR" (version bump + CHANGELOG). +# 2. Merging that PR creates the vX.Y.Z tag and GitHub Release, then this same +# run publishes to npm and attaches the tarball. Publishing lives HERE because +# tags created with GITHUB_TOKEN never trigger other workflows (release.yml). +# Only fix:/feat: (and breaking) commits produce a release; never bump package.json by hand. +on: + push: + branches: [main] + +permissions: + contents: write + pull-requests: write + +jobs: + release: + name: Release PR or publish + runs-on: ubuntu-latest + steps: + - uses: googleapis/release-please-action@v4 + id: release + with: + config-file: release-please-config.json + manifest-file: .release-please-manifest.json + - if: ${{ steps.release.outputs.release_created }} + uses: actions/checkout@v4 + - if: ${{ steps.release.outputs.release_created }} + uses: pnpm/action-setup@v4 + - if: ${{ steps.release.outputs.release_created }} + uses: actions/setup-node@v4 + with: + node-version: "22" + registry-url: "https://registry.npmjs.org" + cache: pnpm + - if: ${{ steps.release.outputs.release_created }} + run: pnpm install --frozen-lockfile + env: + ASKNEWS_NO_AGENT_SKILLS: "1" + # Bundle from the committed OpenAPI snapshot (deterministic, no network). + - if: ${{ steps.release.outputs.release_created }} + run: pnpm build:bundle + - if: ${{ steps.release.outputs.release_created }} + run: pnpm package:tarball + - if: ${{ steps.release.outputs.release_created }} + name: Publish to npm + uses: JS-DevTools/npm-publish@v3 + with: + token: ${{ secrets.NPM_TOKEN }} + access: public + - if: ${{ steps.release.outputs.release_created }} + name: Attach tarball and checksum to the GitHub Release + env: + GH_TOKEN: ${{ github.token }} + run: gh release upload "${{ steps.release.outputs.tag_name }}" release/*.tgz release/*.tgz.sha256 diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 0000000..0451499 --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.2.3" +} diff --git a/AGENTS.md b/AGENTS.md index e37645f..342603e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -79,7 +79,11 @@ pnpm build # generate and bundle dist/bin.js generated files. - Non-interactive commands must never prompt. Respect `CI`, non-TTY streams, and explicit flags. - Destructive or billable live tests require both the live-test gate and an operation-specific gate. -- Publishing the npm package happens through the release workflow on a `v*` tag; do not publish by hand. +- Releases are automated by release-please (`.github/workflows/release-please.yml`): merging to `main` + updates a Release PR; merging that PR tags, publishes to npm, and creates the GitHub Release. + Never bump `package.json` version by hand and never push `v*` tags by hand (`release.yml` is only + an emergency fallback). Only `fix:`/`feat:`/breaking commits trigger a release — use `fix:` (not + `chore:`) for user-visible schema refreshes so they ship. ## Docs map diff --git a/README.md b/README.md index c252538..1d7f950 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # AskNews CLI +[![npm version](https://img.shields.io/npm/v/%40emergentmethods%2Fasknews-cli?label=npm)](https://www.npmjs.com/package/@emergentmethods/asknews-cli) + The official AskNews command-line interface for humans, scripts, CI, and AI agents. ## Install diff --git a/docs/runbooks/release.md b/docs/runbooks/release.md index c253ebc..bb63da7 100644 --- a/docs/runbooks/release.md +++ b/docs/runbooks/release.md @@ -1,15 +1,25 @@ # Release The CLI is published to npm as [`@emergentmethods/asknews-cli`](https://www.npmjs.com/package/@emergentmethods/asknews-cli) -and distributed from GitHub. Releases are automated: pushing a `v*` tag runs -[`.github/workflows/release.yml`](../../.github/workflows/release.yml), which publishes to npm and -creates a GitHub Release with the package tarball and checksum. +and distributed from GitHub. Releases are automated by release-please +([`.github/workflows/release-please.yml`](../../.github/workflows/release-please.yml)): + +1. every push to `main` creates or updates a **Release PR** that bumps `package.json`, updates + `CHANGELOG.md`, and lists the changes since the last release (from conventional commits); +2. merging the Release PR creates the `vX.Y.Z` tag and the GitHub Release, and the same workflow run + publishes to npm and attaches the tarball + checksum. + +Only `fix:`, `feat:`, and breaking-change commits produce a release; `chore:`/`docs:` commits are +collected but do not trigger one on their own — use `fix:` for user-visible schema refreshes. +Never bump `package.json` by hand and never push `v*` tags by hand. +[`release.yml`](../../.github/workflows/release.yml) (tag-triggered) remains only as an emergency +fallback if the automation is broken. ## Preconditions - The public OpenAPI snapshot and generated command reference are current (`pnpm sync:openapi:check`). - `pnpm check` and `pnpm build` pass; opt-in live checks pass if relevant. -- The version in `package.json` is bumped and the changelog/release notes are reviewed. +- The Release PR's version bump and generated notes look right (edit the PR body to adjust notes). - The `asknews-cli` public OAuth client is registered for the target environment. ## Local package verification @@ -31,24 +41,21 @@ embedded AskNews skill. It must not contain credentials, `.env` files, tests, or ## Cut a release -```bash -# after the version bump lands on main -git tag v0.1.0 -git push origin v0.1.0 -``` - -The release workflow then: +Merge the open Release PR (title `chore(main): release X.Y.Z`). The workflow then: -1. installs dependencies and bundles `dist/` from the committed OpenAPI snapshot; -2. builds the versioned tarball and `.sha256`; -3. publishes to npm with `access: public` (using the `NPM_TOKEN` repository secret); -4. creates a GitHub Release with the tarball and checksum attached. +1. creates the tag and GitHub Release with the changelog notes; +2. installs dependencies and bundles `dist/` from the committed OpenAPI snapshot; +3. builds the versioned tarball and `.sha256`; +4. publishes to npm with `access: public` (using the `NPM_TOKEN` repository secret); +5. attaches the tarball and checksum to the GitHub Release. -`JS-DevTools/npm-publish` is a no-op if the `package.json` version is already on npm, so re-running a -tag is safe. +`JS-DevTools/npm-publish` is a no-op if the `package.json` version is already on npm, so re-running +the workflow is safe. The npm badge in the README reflects the published version. ## One-time setup - Create an automation token in the `@emergentmethods` npm org and add it as the `NPM_TOKEN` repository secret. -- Validate the pipeline with a pre-release tag (for example `v0.0.1-rc.0`) before the first real tag. +- The `NPM_TOKEN` must be an npm **Automation** token (classic Publish tokens fail with EOTP in CI). +- The GitHub organization must allow GitHub Actions to create pull requests (Org Settings → Actions → + General → Workflow permissions), or release-please cannot open the Release PR. diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 0000000..d15d86b --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", + "release-type": "node", + "bump-minor-pre-major": true, + "include-component-in-tag": false, + "packages": { + ".": {} + } +}