From 520936b5596b51894b8a08a0c5ddfc8a25477dde Mon Sep 17 00:00:00 2001 From: Evan Sims Date: Mon, 4 Dec 2023 03:09:08 -0500 Subject: [PATCH] ci: Implement GitHub release workflow (#1203) ### Changes This PR implements the new GH release workflow to support automated releasing. ### References N/A ### Testing N/A ### Checklist - [x] I have read the [Auth0 general contribution guidelines](https://github.com/auth0/open-source-template/blob/master/GENERAL-CONTRIBUTING.md) - [x] I have read the [Auth0 Code of Conduct](https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md) - [x] All code quality tools/guidelines have been run/followed --- .github/actions/get-prerelease/action.yml | 30 ++++++++++ .github/actions/get-version/action.yml | 23 +++++++ .github/actions/publish-package/action.yml | 31 ++++++++++ .github/actions/release-create/action.yml | 47 +++++++++++++++ .github/actions/tag-create/action.yml | 33 ++++++++++ .github/actions/tag-exists/action.yml | 36 +++++++++++ .github/workflows/publish.yml | 44 -------------- .github/workflows/release.yml | 70 ++++++++++++++++++++++ 8 files changed, 270 insertions(+), 44 deletions(-) create mode 100644 .github/actions/get-prerelease/action.yml create mode 100644 .github/actions/get-version/action.yml create mode 100644 .github/actions/publish-package/action.yml create mode 100644 .github/actions/release-create/action.yml create mode 100644 .github/actions/tag-create/action.yml create mode 100644 .github/actions/tag-exists/action.yml delete mode 100644 .github/workflows/publish.yml create mode 100644 .github/workflows/release.yml diff --git a/.github/actions/get-prerelease/action.yml b/.github/actions/get-prerelease/action.yml new file mode 100644 index 000000000..ce7acdc3b --- /dev/null +++ b/.github/actions/get-prerelease/action.yml @@ -0,0 +1,30 @@ +name: Return a boolean indicating if the version contains prerelease identifiers + +# +# Returns a simple true/false boolean indicating whether the version indicates it's a prerelease or not. +# +# TODO: Remove once the common repo is public. +# + +inputs: + version: + required: true + +outputs: + prerelease: + value: ${{ steps.get_prerelease.outputs.PRERELEASE }} + +runs: + using: composite + + steps: + - id: get_prerelease + shell: bash + run: | + if [[ "${VERSION}" == *"beta"* || "${VERSION}" == *"alpha"* ]]; then + echo "PRERELEASE=true" >> $GITHUB_OUTPUT + else + echo "PRERELEASE=false" >> $GITHUB_OUTPUT + fi + env: + VERSION: ${{ inputs.version }} diff --git a/.github/actions/get-version/action.yml b/.github/actions/get-version/action.yml new file mode 100644 index 000000000..387fdba67 --- /dev/null +++ b/.github/actions/get-version/action.yml @@ -0,0 +1,23 @@ +name: Return the version extracted from the branch name + +# +# Returns the version from a branch name of a pull request. It expects the branch name to be in the format release/vX.Y.Z, release/X.Y.Z, release/vX.Y.Z-beta.N. etc. +# +# TODO: Remove once the common repo is public. +# + +outputs: + version: + value: ${{ steps.get_version.outputs.VERSION }} + +runs: + using: composite + + steps: + - id: get_version + shell: bash + run: | + VERSION=$(echo ${BRANCH_NAME} | sed -r 's#release/+##g') + echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT + env: + BRANCH_NAME: ${{ github.event.pull_request.head.ref }} diff --git a/.github/actions/publish-package/action.yml b/.github/actions/publish-package/action.yml new file mode 100644 index 000000000..f3887a66f --- /dev/null +++ b/.github/actions/publish-package/action.yml @@ -0,0 +1,31 @@ +name: Publish release to package manager + +inputs: + node-version: + required: true + npm-token: + required: true + +runs: + using: composite + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: ${{ inputs.node-version }} + cache: 'npm' + registry-url: 'https://registry.npmjs.org' + + - name: Build package + uses: ./.github/actions/build + with: + ${{ inputs.node-version }} + + - name: Publish release to NPM + run: npm publish + env: + NODE_AUTH_TOKEN: ${{ inputs.npm-token }} diff --git a/.github/actions/release-create/action.yml b/.github/actions/release-create/action.yml new file mode 100644 index 000000000..6a2bf804c --- /dev/null +++ b/.github/actions/release-create/action.yml @@ -0,0 +1,47 @@ +name: Create a GitHub release + +# +# Creates a GitHub release with the given version. +# +# TODO: Remove once the common repo is public. +# + +inputs: + token: + required: true + files: + required: false + name: + required: true + body: + required: true + tag: + required: true + commit: + required: true + draft: + default: false + required: false + prerelease: + default: false + required: false + fail_on_unmatched_files: + default: true + required: false + +runs: + using: composite + + steps: + - uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 + with: + body: ${{ inputs.body }} + name: ${{ inputs.name }} + tag_name: ${{ inputs.tag }} + target_commitish: ${{ inputs.commit }} + draft: ${{ inputs.draft }} + prerelease: ${{ inputs.prerelease }} + fail_on_unmatched_files: ${{ inputs.fail_on_unmatched_files }} + files: ${{ inputs.files }} + env: + GITHUB_TOKEN: ${{ inputs.token }} diff --git a/.github/actions/tag-create/action.yml b/.github/actions/tag-create/action.yml new file mode 100644 index 000000000..727df4854 --- /dev/null +++ b/.github/actions/tag-create/action.yml @@ -0,0 +1,33 @@ +name: Create a repository tag + +# +# Creates a tag with the given version. +# +# TODO: Remove once the common repo is public. +# + +inputs: + token: + required: true + tag: + required: true + +runs: + using: composite + + steps: + - shell: bash + run: | + git config user.name "${AUTHOR_USERNAME}" + git config user.email "${AUTHOR_EMAIL}" + env: + AUTHOR_USERNAME: ${{ github.event.pull_request.user.login }} + AUTHOR_EMAIL: ${{ github.event.pull_request.user.email }} + + - shell: bash + run: | + git tag -a ${TAG_NAME} -m "Version ${TAG_NAME}" + git push --follow-tags + env: + TAG_NAME: ${{ inputs.tag }} + GITHUB_TOKEN: ${{ inputs.token }} diff --git a/.github/actions/tag-exists/action.yml b/.github/actions/tag-exists/action.yml new file mode 100644 index 000000000..e528612de --- /dev/null +++ b/.github/actions/tag-exists/action.yml @@ -0,0 +1,36 @@ +name: Return a boolean indicating if a tag already exists for the repository + +# +# Returns a simple true/false boolean indicating whether the tag exists or not. +# +# TODO: Remove once the common repo is public. +# + +inputs: + token: + required: true + tag: + required: true + +outputs: + exists: + description: 'Whether the tag exists or not' + value: ${{ steps.tag-exists.outputs.EXISTS }} + +runs: + using: composite + + steps: + - id: check + shell: bash + run: | + GET_API_URL="https://api.github.com/repos/${GITHUB_REPOSITORY}/git/ref/tags/${TAG_NAME}" + http_status_code=$(curl -LI $GET_API_URL -o /dev/null -w '%{http_code}\n' -s -H "Authorization: token ${GITHUB_TOKEN}") + if [ "$http_status_code" -ne "404" ] ; then + echo "EXISTS=true" >> $GITHUB_OUTPUT + else + echo "EXISTS=false" >> $GITHUB_OUTPUT + fi + env: + TAG_NAME: ${{ inputs.tag }} + GITHUB_TOKEN: ${{ inputs.token }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 6439f7a4f..000000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Publish Release - -on: - workflow_dispatch: - push: - tags: - - 'v[0-9]+.[0-9]+.[0-9]+' # Release versions - - '[0-9]+.[0-9]+.[0-9]+' - - 'v[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+' # Beta versions - - '[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+' - -permissions: - contents: read - -env: - NODE_VERSION: 18 - -jobs: - publish-npm: - name: 'NPM' - runs-on: ubuntu-latest - environment: release - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version: ${{ env.NODE_VERSION }} - cache: 'npm' - registry-url: 'https://registry.npmjs.org' - - - name: Build package - uses: ./.github/actions/build - with: - node: ${{ env.NODE_VERSION }} - - - name: Publish release to NPM - run: npm publish - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..b11376ffe --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,70 @@ +name: Create GitHub Release + +on: + pull_request: + types: + - closed + +permissions: + contents: write + +env: + NODE_VERSION: 18 + +### TODO: Replace instances of './.github/actions/' w/ `auth0/dx-sdk-actions/` and append `@latest` after the common `dx-sdk-actions` repo is made public. +### TODO: Also remove `get-prerelease`, `get-version`, `release-create`, `tag-create` and `tag-exists` actions from this repo's .github/actions folder once the repo is public. + +jobs: + release: + if: github.event.pull_request.merged && startsWith(github.event.pull_request.head.ref, 'release/') + runs-on: ubuntu-latest + environment: release + + steps: + # Checkout the code + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # Get the version from the branch name + - id: get_version + uses: ./.github/actions/get-version + + # Get the prerelease flag from the branch name + - id: get_prerelease + uses: ./.github/actions/get-prerelease + with: + version: ${{ steps.get_version.outputs.version }} + + # Check if the tag already exists + - id: tag_exists + uses: ./.github/actions/tag-exists + with: + tag: ${{ steps.get_version.outputs.version }} + token: ${{ secrets.GITHUB_TOKEN }} + + # If the tag already exists, exit with an error + - if: steps.tag_exists.outputs.exists == 'true' + run: exit 1 + + # Publish the release to our package manager + - uses: ./.github/actions/publish-package + with: + node-version: ${{ env.NODE_VERSION }} + npm-token: ${{ secrets.NPM_TOKEN }} + + # Create a tag for the release + - uses: ./.github/actions/tag-create + with: + tag: ${{ steps.get_version.outputs.version }} + token: ${{ secrets.GITHUB_TOKEN }} + + # Create a release for the tag + - uses: ./.github/actions/release-create + with: + token: ${{ secrets.GITHUB_TOKEN }} + name: ${{ steps.get_version.outputs.version }} + body: ${{ github.event.pull_request.body }} + tag: ${{ steps.get_version.outputs.version }} + commit: ${{ github.sha }} + prerelease: ${{ steps.get_prerelease.outputs.prerelease }}