Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Release Please
on:
push:
branches:
- main
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
jobs:
release_please:
runs-on: ubuntu-latest
permissions:
contents: write
issues: write
pull-requests: write
steps:
- uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5
with:
token: ${{ secrets.GH_RELEASE_TOKEN }}
config-file: release-please-config.json
manifest-file: .release-please-manifest.json
17 changes: 4 additions & 13 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -1,22 +1,13 @@
# Cut a release whenever a new tag is pushed to the repo.
# Build and publish whenever Release Please creates a version tag.
name: Release
on:
# Can be triggered from the tag.yaml workflow
workflow_call:
inputs:
tag_name:
required: true
type: string
secrets:
publish_token:
required: true
# Can be triggered from the tag.yaml workflow
# Recover an existing tag whose release did not finish.
workflow_dispatch:
inputs:
tag_name:
required: true
type: string
# Or, developers can manually push a tag from their clone
# Release Please creates version tags after its release PR lands.
push:
tags:
- "v*.*.*"
Expand All @@ -41,4 +32,4 @@ jobs:
contents: write
id-token: write
secrets:
publish_token: ${{ secrets.publish_token || secrets.BCR_PUBLISH_TOKEN }}
publish_token: ${{ secrets.BCR_PUBLISH_TOKEN }}
64 changes: 0 additions & 64 deletions .github/workflows/tag.yaml

This file was deleted.

1 change: 1 addition & 0 deletions .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ ".": "0.9.1" }
25 changes: 13 additions & 12 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@

Follow [docs/releasing.md](docs/releasing.md).

- Use `.github/workflows/tag.yaml` as the normal release entrypoint. Dispatch it
on `main` without inputs; it chooses the version from Conventional Commits.
- Before dispatching, confirm `main` CI and Verify Hooks are green, no tag or
release run is active, the latest tag/release is known, and
`BCR_PUBLISH_TOKEN` is a Classic PAT with `repo` and `workflow` scopes that
can push to `formatjs/bazel-central-registry` and open the upstream PR.
- Do not invent a version or push a tag for a normal patch or minor release.
- Use `release.yaml` only to recover an existing tag that was not released. Use
`publish.yaml` only to retry BCR publication for an existing release.
- A major version requires explicit confirmation. The tag workflow may create
the tag, but intentionally skips the release and BCR jobs for a major bump.
- Release Please opens or updates the version bump PR after commits land on
`main`. Merge that PR to publish automatically.
- Before merging, confirm `main` CI and Verify Hooks are green, no release run
is active, and the proposed version is expected.
- `GH_RELEASE_TOKEN` and `BCR_PUBLISH_TOKEN` must be Classic PATs with `repo`
and `workflow` scopes. The BCR token must be able to push to
`formatjs/bazel-central-registry` and open the upstream PR.
- Do not invent a version or push a tag. Merging a major version PR is explicit
confirmation of the major release.
- Release Please tags trigger `release.yaml` automatically. Dispatch it only to
recover an existing tag. Use `publish.yaml` only to retry BCR publication for
an existing release.
- Monitor the workflow through the GitHub release and BCR handoff. Tag creation
alone is not completion.
- If the BCR push rejects the token, rotate the secret and retry `publish.yaml`
with the existing tag. Do not rerun the tag or release jobs.
with the existing tag. Do not rerun Release Please or create another tag.
19 changes: 6 additions & 13 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,10 @@ This means that any usage of `@rules_formatjs` on your system will point to this

## Releasing

The release workflow chooses the next version from Conventional Commits, creates
the tag and GitHub release, and opens the Bazel Central Registry PR. It also
runs on a schedule.
Release Please opens or updates a version bump PR from Conventional Commits.
Merging that PR creates the tag and GitHub release, then builds release assets,
creates attestations, and opens the Bazel Central Registry PR automatically.

To start a normal release without waiting for the schedule, dispatch the
no-input tag workflow on `main`:

```shell
gh workflow run tag.yaml --repo formatjs/rules_formatjs --ref main
```

Do not push a tag manually for a normal patch or minor release. See
[docs/releasing.md](docs/releasing.md) for preflight checks, monitoring, major
releases, and recovery.
Do not choose or push a tag manually. See
[docs/releasing.md](docs/releasing.md) for setup, checks, monitoring, and
recovery.
123 changes: 47 additions & 76 deletions docs/releasing.md
Original file line number Diff line number Diff line change
@@ -1,115 +1,86 @@
# Releasing

The normal release flow starts from `main` and chooses the next version from
Conventional Commits.
Release Please keeps a version bump PR current from Conventional Commits. Merge
that PR to publish.

```mermaid
flowchart LR
tag["Tag a Release"] --> version["Create the next semver tag"]
version --> release["Test, build, attest, and create the GitHub release"]
commit["Conventional commits land"] --> pr["Release Please updates version PR"]
pr -->|merge| tag["Create tag and GitHub release"]
tag --> release["Test, build, attest, and upload assets"]
release --> bcr["Open the Bazel Central Registry PR"]
```

## Normal release
## Setup

Before starting, confirm that CI and Verify Hooks are green on `main`, no tag or
release workflow is already running, and the latest release is the one you
expect. `BCR_PUBLISH_TOKEN` must belong to an account that can push to
`formatjs/bazel-central-registry`. It must be a Classic PAT with `repo` and
`workflow` scopes; fine-grained PATs cannot open the pull request against the
public upstream registry.
Two repository secrets are required:

