diff --git a/ci/release/pr_code_freeze_template.md b/.github/CODE_FREEZE_PR_TEMPLATE.md similarity index 55% rename from ci/release/pr_code_freeze_template.md rename to .github/CODE_FREEZE_PR_TEMPLATE.md index 99642f7..62f0e82 100644 --- a/ci/release/pr_code_freeze_template.md +++ b/.github/CODE_FREEZE_PR_TEMPLATE.md @@ -1,11 +1,11 @@ -## :snowflake: Code freeze for `branch-${VERSION}` and `v${VERSION}` release +## :snowflake: Code freeze for `branch-${CURRENT_VERSION}` and `v${CURRENT_VERSION}` release ### What does this mean? -Only critical/hotfix level issues should be merged into `branch-${VERSION}` until release (merging of this PR). +Only critical/hotfix level issues should be merged into `branch-${CURRENT_VERSION}` until release (merging of this PR). All other development PRs should be retargeted towards the next release branch: `branch-${NEXT_VERSION}`. ### What is the purpose of this PR? - Update documentation - Allow testing for the new release -- Enable a means to merge `branch-${VERSION}` into `main` for the release +- Enable a means to merge `branch-${CURRENT_VERSION}` into `main` for the release diff --git a/.github/actions/configure-morpheus-bot/action.yml b/.github/actions/configure-morpheus-bot/action.yml new file mode 100644 index 0000000..13f45d8 --- /dev/null +++ b/.github/actions/configure-morpheus-bot/action.yml @@ -0,0 +1,50 @@ +# SPDX-FileCopyrightText: Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: Configure Morpheus Bot + +inputs: + bot-app-id: + description: 'The app id of the bot' + required: true + type: string + bot-private-key: + description: 'The private key of the bot' + required: true + type: string +outputs: + token: + description: 'The token generated for the bot' + value: ${{steps.generate-token.outputs.token }} + +runs: + using: "composite" + steps: + - name: Generate Token + uses: actions/create-github-app-token@v1 + id: generate-token + with: + app-id: ${{ inputs.bot-app-id }} + private-key: ${{ inputs.bot-private-key }} + - name: Configure Git + shell: bash + run: | + git config --global user.name "morpheus-bot-test[bot]" + git config --global user.email "152534332+morpheus-bot-test[bot]@users.noreply.github.com" + echo "GITHUB_TOKEN=${{ steps.generate-token.outputs.token }}" >> "$GITHUB_ENV" + echo "Git config:" + git config -l --show-origin + echo "Github Auth Info:" + gh auth status diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..524fb6e --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,72 @@ +# SPDX-FileCopyrightText: Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: Release + +permissions: + contents: write + pull-requests: write + +on: + workflow_dispatch: + inputs: + current_version_array: + description: 'Current full version of the project expressed as a JSON array (e.g. `["24", "03", "00"]`)' + required: true + type: string + default: '["24", "03", "00"]' + next_version_array: + description: 'Next full version of the project as a JSON array (e.g. `["24", "07", "00"]`)' + required: true + type: string + default: '["24", "07", "00"]' + create_codefreeze_pr: + description: 'Create/Update the codefreeze PR' + required: true + type: boolean + default: false + create_next_release_branch: + description: 'Creates the next release branch and configures tags' + required: true + type: boolean + default: false + update_next_release_versions: + description: 'Runs the update-version and commits the changes to the next release branch' + required: true + type: boolean + default: false + update_changelog: + description: 'Updates the CHANGELOG.md file for the current release and commits the changes to the current release branch' + required: true + type: boolean + default: false + merge_release_branch: + description: 'Merges the code freeze release branch, creates the release tag, and creates a new Github release' + required: true + type: boolean + default: false + +jobs: + release_procedures: + uses: nv-morpheus/utilities/.github/workflows/release_procedures.yml@mdd_release-procedures + with: + current_version_array: ${{ inputs.current_version_array }} + next_version_array: ${{ inputs.next_version_array }} + create_codefreeze_pr: ${{ inputs.create_codefreeze_pr }} + create_next_release_branch: ${{ inputs.create_next_release_branch }} + update_next_release_versions: ${{ inputs.update_next_release_versions }} + update_changelog: ${{ inputs.update_changelog }} + merge_release_branch: ${{ inputs.merge_release_branch }} + secrets: inherit diff --git a/.github/workflows/release_procedures.yml b/.github/workflows/release_procedures.yml new file mode 100644 index 0000000..57551c4 --- /dev/null +++ b/.github/workflows/release_procedures.yml @@ -0,0 +1,261 @@ +# SPDX-FileCopyrightText: Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: Release Procedures + +permissions: + contents: write + pull-requests: write + +on: + workflow_call: + inputs: + current_version_array: + description: 'Current full version of the project expressed as a JSON array (e.g. `["24", "03", "00"]`)' + required: true + type: string + default: '["24", "03", "00"]' + next_version_array: + description: 'Next full version of the project as a JSON array (e.g. `["24", "07", "00"]`)' + required: true + type: string + default: '["24", "07", "00"]' + create_codefreeze_pr: + description: 'Create/Update the codefreeze PR' + required: true + type: boolean + default: false + create_next_release_branch: + description: 'Creates the next release branch and configures tags' + required: true + type: boolean + default: false + update_next_release_versions: + description: 'Runs the update-version and commits the changes to the next release branch' + required: true + type: boolean + default: false + update_changelog: + description: 'Updates the CHANGELOG.md file for the current release and commits the changes to the current release branch' + required: true + type: boolean + default: false + merge_release_branch: + description: 'Merges the code freeze release branch, creates the release tag, and creates a new Github release' + required: true + type: boolean + secrets: + ACTIONS_APP_ID: + description: 'The Github App ID for the bot' + required: true + ACTIONS_APP_KEY: + description: 'The private key for the Github App' + required: true + +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPO_NAME: ${{ github.event.repository.name }} + CURRENT_VERSION: ${{ format('{0}.{1}', fromJson(inputs.current_version_array)[0], fromJson(inputs.current_version_array)[1]) }} + CURRENT_FULL_VERSION: ${{ format('{0}.{1}.{2}', fromJson(inputs.current_version_array)[0], fromJson(inputs.current_version_array)[1], fromJson(inputs.current_version_array)[2]) }} + NEXT_VERSION: ${{ format('{0}.{1}', fromJson(inputs.next_version_array)[0], fromJson(inputs.next_version_array)[1]) }} + NEXT_FULL_VERSION: ${{ format('{0}.{1}.{2}', fromJson(inputs.next_version_array)[0], fromJson(inputs.next_version_array)[1], fromJson(inputs.next_version_array)[2]) }} + +jobs: + create_codefreeze_pr: + if: ${{ inputs.create_codefreeze_pr }} + name: Create Codefreeze PR + runs-on: ubuntu-latest + steps: + - name: Configure Bot + id: configure-bot + uses: nv-morpheus/utilities/.github/actions/configure-morpheus-bot@mdd_release-procedures + with: + bot-app-id: ${{ secrets.ACTIONS_APP_ID }} + bot-private-key: ${{ secrets.ACTIONS_APP_KEY }} + - name: Checkout + uses: actions/checkout@v4 + with: + path: utilities + repository: nv-morpheus/utilities + # ref: branch-${{ env.CURRENT_VERSION }} + token: ${{ steps.configure-bot.outputs.token }} + sparse-checkout: | + .github/CODE_FREEZE_PR_TEMPLATE.md + sparse-checkout-cone-mode: false + - name: Create PR + run: | + cat utilities/.github/CODE_FREEZE_PR_TEMPLATE.md | envsubst | \ + gh pr create --repo ${{ github.repository }} \ + --base main --head branch-${CURRENT_VERSION} \ + --title "[RELEASE] ${REPO_NAME} v${CURRENT_FULL_VERSION}" \ + --body-file - \ + --label "! - Release" + create_next_release_branch: + if: ${{ inputs.create_next_release_branch }} + name: Create Next Release Branch + runs-on: ubuntu-latest + steps: + - name: Configure Bot + id: configure-bot + uses: nv-morpheus/utilities/.github/actions/configure-morpheus-bot@mdd_release-procedures + with: + bot-app-id: ${{ secrets.ACTIONS_APP_ID }} + bot-private-key: ${{ secrets.ACTIONS_APP_KEY }} + - name: Checkout + uses: actions/checkout@v4 + with: + path: ${{ env.REPO_NAME }} + ref: branch-${{ env.CURRENT_VERSION }} + fetch-depth: 0 # Fetch all history for all tags and branches + token: ${{ steps.configure-bot.outputs.token }} + - name: Create branch + run: | + cd ${REPO_NAME} + + # Double check the auth status + gh auth status + git checkout -b branch-${NEXT_VERSION} + git commit --allow-empty -m "Creating branch for v${NEXT_VERSION}" + git tag -a -m "Alpha release of v${NEXT_VERSION}" v${NEXT_FULL_VERSION}a + git push origin branch-${NEXT_VERSION} v${NEXT_FULL_VERSION}a + - name: Set default branch + run: | + gh repo edit ${{ github.repository }} --default-branch branch-${NEXT_VERSION} + + update_next_release_versions: + if: ${{ always() && inputs.update_next_release_versions }} + name: Update Next Release Versions + needs: [create_next_release_branch] + runs-on: ubuntu-latest + steps: + - name: Configure Bot + id: configure-bot + uses: nv-morpheus/utilities/.github/actions/configure-morpheus-bot@mdd_release-procedures + with: + bot-app-id: ${{ secrets.ACTIONS_APP_ID }} + bot-private-key: ${{ secrets.ACTIONS_APP_KEY }} + - name: Checkout + uses: actions/checkout@v4 + with: + lfs: false + path: ${{ env.REPO_NAME }} + ref: branch-${{ env.NEXT_VERSION }} + token: ${{ steps.configure-bot.outputs.token }} + submodules: recursive + - name: Run update script + run: | + cd ${REPO_NAME} + + # Run the update-versions script and commit all changes + ./ci/release/update-version.sh ${CURRENT_FULL_VERSION} ${NEXT_FULL_VERSION} + git add . + git commit -m "Updating versions for v${NEXT_FULL_VERSION}" + + # Push the changes + git push origin branch-${NEXT_VERSION} + + update_changelog: + if: ${{ inputs.update_changelog }} + name: Update Changelog + runs-on: ubuntu-latest + steps: + - name: Configure Bot + id: configure-bot + uses: nv-morpheus/utilities/.github/actions/configure-morpheus-bot@mdd_release-procedures + with: + bot-app-id: ${{ secrets.ACTIONS_APP_ID }} + bot-private-key: ${{ secrets.ACTIONS_APP_KEY }} + - name: Checkout + uses: actions/checkout@v4 + with: + lfs: false + path: ${{ env.REPO_NAME }} + ref: branch-${{ env.CURRENT_VERSION }} + token: ${{ steps.configure-bot.outputs.token }} + - name: Update the CHANGELOG.md file + run: | + cd ${REPO_NAME} + + # Get the release notes from the current nightly release + RELEASE_NOTES=$(gh release view v${CURRENT_FULL_VERSION}a --repo ${{ github.repository }} --json body | jq -r '.body' | tail -n +6) + + echo "RELEASE_NOTES=${RELEASE_NOTES}" + + # Update the CHANGELOG.md file + echo -e "# ${REPO_NAME} ${CURRENT_FULL_VERSION} ($(date +"%d %b %Y"))\n\n${RELEASE_NOTES}\n\n$(cat CHANGELOG.md)" > CHANGELOG.md + + # Update the links + export PR_URL_PREFIX="https://github.com/${{ github.repository }}/pull/" + export GH_URL="https://github.com" + sed -i "s|(#\([[:digit:]]*\))|([#\1](${PR_URL_PREFIX}\1))|g" CHANGELOG.md + sed -i "s|@\([a-zA-Z0-9\-]\{1,39\}\)$|[@\1](${GH_URL}/\1)|g" CHANGELOG.md + + # # Commit the changes + # git add CHANGELOG.md + # git commit -m "Updating CHANGELOG" + # git push origin branch-${CURRENT_VERSION} + cat CHANGELOG.md + + merge_release_branch: + if: ${{ inputs.merge_release_branch }} + name: Merge Release Branch + runs-on: ubuntu-latest + steps: + - name: Configure Bot + id: configure-bot + uses: nv-morpheus/utilities/.github/actions/configure-morpheus-bot@mdd_release-procedures + with: + bot-app-id: ${{ secrets.ACTIONS_APP_ID }} + bot-private-key: ${{ secrets.ACTIONS_APP_KEY }} + - name: Find Matching Release PRs + id: find_matching_prs + run: | + set -x + PR_LIST=$(gh pr list --repo ${{ github.repository }} --base main --head branch-${CURRENT_VERSION} --label "! - Release" --state open --json number) + if [[ $(echo "${PR_LIST}" | jq length) != 1 ]]; then + echo "::error Found multiple PRs for the current release. Please close all but one PR and try again. Matched PRs: ${PR_LIST}" + exit 1 + fi + + # Save the PR number to an output variable + echo "pr_number=$(echo ${PR_LIST} | jq -r '.[0].number')" >> $GITHUB_OUTPUT + - name: Merge the release PR + run: | + PR_NUMBER=${{ steps.find_matching_prs.outputs.pr_number }} + gh pr merge ${PR_NUMBER} --repo ${{ github.repository }} --merge + - name: Checkout main branch + uses: actions/checkout@v4 + with: + lfs: false + path: ${{ env.REPO_NAME }} + ref: main + fetch-tags: true # Fetch all tags + token: ${{ steps.configure-bot.outputs.token }} + - name: Create release commit and tag + run: | + cd ${REPO_NAME} + git commit --allow-empty -m "REL v${CURRENT_FULL_VERSION} release" + git tag -a -m "$(date +"%B %Y") Release" v${CURRENT_FULL_VERSION} + git push origin main v${CURRENT_FULL_VERSION} + - name: Create Github release + run: | + # Get the release body from the current nightly release + RELEASE_BODY=$(gh release view v${CURRENT_FULL_VERSION}a --repo ${{ github.repository }} --json body | jq -r '.body' | tail -n +6) + + # Build the release for Github + gh release create v${CURRENT_FULL_VERSION} --repo ${{ github.repository }} \ + --title "v${CURRENT_FULL_VERSION}" \ + --notes "${RELEASE_BODY}" \ + --verify-tag