diff --git a/.github/workflows/publish-cli.yml b/.github/workflows/publish-cli.yml index 28aa0fb..465be78 100644 --- a/.github/workflows/publish-cli.yml +++ b/.github/workflows/publish-cli.yml @@ -32,10 +32,9 @@ jobs: fi STABLE_SEMVER_RE='^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$' - NIGHTLY_SEMVER_RE='^v0\.0\.[0-9]+-nightly\.[0-9]{8}\.[0-9]+$' - if [[ ! "$GITHUB_REF_NAME" =~ $STABLE_SEMVER_RE ]] && [[ ! "$GITHUB_REF_NAME" =~ $NIGHTLY_SEMVER_RE ]]; then + if [[ ! "$GITHUB_REF_NAME" =~ $STABLE_SEMVER_RE ]]; then echo "Unsupported release tag: ${GITHUB_REF_NAME}" - echo "Release tags must use stable SemVer form vMAJOR.MINOR.PATCH or nightly form v0.0.N-nightly.YYYYMMDD.NUMBER." + echo "Release tags must use stable SemVer form vMAJOR.MINOR.PATCH." exit 1 fi @@ -61,12 +60,14 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 + - uses: actions/setup-node@v4 + with: + node-version: "24" - name: Resolve release version id: release run: | set -euo pipefail - NIGHTLY_SEMVER_RE='^v0\.0\.[0-9]+-nightly\.[0-9]{8}\.[0-9]+$' if [ "$GITHUB_REF" = "refs/heads/main" ]; then DATE_PART="$(date -u +%Y%m%d)" @@ -87,13 +88,16 @@ jobs: LATEST="false" else RELEASE_TAG="$GITHUB_REF_NAME" - if [[ "$GITHUB_REF_NAME" =~ $NIGHTLY_SEMVER_RE ]]; then - PRERELEASE="true" - LATEST="false" - else - PRERELEASE="false" - LATEST="auto" + NPM_VERSION="$(node -p "require('./package.json').version")" + + if [ "v${NPM_VERSION}" != "$RELEASE_TAG" ]; then + echo "Release tag ${RELEASE_TAG} does not match package.json version ${NPM_VERSION}." + echo "Stable releases must be created from the Release Please release PR commit." + exit 1 fi + + PRERELEASE="false" + LATEST="auto" fi { @@ -401,24 +405,20 @@ jobs: - name: Upgrade npm run: npm install -g npm@11 - - name: Resolve npm version + - name: Verify npm package version id: npm_version env: CLI_VERSION: ${{ needs.resolve-release.outputs.cli_version }} run: | set -euo pipefail - VERSION="${CLI_VERSION#v}" - if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - echo "Refusing to publish non-stable version to npm: ${CLI_VERSION}" + VERSION="$(node -p "require('./package.json').version")" + if [ "v${VERSION}" != "$CLI_VERSION" ]; then + echo "Refusing to publish npm version ${VERSION} for release ${CLI_VERSION}." + echo "package.json must match the stable release tag." exit 1 fi echo "version=${VERSION}" >> "$GITHUB_OUTPUT" - - name: Set package version - run: | - npm version "${{ steps.npm_version.outputs.version }}" \ - --no-git-tag-version --allow-same-version - - name: Verify release assets exist env: VERSION: ${{ steps.npm_version.outputs.version }} diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml new file mode 100644 index 0000000..86b4c7a --- /dev/null +++ b/.github/workflows/release-please.yml @@ -0,0 +1,23 @@ +name: Release Please + +on: + push: + branches: + - main + +permissions: + contents: write + issues: write + pull-requests: write + +jobs: + release-please: + runs-on: ubuntu-latest + steps: + - uses: googleapis/release-please-action@5c625bfb5d1ff62eadeeb3772007f7f66fdcf071 # v4 + with: + # Use a PAT so Release Please tags/releases trigger publish-cli.yml. + # GITHUB_TOKEN-created refs do not trigger follow-on workflow runs. + token: ${{ secrets.RELEASE_PLEASE_TOKEN }} + config-file: release-please-config.json + manifest-file: .release-please-manifest.json diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 0000000..63c033c --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.0.4" +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 402a00e..8b4ba02 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -88,13 +88,26 @@ The publish workflow builds signed binaries for `linux-amd64`, `linux-arm64`, `macos-amd64`, `macos-arm64`, and `windows-amd64`. It publishes stable release assets from SemVer tags. -To cut a stable release, merge the release commit to `main`, tag that commit -with a SemVer tag such as `v1.2.3`, and push the tag. Prerelease and build -metadata tags are not stable release tags. The publish workflow also rejects -stable release tags that are not reachable from `origin/main`. - -Required repository variable for stable release publishing: - +Stable releases are managed by Release Please. Normal feature and fix commits +land on `main` using Conventional Commit messages. Release Please opens or +updates a release PR that bumps `package.json`, updates +`.release-please-manifest.json`, and updates `CHANGELOG.md`. Merge that release +PR to cut a stable release. Release Please then creates the SemVer tag and +GitHub Release, such as `v1.2.3`, and the tag-triggered publish workflow +attaches signed binaries and publishes npm. + +Do not manually bump `package.json` outside a Release Please release PR. The +publish workflow rejects stable tags when `package.json` does not match the tag, +or when the tag is not reachable from `origin/main`. + +Prerelease and build metadata tags are not stable release tags. Nightly builds +remain automated from `main` and publish to the mutable `nightly` GitHub Release; +they are not npm releases and are separate from the stable Release Please flow. + +Required repository secret and variable for stable release publishing: + +- `RELEASE_PLEASE_TOKEN` (a GitHub token that can create release PRs, tags, and + releases that trigger follow-on workflows) - `VOLCANO_FIRST_PARTY_DEVICE_CLIENT_ID_PRODUCTION` Release assets include platform binaries, adjacent `.sigstore.json` bundles, diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 0000000..27fe16f --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,11 @@ +{ + "bootstrap-sha": "363ccef4a5c92b78795ee65cab4dd491685e0030", + "include-component-in-tag": false, + "packages": { + ".": { + "release-type": "node", + "package-name": "@volcano.dev/cli", + "changelog-path": "CHANGELOG.md" + } + } +}