diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d045ebbbdf3cd..03b56636e9736 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,8 +1,6 @@ name: CI on: - release: - types: [published] pull_request: branches: - '**' @@ -10,6 +8,8 @@ on: - '**.md' merge_group: push: + tags: + - '*' branches: - develop paths-ignore: @@ -17,7 +17,7 @@ on: concurrency: # merge_group runs group by the merge-group ref so a recreated group cancels the stale run; - # push/release runs group by run_id on purpose (never cancel a deploy in progress) + # push (incl. tag) runs group by run_id on purpose (never cancel a deploy in progress) group: ${{ github.workflow }}-${{ github.head_ref || (github.event_name == 'merge_group' && github.ref) || github.run_id }} cancel-in-progress: true @@ -189,7 +189,7 @@ jobs: name: 🚀 Notify external services - draft runs-on: ubuntu-24.04-arm needs: [release-versions] - if: github.event_name == 'release' + if: startsWith(github.ref, 'refs/tags/') steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -199,30 +199,22 @@ jobs: ref: ${{ github.ref }} - name: Register release on cloud as Draft - if: github.event_name == 'release' + if: startsWith(github.ref, 'refs/tags/') env: UPDATE_TOKEN: ${{ secrets.UPDATE_TOKEN }} run: | REPO_VERSION=$(node -p "require('./package.json').version") - if [[ '${{ github.event_name }}' = 'release' ]]; then - GIT_TAG="${GITHUB_REF#*tags/}" - GIT_BRANCH="" - ARTIFACT_NAME="${REPO_VERSION}" - RC_VERSION=$GIT_TAG + GIT_TAG="${GITHUB_REF#*tags/}" + GIT_BRANCH="" + ARTIFACT_NAME="${REPO_VERSION}" + RC_VERSION=$GIT_TAG - if [[ '${{ needs.release-versions.outputs.release }}' = 'release-candidate' ]]; then - RC_RELEASE=candidate - elif [[ '${{ needs.release-versions.outputs.release }}' = 'latest' ]]; then - RC_RELEASE=stable - fi - else - GIT_TAG="" - GIT_BRANCH="${GITHUB_REF#*heads/}" - ARTIFACT_NAME="${REPO_VERSION}.$GITHUB_SHA" - RC_VERSION="${REPO_VERSION}" - RC_RELEASE=develop - fi; + if [[ '${{ needs.release-versions.outputs.release }}' = 'release-candidate' ]]; then + RC_RELEASE=candidate + elif [[ '${{ needs.release-versions.outputs.release }}' = 'latest' ]]; then + RC_RELEASE=stable + fi curl -H "Content-Type: application/json" -H "X-Update-Token: $UPDATE_TOKEN" -d \ "{\"nodeVersion\": \"${{ needs.release-versions.outputs.node-version }}\", \"denoVersion\": \"${{ needs.release-versions.outputs.deno-version }}\",\"compatibleMongoVersions\": [\"8.0\"], \"commit\": \"$GITHUB_SHA\", \"tag\": \"$RC_VERSION\", \"branch\": \"$GIT_BRANCH\", \"artifactName\": \"$ARTIFACT_NAME\", \"releaseType\": \"draft\", \"draftAs\": \"$RC_RELEASE\"}" \ @@ -328,7 +320,7 @@ jobs: - production - coverage exclude: - - type: ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'production' || '' }} + - type: ${{ (!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/develop') && 'production' || '' }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -360,7 +352,7 @@ jobs: [rocketchat], ] type: - - ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }} + - ${{ (!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }} - fips exclude: - arch: arm64 @@ -384,7 +376,7 @@ jobs: if: github.actor != 'dependabot[bot]' env: # add suffix for the extra images with coverage if building for production - DOCKER_TAG_SUFFIX_ROCKETCHAT: ${{ matrix.type == 'coverage' && (github.event_name == 'release' || github.ref == 'refs/heads/develop') && '-cov' || '' }} + DOCKER_TAG_SUFFIX_ROCKETCHAT: ${{ matrix.type == 'coverage' && (startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/develop') && '-cov' || '' }} with: CR_USER: ${{ secrets.CR_USER }} CR_PAT: ${{ secrets.CR_PAT }} @@ -394,7 +386,7 @@ jobs: arch: ${{ matrix.arch }} service: ${{ matrix.service[0] }} type: ${{ matrix.type }} - publish-image: ${{ github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop' }} + publish-image: ${{ github.event.pull_request.head.repo.full_name == github.repository || startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/develop' }} - name: Image ${{ matrix.service[1] || '"skipped"' }} uses: ./.github/actions/build-docker @@ -410,7 +402,7 @@ jobs: arch: ${{ matrix.arch }} service: ${{ matrix.service[1] }} type: ${{ matrix.type }} - publish-image: ${{ github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop' }} + publish-image: ${{ github.event.pull_request.head.repo.full_name == github.repository || startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/develop' }} setup-docker: false - name: Image ${{ matrix.service[2] || '"skipped"' }} @@ -427,7 +419,7 @@ jobs: arch: ${{ matrix.arch }} service: ${{ matrix.service[2] }} type: ${{ matrix.type }} - publish-image: ${{ github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop' }} + publish-image: ${{ github.event.pull_request.head.repo.full_name == github.repository || startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/develop' }} setup-docker: false - name: Image ${{ matrix.service[3] || '"skipped"' }} @@ -444,7 +436,7 @@ jobs: arch: ${{ matrix.arch }} service: ${{ matrix.service[3] }} type: ${{ matrix.type }} - publish-image: ${{ github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop' }} + publish-image: ${{ github.event.pull_request.head.repo.full_name == github.repository || startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/develop' }} setup-docker: false build-gh-docker-publish: @@ -458,7 +450,7 @@ jobs: steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') + if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/develop') with: sparse-checkout: | docker-compose-ci.yml @@ -467,7 +459,7 @@ jobs: ref: ${{ github.ref }} - name: Login to GitHub Container Registry - if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') + if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/develop') uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 with: registry: ghcr.io @@ -475,7 +467,7 @@ jobs: password: ${{ secrets.CR_PAT }} - name: Download manifests - if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') + if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/develop') uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: manifests-* @@ -483,7 +475,7 @@ jobs: merge-multiple: true - name: Create and push multi-arch manifests - if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') + if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/develop') run: | set -o xtrace shopt -s nullglob @@ -571,7 +563,6 @@ jobs: run: | ./actionlint -color - # gating `checks` also skips every e2e test job (they all `need` it); # test-storybook and test-unit don't, so they carry the same gate below checks: @@ -659,7 +650,7 @@ jobs: deno-version: ${{ needs.release-versions.outputs.deno-version }} lowercase-repo: ${{ needs.release-versions.outputs.lowercase-repo }} gh-docker-tag: ${{ needs.release-versions.outputs.gh-docker-tag }} - retries: ${{ (github.event_name == 'release' || github.event_name == 'merge_group' || github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master') && 2 || 0 }} + retries: ${{ (startsWith(github.ref, 'refs/tags/') || github.event_name == 'merge_group' || github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master') && 2 || 0 }} secrets: CR_USER: ${{ secrets.CR_USER }} CR_PAT: ${{ secrets.CR_PAT }} @@ -750,7 +741,7 @@ jobs: deno-version: ${{ needs.release-versions.outputs.deno-version }} lowercase-repo: ${{ needs.release-versions.outputs.lowercase-repo }} gh-docker-tag: ${{ needs.release-versions.outputs.gh-docker-tag }} - retries: ${{ (github.event_name == 'release' || github.event_name == 'merge_group' || github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master') && 2 || 0 }} + retries: ${{ (startsWith(github.ref, 'refs/tags/') || github.event_name == 'merge_group' || github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master') && 2 || 0 }} secrets: CR_USER: ${{ secrets.CR_USER }} CR_PAT: ${{ secrets.CR_PAT }} @@ -821,7 +812,7 @@ jobs: deno-version: ${{ needs.release-versions.outputs.deno-version }} lowercase-repo: ${{ needs.release-versions.outputs.lowercase-repo }} gh-docker-tag: ${{ needs.release-versions.outputs.gh-docker-tag }} - retries: ${{ (github.event_name == 'release' || github.event_name == 'merge_group' || github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master') && 2 || 0 }} + retries: ${{ (startsWith(github.ref, 'refs/tags/') || github.event_name == 'merge_group' || github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master') && 2 || 0 }} secrets: CR_USER: ${{ secrets.CR_USER }} CR_PAT: ${{ secrets.CR_PAT }} @@ -860,7 +851,7 @@ jobs: run: yarn build - name: Login to GitHub Container Registry - if: (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') && github.actor != 'dependabot[bot]' + if: (github.event.pull_request.head.repo.full_name == github.repository || startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/develop') && github.actor != 'dependabot[bot]' uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 with: registry: ghcr.io @@ -875,7 +866,7 @@ jobs: # Download Docker images from build artifacts - name: Download Docker images uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - if: github.event.pull_request.head.repo.full_name != github.repository && github.event_name != 'release' && github.ref != 'refs/heads/develop' + if: github.event.pull_request.head.repo.full_name != github.repository && !startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/develop' with: pattern: 'docker-image-rocketchat-amd64-coverage' path: /tmp/docker-images @@ -883,7 +874,7 @@ jobs: # Load Docker images - name: Load Docker images - if: github.event.pull_request.head.repo.full_name != github.repository && github.event_name != 'release' && github.ref != 'refs/heads/develop' + if: github.event.pull_request.head.repo.full_name != github.repository && !startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/develop' shell: bash run: | set -o xtrace @@ -985,7 +976,23 @@ jobs: tests-done: name: ✅ Tests Done runs-on: ubuntu-24.04-arm - needs: [test-guard, checks, test-unit, test-api, test-ui, test-api-ee, test-ui-ee, test-api-livechat, test-api-livechat-ee, test-api-apps-deno-ee, test-api-fips, test-api-livechat-fips, test-ui-fips, test-federation-matrix] + needs: + [ + test-guard, + checks, + test-unit, + test-api, + test-ui, + test-api-ee, + test-ui-ee, + test-api-livechat, + test-api-livechat-ee, + test-api-apps-deno-ee, + test-api-fips, + test-api-livechat-fips, + test-ui-fips, + test-federation-matrix, + ] if: always() && needs.test-guard.outputs.skip-tests != 'true' steps: - name: Test finish aggregation @@ -1047,7 +1054,7 @@ jobs: deploy: name: 🚀 Publish build assets runs-on: ubuntu-24.04-arm - if: github.event_name == 'release' || github.ref == 'refs/heads/develop' + if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/develop' needs: [build-gh-docker-publish, release-versions] steps: @@ -1073,7 +1080,7 @@ jobs: run: | REPO_VERSION=$(node -p "require('./package.json').version") - if [[ "${{ github.event_name }}" = 'release' ]]; then + if [[ "${{ startsWith(github.ref, 'refs/tags/') }}" = 'true' ]]; then ARTIFACT_NAME="${REPO_VERSION}" else ARTIFACT_NAME="${REPO_VERSION}.$GITHUB_SHA" @@ -1128,7 +1135,7 @@ jobs: password: ${{ secrets.CR_PAT }} - name: Download manifests - if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') + if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/develop') uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: manifests-* @@ -1245,7 +1252,7 @@ jobs: run: | REPO_VERSION=$(node -p "require('./package.json').version") - if [[ '${{ github.event_name }}' = 'release' ]]; then + if [[ '${{ startsWith(github.ref, 'refs/tags/') }}' = 'true' ]]; then GIT_TAG="${GITHUB_REF#*tags/}" GIT_BRANCH="" ARTIFACT_NAME="${REPO_VERSION}" @@ -1271,10 +1278,46 @@ jobs: # Makes build fail if the release isn't there curl --fail "https://releases.rocket.chat/$RC_VERSION/info" + publish-github-release: + name: 🚀 Publish GitHub Release + runs-on: ubuntu-24.04-arm + if: startsWith(github.ref, 'refs/tags/') + needs: [docker-image-publish, release-versions] + permissions: + contents: write + steps: + # the release is created as a draft by the release-action and is only published + # here, after all artifacts are available, so users never see a release + # they can't install yet + - name: Remove draft from release + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + + # drafts are not addressable by tag (GET /releases/tags/{tag} returns 404), + # so find the release id by listing; the draft was created right before the + # tag push, so it's always within the most recent releases + RELEASE_ID=$(gh api "repos/${GITHUB_REPOSITORY}/releases?per_page=100" \ + --jq "[.[] | select(.tag_name == \"${GITHUB_REF_NAME}\")][0].id // empty") + + if [[ -z "$RELEASE_ID" ]]; then + echo "No release found for tag ${GITHUB_REF_NAME}" + exit 1 + fi + + MAKE_LATEST=false + if [[ '${{ needs.release-versions.outputs.release }}' == 'latest' && '${{ needs.release-versions.outputs.latest-release }}' == "$GITHUB_REF_NAME" ]]; then + MAKE_LATEST=true + fi + + gh api -X PATCH "repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}" \ + -F draft=false -f make_latest="$MAKE_LATEST" + docs-update: name: Update Version Durability - if: github.event_name == 'release' + if: startsWith(github.ref, 'refs/tags/') needs: - docker-image-publish diff --git a/docs/release-process.md b/docs/release-process.md new file mode 100644 index 0000000000000..e75e36fa37fc2 --- /dev/null +++ b/docs/release-process.md @@ -0,0 +1,101 @@ +# Release Process + +This document describes how Rocket.Chat releases are produced, from the moment a release is started until all artifacts are published and users are notified. It covers the automation implemented by the GitHub workflows in `.github/workflows/` and the custom changesets-based release action in `packages/release-action`. + +## Overview + +Releases are driven by **git tags**: the release action bumps versions, publishes npm packages, creates an annotated git tag, and pushes it. The tag push triggers the main CI pipeline (`.github/workflows/ci.yml`), which builds, tests, and publishes all release artifacts. + +The GitHub Release is created as a **draft** at the moment the tag is pushed and is only flipped to a published release at the end of the pipeline, after the Docker images are available on Docker Hub. This guarantees that a release is never announced before its artifacts exist. If the pipeline fails midway, the release stays a draft until the workflow is re-run (or the release is published manually after fixing the problem). + +Versioning and changelogs are managed with [changesets](https://github.com/changesets/changesets). Every PR that should be mentioned in the changelog adds a changeset file under `.changeset/`; the release action consumes them when bumping versions. + +## Release types and entry points + +### Develop builds + +Every push to the `develop` branch runs the full CI pipeline and publishes: + +- Docker images to GHCR and Docker Hub with the `develop` tag. +- A build tarball to S3, named `rocket.chat-..tgz`. +- A registration on `releases.rocket.chat` with `releaseType: develop`. + +No git tag, npm publish, or GitHub Release is involved. + +### Release candidate (`next`) + +A release candidate is started by the scheduled workflow `release-candidate.yml` (monthly cron) or manually via `new-release.yml` (`workflow_dispatch` with action `next`). It runs the release action's `bumpNextVersion`, which: + +1. Enters changesets pre-release mode (`rc`) and bumps all packages (e.g. `7.10.0-rc.0`, or `-rc.N` for subsequent candidates). +2. Updates version references across the repo files. +3. Creates (or force-pushes) the `release-X.Y.Z` branch with the bump commit. +4. Publishes the npm packages. +5. Creates the annotated tag `X.Y.Z-rc.N` and pushes branch and tag. +6. For the first candidate (`rc.0`) only: opens the `Release X.Y.Z` pull request from `release-X.Y.Z` to `master`. +7. Creates a **draft, pre-release** GitHub Release for the tag. + +The tag push then triggers the CI pipeline described below. + +### Final release (`publish-final`) + +When the `Release X.Y.Z` pull request is merged into `master`, the push to `master` triggers `publish-release.yml`, which runs the release action's `publishRelease` with `mergeFinal: true`. It: + +1. Exits changesets pre-release mode and bumps all packages to the final version. +2. Commits the bump, publishes the npm packages. +3. Creates the annotated tag `X.Y.Z` and pushes it (`git push --follow-tags`). +4. Creates a **draft** GitHub Release for the tag. + +### Patch release (`cut`) + +Patch releases are started manually via `new-release.yml` (`workflow_dispatch` with action `cut` and the release branch as base ref, e.g. `release-7.9.2`). `publishRelease` runs without `mergeFinal`: + +1. Bumps the patch version from the pending changesets on the release branch. +2. If the new version is the newest stable release, merges the release branch back into `master` (patches to older LTS branches skip this). +3. Publishes npm packages, tags, pushes, and creates a **draft** GitHub Release. + +There is also a `patch` action (`startPatchRelease`) that only prepares a patch release branch from an existing tag so fixes can be cherry-picked onto it; the actual release is then done with `cut`. + +> **Note:** all release workflows check out the repo with the `CI_PAT` token. This is required — tags pushed with the default `GITHUB_TOKEN` do **not** trigger workflows, so the CI pipeline would never run for the release. + +## The tag-push pipeline (`ci.yml`) + +Pushing a tag (any tag) triggers `ci.yml`. The relevant stages, in order: + +1. **`release-versions`** — classifies the tag by name: `X.Y.Z` → release `latest`, `X.Y.Z-rc.N` → `release-candidate`. It also computes `latest-release`, the newest non-rc/non-beta tag in the repo, used later to decide whether this tag should become `latest` on Docker Hub and GitHub. +2. **`notify-draft-services`** — registers the version on `releases.rocket.chat` as a draft (`draftAs: candidate` or `stable`), so internal services know a release is in flight. +3. **Build and tests** — packages and the Meteor app are built, and the full test suite (unit, API, UI, apps, federation) runs. Tag pushes never skip tests: the merge-queue test-guard only skips when the exact commit already has a successful "Tests Done" check, which release bump commits don't. +4. **GHCR publish** — Docker images (rocketchat + services, including `-fips` variants) are built and pushed to GHCR tagged with the tag name. +5. **`deploy`** — the production build tarball is GPG-signed and uploaded to S3 as `rocket.chat-.tgz`. +6. **`docker-image-publish`** — images are copied from GHCR to Docker Hub with: + - the version tag (e.g. `7.10.0` or `7.10.0-rc.3`); + - `release-candidate` for RCs, or `latest` for the newest stable version; + - the commit sha (`sha-`); + - `-fips` suffixed variants of all of the above for FIPS images. +7. **`notify-services`** — flips the `releases.rocket.chat` registration from draft to final and verifies the release info endpoint responds. +8. **`publish-github-release`** — finds the draft GitHub Release for the tag and publishes it (`draft: false`), setting `make_latest` only when the tag is the newest stable release (RCs and patches to older versions never become `latest`). +9. **`docs-update`** — updates the version durability table in the documentation. + +### Draft release lifecycle + +| Moment | GitHub Release state | +| --- | --- | +| Release action pushes tag + creates release | Draft (invisible to users) | +| CI builds/tests/publishes artifacts | Draft | +| `publish-github-release` (after Docker Hub publish) | Published; `latest` when applicable | + +If any stage fails, the release remains a draft. Re-running the failed workflow resumes publication; alternatively the draft can be published manually once the artifacts are confirmed in place. + +## Secrets involved + +| Secret | Used for | +| --- | --- | +| `CI_PAT` | Checkout/push in release workflows so tag pushes trigger CI | +| `NPM_TOKEN` | Publishing packages to npm | +| `UPDATE_TOKEN` | Registering releases on `releases.rocket.chat` | +| `CR_USER` / `CR_PAT` | GHCR push/pull | +| `DOCKER_USER` / `DOCKER_PASS` | Docker Hub publish | +| `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` | S3 tarball upload | +| `GPG_PASSWORD` | Signing the build tarball | +| `D360_TOKEN` / `D360_USER_ID` | Documentation version durability update | + +The `publish-github-release` job uses the built-in `GITHUB_TOKEN` with job-level `contents: write` permission — publishing the release does not need to trigger any other workflow. diff --git a/packages/release-action/action.yml b/packages/release-action/action.yml index 23d7382aab6d8..7703940db1778 100644 --- a/packages/release-action/action.yml +++ b/packages/release-action/action.yml @@ -3,7 +3,7 @@ description: Action to cut and publish releases using changesets inputs: action: - description: "The main action to perform: publish, publish-final, bump or patch" + description: "The main action to perform: publish-final, cut, next, patch or update-pr-description" required: true base-ref: description: "Base ref to use for the release" diff --git a/packages/release-action/src/bumpNextVersion.ts b/packages/release-action/src/bumpNextVersion.ts index d8628e46cf242..28e2735e5c9d8 100644 --- a/packages/release-action/src/bumpNextVersion.ts +++ b/packages/release-action/src/bumpNextVersion.ts @@ -89,11 +89,13 @@ export async function bumpNextVersion({ } core.info('create release'); + // the release stays a draft until CI publishes all artifacts for the tag await octokit.rest.repos.createRelease({ name: newVersion, tag_name: newVersion, body: prBody, prerelease: newVersion.includes('-'), + draft: true, ...github.context.repo, }); } diff --git a/packages/release-action/src/publishRelease.ts b/packages/release-action/src/publishRelease.ts index d0706bdbdc740..6350bc3a28a3c 100644 --- a/packages/release-action/src/publishRelease.ts +++ b/packages/release-action/src/publishRelease.ts @@ -116,12 +116,14 @@ export async function publishRelease({ await pushChanges(); core.info('create release'); + // the release stays a draft until CI publishes all artifacts for the tag; + // a draft can't be 'latest', so CI decides make_latest when publishing it await octokit.rest.repos.createRelease({ name: newVersion, tag_name: newVersion, body: releaseBody, prerelease, - make_latest: isLatestRelease ? 'true' : 'false', + draft: true, ...github.context.repo, }); }