From 847b0a56e2701c48deff47f7af251a875881ee77 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Wed, 7 Feb 2024 11:06:46 +0100 Subject: [PATCH] ci: add new release process based on release-please (#849) Adds a new release process based on [release-please](https://github.com/googleapis/release-please). As soon as this gets merged, releases will work as follows: 1. PR merges will be collected by release-please into a release PR. The team at Supabase decides when a release is ready to go out, usually weekly or bi-weekly. 2. Every PR merge (that uses `feat:` or `fix:` titles) will result in a release candidate release with tag `rc`. Example: if the new release will be `2.140.0` then the RC release will be `rc2.140-rc.1`, and so on. 3. Once the release PR is merged, an official release will be published with the tag `v`, or per the example `v2.140.0`. 4. Releases with a patch version of `0` get a special branch `release/v2.140.0` which can be used to patch that and only that major+minor version, using the same process as above. 5. RC releases are tagged `rc` in NPM and regular ones as `latest`. Patched releases get the label `patched`. Similar to: - https://github.com/supabase/gotrue/pull/1391 --- .github/workflows/release.yml | 166 ++++++++++++++++++++++++++-------- src/lib/version.ts | 2 +- 2 files changed, 128 insertions(+), 40 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fdbc3d7c9..8c7554126 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,62 +4,150 @@ on: push: branches: - master - - next - - rc - workflow_dispatch: - inputs: - ref: - description: Tag or branch to check out for releasing - default: master - type: string - required: true + - release/* jobs: - release: - name: Release / Node ${{ matrix.node }} - strategy: - matrix: - node: ['20'] - + release_please: runs-on: ubuntu-latest - + permissions: + contents: write + pull-requests: write steps: - - if: ${{ inputs.ref != 'master' }} - run: Input ref is ${{ inputs.ref }} + - uses: google-github-actions/release-please-action@v4 + id: release + with: + release-type: go + target-branch: ${{ github.ref_name }} - uses: actions/checkout@v4 + if: ${{ steps.release.outputs.release_created == 'true' || steps.release.outputs.prs_created == 'true' }} with: - ref: ${{ inputs.ref || 'master' }} - fetch-depth: 0 # Get whole repo with all the information + fetch-depth: 0 + + - if: ${{ steps.release.outputs }} + id: versions + run: | + set -ex + + RELEASE_CANDIDATE=true + NOT_RELEASE_CANDIDATE='${{ steps.release.outputs.release_created }}' + if [ "$NOT_RELEASE_CANDIDATE" == "true" ] + then + RELEASE_CANDIDATE=false + fi + + MAIN_RELEASE_VERSION=x + RELEASE_VERSION=y + + if [ "$RELEASE_CANDIDATE" == "true" ] + then + # Release please doesn't tell you the candidate version when it + # creates the PR, so we have to take it from the title. + MAIN_RELEASE_VERSION=$(node -e "console.log('${{ steps.release.outputs.pr && fromJSON(steps.release.outputs.pr).title }}'.split(' ').reverse().find(x => x.match(/[0-9]+[.][0-9]+[.][0-9]+/)))") + + # Use git describe tags to identify the number of commits the branch + # is ahead of the most recent non-release-candidate tag, which is + # part of the rc. value. + RELEASE_VERSION=$MAIN_RELEASE_VERSION-rc.$(node -e "console.log('$(git describe --tags --exclude *rc*)'.split('-')[1])") + + # release-please only ignores releases that have a form like [A-Z0-9], so prefixing with rc + RELEASE_NAME="rc$RELEASE_VERSION" + else + MAIN_RELEASE_VERSION=${{ steps.release.outputs.major }}.${{ steps.release.outputs.minor }}.${{ steps.release.outputs.patch }} + RELEASE_VERSION="$MAIN_RELEASE_VERSION" + RELEASE_NAME="v$RELEASE_VERSION" + fi + + echo "MAIN_RELEASE_VERSION=${MAIN_RELEASE_VERSION}" >> "${GITHUB_ENV}" + echo "RELEASE_VERSION=${RELEASE_VERSION}" >> "${GITHUB_ENV}" + echo "RELEASE_CANDIDATE=${RELEASE_CANDIDATE}" >> "${GITHUB_ENV}" + echo "RELEASE_NAME=${RELEASE_NAME}" >> "${GITHUB_ENV}" + + echo "MAIN_RELEASE_VERSION=${MAIN_RELEASE_VERSION}" >> "${GITHUB_OUTPUT}" + echo "RELEASE_VERSION=${RELEASE_VERSION}" >> "${GITHUB_OUTPUT}" + echo "RELEASE_CANDIDATE=${RELEASE_CANDIDATE}" >> "${GITHUB_OUTPUT}" + echo "RELEASE_NAME=${RELEASE_NAME}" >> "${GITHUB_OUTPUT}" - - name: Set up Node - uses: actions/setup-node@v1 + - uses: actions/setup-node@v4 + if: ${{ steps.release.outputs.release_created == 'true' || steps.release.outputs.prs_created == 'true' }} with: - node-version: ${{ matrix.node }} + node-version: 20 + + - name: Build release artifacts + if: ${{ steps.release.outputs.release_created == 'true' || steps.release.outputs.prs_created == 'true' }} + run: | + set -ex + + echo "export const version = '$RELEASE_VERSION'" > src/lib/version.ts - - run: | npm ci npm run build - - name: Create a release for @supabase/auth-js - run: npx semantic-release -r 'https://github.com/supabase/gotrue-js.git' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + for f in package.json package-lock.json + do + sed -i 's|"version": "0.0.0",|"version": "'"$RELEASE_VERSION"'",|g' "$f" + done + + echo '//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}' > ~/.npmrc + + DIST_TAG=patched + if [ "$RELEASE_CANDIDATE" == "true" ] + then + DIST_TAG=rc + elif [ "$GITHUB_REF" == "refs/heads/main" ] && [ "$GITHUB_REF" == "refs/heads/master" ] + then + # This is the main branch and it's not a prerelease, so the dist-tag should be `latest`. + DIST_TAG=latest + fi + + echo "Publishing auth-js now..." + + npm publish --tag "$DIST_TAG" + + echo "Publishing gotrue-js now..." + + for f in package.json package-lock.json + do + sed -i 's|\(["/]\)auth-js|\1gotrue-js|g' "$f" + done - - name: Publish @supabase/gotrue-js - env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + npm publish --tag "$DIST_TAG" + + - name: Create GitHub release and branches + if: ${{ steps.release.outputs.release_created == 'true' || steps.release.outputs.prs_created == 'true' }} run: | - if [ "0.0.0" != $(jq -r '.version' package.json) ] + set -ex + + if [ "$RELEASE_CANDIDATE" == "true" ] then - echo '//registry.npmjs.org/:_authToken=${NPM_TOKEN}' > ~/.npmrc + PR_NUMBER='${{ steps.release.outputs.pr && fromJSON(steps.release.outputs.pr).number }}' + + GH_TOKEN='${{ github.token }}' gh release \ + create $RELEASE_NAME \ + --title "v$RELEASE_VERSION" \ + --prerelease \ + -n "This is a release candidate. See release-please PR #$PR_NUMBER for context." + + GH_TOKEN='${{ github.token }}' gh pr comment "$PR_NUMBER" \ + -b "Release candidate [v$RELEASE_VERSION](https://github.com/supabase/gotrue-js/releases/tag/$RELEASE_NAME) published." + else + if [ "$GITHUB_REF" == "refs/heads/main" ] || [ "$GITHUB_REF" == "refs/heads/master" ] + then + IS_PATCH_ZERO=$(node -e "console.log('$RELEASE_VERSION'.endsWith('.0'))") - for f in package.json package-lock.json - do - sed -i 's|\(["/]\)auth-js|\1gotrue-js|g' "$f" - done + if [ "$IS_PATCH_ZERO" == "true" ] + then + # Only create release branch if patch version is 0, as this + # means that the release can be patched in the future. - npm publish --tag latest + GH_TOKEN='${{ github.token }}' gh api \ + --method POST \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + /repos/supabase/gotrue-js/git/refs \ + -f "ref=refs/heads/release/${RELEASE_VERSION}" \ + -f "sha=$GITHUB_SHA" + fi + fi fi diff --git a/src/lib/version.ts b/src/lib/version.ts index 9ccc1f938..aee3a05cf 100644 --- a/src/lib/version.ts +++ b/src/lib/version.ts @@ -1,2 +1,2 @@ -// Generated by genversion. +// Will be overwriten by .github/workflows/release.yml export const version = '0.0.0'