From 0b0d8c51f3deb470c6d0e0578e6e6c1ab390b512 Mon Sep 17 00:00:00 2001 From: Poovamraj T T Date: Tue, 19 Dec 2023 16:04:58 +0100 Subject: [PATCH] Automate release workflow --- .github/actions/get-prerelease/action.yml | 30 +++++++ .github/actions/get-release-notes/action.yml | 42 ++++++++++ .github/actions/get-version/action.yml | 21 +++++ .github/actions/maven-publish/action.yml | 44 ++++++++++ .github/actions/release-create/action.yml | 47 +++++++++++ .github/actions/tag-exists/action.yml | 36 ++++++++ .github/workflows/java-release.yml | 88 ++++++++++++++++++++ .github/workflows/publish.yml | 32 ------- .github/workflows/release.yml | 27 ++++++ .shiprc | 8 ++ .version | 1 + build.gradle | 7 ++ 12 files changed, 351 insertions(+), 32 deletions(-) create mode 100644 .github/actions/get-prerelease/action.yml create mode 100644 .github/actions/get-release-notes/action.yml create mode 100644 .github/actions/get-version/action.yml create mode 100644 .github/actions/maven-publish/action.yml create mode 100644 .github/actions/release-create/action.yml create mode 100644 .github/actions/tag-exists/action.yml create mode 100644 .github/workflows/java-release.yml delete mode 100644 .github/workflows/publish.yml create mode 100644 .github/workflows/release.yml create mode 100644 .shiprc create mode 100644 .version diff --git a/.github/actions/get-prerelease/action.yml b/.github/actions/get-prerelease/action.yml new file mode 100644 index 0000000..ce7acdc --- /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-release-notes/action.yml b/.github/actions/get-release-notes/action.yml new file mode 100644 index 0000000..287d206 --- /dev/null +++ b/.github/actions/get-release-notes/action.yml @@ -0,0 +1,42 @@ +name: Return the release notes extracted from the body of the PR associated with the release. + +# +# Returns the release notes from the content of a pull request linked to a release branch. 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. +# +inputs: + version: + required: true + repo_name: + required: false + repo_owner: + required: true + token: + required: true + +outputs: + release-notes: + value: ${{ steps.get_release_notes.outputs.RELEASE_NOTES }} + +runs: + using: composite + + steps: + - uses: actions/github-script@v7 + id: get_release_notes + with: + result-encoding: string + script: | + const { data: pulls } = await github.rest.pulls.list({ + owner: process.env.REPO_OWNER, + repo: process.env.REPO_NAME, + state: 'all', + head: `${process.env.REPO_OWNER}:release/${process.env.VERSION}`, + }); + core.setOutput('RELEASE_NOTES', pulls[0].body); + env: + GITHUB_TOKEN: ${{ inputs.token }} + REPO_OWNER: ${{ inputs.repo_owner }} + REPO_NAME: ${{ inputs.repo_name }} + VERSION: ${{ inputs.version }} diff --git a/.github/actions/get-version/action.yml b/.github/actions/get-version/action.yml new file mode 100644 index 0000000..9440ec9 --- /dev/null +++ b/.github/actions/get-version/action.yml @@ -0,0 +1,21 @@ +name: Return the version extracted from the branch name + +# +# Returns the version from the .version file. +# +# 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=$(head -1 .version) + echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT diff --git a/.github/actions/maven-publish/action.yml b/.github/actions/maven-publish/action.yml new file mode 100644 index 0000000..ee47706 --- /dev/null +++ b/.github/actions/maven-publish/action.yml @@ -0,0 +1,44 @@ +name: Publish release to Java + +inputs: + ossr-username: + required: true + ossr-password: + required: true + signing-key: + required: true + signing-password: + required: true + java-version: + required: true + is-android: + required: true + version: + required: true + +runs: + using: composite + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Java + shell: bash + run: | + curl -s "https://get.sdkman.io" | bash + source "/home/runner/.sdkman/bin/sdkman-init.sh" + sdk list java + sdk install java ${{ inputs.java-version }} && sdk default java ${{ inputs.java-version }} + + - uses: gradle/wrapper-validation-action@56b90f209b02bf6d1deae490e9ef18b21a389cd4 # pin@1.1.0 + + - name: Publish Java + shell: bash + if: inputs.is-android == 'false' + run: ./gradlew clean assemble sign publishMavenJavaPublicationToMavenRepository -PisSnapshot=false -Pversion="${{ inputs.version }}" -PossrhUsername="${{ inputs.ossr-username }}" -PossrhPassword="${{ inputs.ossr-password }}" -PsigningKey="${{ inputs.signing-key }}" -PsigningPassword="${{ inputs.signing-password }}" + + - name: Publish Android + shell: bash + if: inputs.is-android == 'true' + run: ./gradlew clean assemble sign publishAndroidLibraryPublicationToMavenRepository -PisSnapshot=false -Pversion="${{ inputs.version }}" -PossrhUsername="${{ inputs.ossr-username }}" -PossrhPassword="${{ inputs.ossr-password }}" -PsigningKey="${{ inputs.signing-key }}" -PsigningPassword="${{ inputs.signing-password }}" diff --git a/.github/actions/release-create/action.yml b/.github/actions/release-create/action.yml new file mode 100644 index 0000000..6a2bf80 --- /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-exists/action.yml b/.github/actions/tag-exists/action.yml new file mode 100644 index 0000000..b5fbdb7 --- /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: tag-exists + 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/java-release.yml b/.github/workflows/java-release.yml new file mode 100644 index 0000000..3f81eb1 --- /dev/null +++ b/.github/workflows/java-release.yml @@ -0,0 +1,88 @@ +name: Create Java and GitHub Release + +on: + workflow_call: + inputs: + java-version: + required: true + type: string + is-android: + required: true + type: string + secrets: + ossr-username: + required: true + ossr-password: + required: true + signing-key: + required: true + signing-password: + required: true + github-token: + required: true + +### 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_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && 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 }} + + # Get the release notes + - id: get_release_notes + uses: ./.github/actions/get-release-notes + with: + token: ${{ secrets.github-token }} + version: ${{ steps.get_version.outputs.version }} + repo_owner: ${{ github.repository_owner }} + repo_name: ${{ github.event.repository.name }} + + # 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 Maven + - uses: ./.github/actions/maven-publish + with: + java-version: ${{ inputs.java-version }} + is-android: ${{ inputs.is-android }} + version: ${{ steps.get_version.outputs.version }} + ossr-username: ${{ secrets.ossr-username }} + ossr-password: ${{ secrets.ossr-password }} + signing-key: ${{ secrets.signing-key }} + signing-password: ${{ secrets.signing-password }} + + # Create a release for the tag + - uses: ./.github/actions/release-create + with: + token: ${{ secrets.github-token }} + name: ${{ steps.get_version.outputs.version }} + body: ${{ steps.get_release_notes.outputs.release-notes }} + tag: ${{ steps.get_version.outputs.version }} + commit: ${{ github.sha }} + prerelease: ${{ steps.get_prerelease.outputs.prerelease }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index ef49f37..0000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Publish Release - -on: - workflow_dispatch: - inputs: - branch: - description: The branch to release from. - required: true - default: master - -permissions: - contents: read - -jobs: - publish: - name: Publish to Maven Central - runs-on: ubuntu-latest - environment: release - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - ref: ${{ github.event.inputs.branch }} - - - uses: ./.github/actions/setup - - - run: ./gradlew clean assemble -PisSnapshot=false - - - run: ./gradlew exportVersion -PisSnapshot=false - - - run: ./gradlew publishAndroidLibraryPublicationToMavenRepository -PossrhUsername="${{ secrets.OSSR_USERNAME }}" -PossrhPassword="${{ secrets.OSSR_PASSWORD }}" -PsigningKey="${{ secrets.SIGNING_KEY }}" -PsigningPassword="${{ secrets.SIGNING_PASSWORD }}" -PisSnapshot=false" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..b969eef --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,27 @@ +name: Create GitHub Release + +on: + pull_request: + types: + - closed + workflow_dispatch: + +permissions: + contents: write + +### TODO: Replace instances of './.github/workflows/' w/ `auth0/dx-sdk-actions/workflows/` and append `@latest` after the common `dx-sdk-actions` repo is made public. +### TODO: Also remove `get-prerelease`, `get-release-notes`, `get-version`, `maven-publish`, `release-create`, and `tag-exists` actions from this repo's .github/actions folder once the repo is public. +### TODO: Also remove `java-release` workflow from this repo's .github/workflows folder once the repo is public. + +jobs: + release: + uses: ./.github/workflows/java-release.yml + with: + java-version: 8.0.382-tem + is-android: true + secrets: + ossr-username: ${{ secrets.OSSR_USERNAME }} + ossr-password: ${{ secrets.OSSR_PASSWORD }} + signing-key: ${{ secrets.SIGNING_KEY }} + signing-password: ${{ secrets.SIGNING_PASSWORD }} + github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.shiprc b/.shiprc new file mode 100644 index 0000000..f81a9f7 --- /dev/null +++ b/.shiprc @@ -0,0 +1,8 @@ +{ + "files": { + "README.md": [], + ".version": [], + "build.gradle": ["version = \"{MAJOR}.{MINOR}.{PATCH}\""] + }, + "prefixVersion": false +} diff --git a/.version b/.version new file mode 100644 index 0000000..f93ea0c --- /dev/null +++ b/.version @@ -0,0 +1 @@ +2.0.2 \ No newline at end of file diff --git a/build.gradle b/build.gradle index 3a20404..391b4a5 100644 --- a/build.gradle +++ b/build.gradle @@ -14,6 +14,13 @@ plugins { id 'lifecycle-base' } +def signingKey = findProperty('signingKey') +def signingKeyPwd = findProperty('signingPassword') + +signing { + useInMemoryPgpKeys(signingKey, signingKeyPwd) +} + allprojects { group = 'com.auth0.android'