```sh
gh run list \
--repo formatjs/rules_formatjs \
--workflow ci.yaml \
--branch main \
--limit 1
- `GH_RELEASE_TOKEN`: Classic PAT with `repo` and `workflow` scopes. Release
Please uses it so tag pushes trigger `release.yaml`.
- `BCR_PUBLISH_TOKEN`: Classic PAT with `repo` and `workflow` scopes. Its account
must be able to push to `formatjs/bazel-central-registry` and open the
upstream PR.

gh run list \
--repo formatjs/rules_formatjs \
--workflow verify-hooks.yml \
--branch main \
--limit 1

gh run list --repo formatjs/rules_formatjs --workflow tag.yaml --limit 5
gh release list --repo formatjs/rules_formatjs --limit 5
```

Dispatch the tag workflow. It has no inputs.
Set secrets interactively so tokens do not enter shell history:

```sh
gh workflow run tag.yaml --repo formatjs/rules_formatjs --ref main
gh secret set GH_RELEASE_TOKEN --repo formatjs/rules_formatjs
gh secret set BCR_PUBLISH_TOKEN --repo formatjs/rules_formatjs
```

The workflow uses `smlx/ccv` to inspect commits since the latest release. A
`fix` normally produces a patch, a `feat` produces a minor, and a breaking
change produces a major. Other commit types might not create a release.

Manual dispatch bypasses the two-week guard used by the scheduled run. Do not
push a tag or choose a version manually for a normal patch or minor release.
## Normal release

Find and watch the dispatched run:
Before merging the Release Please PR, confirm `main` CI and Verify Hooks are
green, no release run is active, and the proposed version is expected. A `fix`
normally produces a patch, a `feat` produces a minor, and a breaking change
produces a major.

```sh
gh run list \
--repo formatjs/rules_formatjs \
--workflow tag.yaml \
--event workflow_dispatch \
--limit 1

gh run watch RUN_ID --repo formatjs/rules_formatjs --exit-status
gh run list --repo formatjs/rules_formatjs --workflow ci.yaml --branch main --limit 1
gh run list --repo formatjs/rules_formatjs --workflow verify-hooks.yml --branch main --limit 1
gh run list --repo formatjs/rules_formatjs --workflow release-please.yml --limit 5
gh release list --repo formatjs/rules_formatjs --limit 5
```

Completion means all of the following are true:

- the new tag points at the intended `main` commit;
- the GitHub release exists with the source and docs archives;
- release attestations were created;
- the publish job opened or updated the BCR PR.
Merge the Release Please PR. That merge is explicit approval of its version,
including a major bump. Release Please creates the tag and GitHub release. The
tag triggers `release.yaml`, which builds assets, creates attestations, updates
the release, and opens the BCR PR.

```sh
gh run list --repo formatjs/rules_formatjs --workflow release.yaml --limit 1
gh run watch RUN_ID --repo formatjs/rules_formatjs --exit-status
gh release view TAG --repo formatjs/rules_formatjs
```

## Major releases

The tag workflow intentionally skips the release and BCR jobs when it computes
a major version. It may still create the tag. Confirm the version and tag before
continuing, then release that existing tag explicitly:

```sh
gh workflow run release.yaml \
--repo formatjs/rules_formatjs \
--ref main \
-f tag_name=TAG
```
Completion means the tag points at the Release Please merge, the GitHub release
contains source and docs archives, attestations exist, and the BCR PR is open.

## Recovery

Use the narrower workflows only when resuming an existing release:

- If the tag exists but the GitHub release does not, dispatch `release.yaml`
with that tag.
- If the Release Please PR is missing or stale, dispatch
`release-please.yml` on `main`.
- If the tag exists but assets or attestations are missing, dispatch
`release.yaml` with that tag.
- If the GitHub release exists but BCR publication failed, dispatch
`publish.yaml` with that tag.
- If the BCR push reports `Invalid username or token`, rotate
`BCR_PUBLISH_TOKEN` with a valid Classic PAT that has `repo` and `workflow`
scopes, then retry `publish.yaml`. Do not rerun the tag or release workflow.

Set or rotate the repository secret interactively so the token is not written
to shell history:
- If the BCR push rejects its token, rotate `BCR_PUBLISH_TOKEN`, then retry
`publish.yaml`. Do not rerun Release Please or create another tag.

```sh
gh secret set BCR_PUBLISH_TOKEN --repo formatjs/rules_formatjs
```
gh workflow run release-please.yml --repo formatjs/rules_formatjs --ref main

gh workflow run release.yaml \
--repo formatjs/rules_formatjs \
--ref main \
-f tag_name=TAG

```sh
gh workflow run publish.yaml \
--repo formatjs/rules_formatjs \
--ref main \
-f tag_name=TAG
```

Do not use either recovery workflow to invent a new version. Do not set the
version in `MODULE.bazel`; the BCR publisher patches it in the registry PR.
Do not invent a version or push a tag. Keep `MODULE.bazel` version blank;
Release Please updates `version.txt`, while the BCR publisher sets the module
version in its registry PR.
11 changes: 11 additions & 0 deletions release-please-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
"release-type": "simple",
"include-component-in-tag": false,
"changelog-type": "github",
"packages": {
".": {
"package-name": "rules_formatjs"
}
}
}
1 change: 1 addition & 0 deletions version.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.9.1
Loading