Promote branch #138
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: 'Promote branch' | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| promotion-type: | |
| type: choice | |
| options: | |
| - 'preview' | |
| - 'release' | |
| description: 'Promotion type.' | |
| required: true | |
| base-branch: | |
| type: string | |
| description: 'Base branch to create target from.' | |
| default: 'main' | |
| required: true | |
| permissions: | |
| actions: read | |
| id-token: write | |
| contents: write | |
| pull-requests: write | |
| concurrency: | |
| group: 'promote-branch-${{ inputs.promotion-type }}-${{github.ref_name }}' | |
| cancel-in-progress: false | |
| env: | |
| dotnet-sdk-version: '9.x' | |
| is-development-branch: ${{ startsWith(github.ref_name, 'develop') }} | |
| is-maintenance-branch: ${{ startsWith(github.ref_name, 'support') }} | |
| jobs: | |
| versioning: | |
| name: 'Extract version' | |
| runs-on: ubuntu-latest | |
| outputs: | |
| friendly-version: ${{ steps.extract-version.outputs.version }} | |
| steps: | |
| - name: 'Checkout ${{ github.head_ref || github.ref }}' | |
| uses: actions/checkout@v5 | |
| - name: 'Setup .NET ${{ env.dotnet-sdk-version }}' | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: ${{ env.dotnet-sdk-version }} | |
| - name: 'Extract version from branch name' | |
| id: extract-version | |
| uses: './.github/actions/versioning/extract-version' | |
| with: | |
| branch-name: ${{ github.ref_name }} | |
| workflow-variables: | |
| name: 'Set workflow variables' | |
| needs: [versioning] | |
| runs-on: ubuntu-latest | |
| outputs: | |
| base-branch: ${{ steps.set-base-branch.outputs.base-branch }} | |
| target-branch: ${{ steps.set-target-branch.outputs.target-branch }} | |
| target-branch-exists: ${{ steps.check-target-branch-exists.outputs.target-branch-exists }} | |
| pull-request-exists: ${{ steps.check-pull-request-exists.outputs.pull-request-exists }} | |
| steps: | |
| - name: 'Set target branch' | |
| id: set-target-branch | |
| run: | | |
| if [[ "${{ inputs.promotion-type }}" == "preview" ]]; then | |
| target_branch="preview/${{ needs.versioning.outputs.friendly-version }}" | |
| elif [[ "${{ inputs.promotion-type }}" == "release" ]]; then | |
| target_branch="release/${{ needs.versioning.outputs.friendly-version }}" | |
| fi | |
| echo "Setting target branch $target_branch." | |
| echo "target-branch=$target_branch" >> $GITHUB_OUTPUT | |
| - name: 'Set base branch' | |
| id: set-base-branch | |
| run: | | |
| base_branch=${{ inputs.base-branch }} | |
| echo "Setting base branch $base_branch." | |
| echo "base-branch=$base_branch" >> $GITHUB_OUTPUT | |
| - name: 'Check if base branch exists' | |
| id: check-target-branch-exists | |
| env: | |
| target-branch: ${{ steps.set-target-branch.outputs.target-branch }} | |
| run: | | |
| set +e | |
| git ls-remote --exit-code --heads origin ${{ env.target-branch }} | |
| if [[ $? -eq 0 ]]; then | |
| echo "Target branch ${{ env.target-branch }} does exist." | |
| target_branch_exists="true" | |
| else | |
| echo "Target branch ${{ env.target-branch }} does not exist." | |
| target_branch_exists="false" | |
| fi | |
| echo "target-branch-exists=$target_branch_exists" >> $GITHUB_OUTPUT | |
| set -e | |
| - name: 'Check if base branch exists' | |
| id: check-base-branch-exists | |
| env: | |
| base-branch: ${{ steps.set-base-branch.outputs.base-branch }} | |
| run: | | |
| set +e | |
| git ls-remote --exit-code --heads origin ${{ env.base-branch }} | |
| if [[ $? -eq 0 ]]; then | |
| echo "Base branch ${{ env.base-branch }} does exist." | |
| base_branch_exists="true" | |
| else | |
| echo "Base branch ${{ env.base-branch }} does not exist." | |
| base_branch_exists="false" | |
| fi | |
| echo "base-branch-exists=$base_branch_exists" >> $GITHUB_OUTPUT | |
| set -e | |
| - name: 'Check if pull request exists exists' | |
| id: check-pull-request-exists | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| GH_REPO: ${{ github.repository_owner }}/${{ github.event.repository.name }} | |
| current-branch: ${{ github.ref_name }} | |
| target-branch: ${{ steps.set-target-branch.outputs.target-branch }} | |
| run: | | |
| pull_request_count=$(gh pr list --head ${{ env.current-branch }} --base ${{ env.target-branch }} --state open --limit 1 --json id --jq '. | length') | |
| if [[ $pull_request_count -eq 0 ]]; then | |
| echo "Pull request does not exist." | |
| pull_request_exists="false" | |
| else | |
| echo "Pull request does exist." | |
| pull_request_exists="true" | |
| fi | |
| echo "pull-request-exists=$pull_request_exists" >> $GITHUB_OUTPUT | |
| validate-promotion: | |
| name: 'Validate promotion' | |
| needs: [ versioning, workflow-variables ] | |
| runs-on: ubuntu-latest | |
| env: | |
| promotion-type: ${{ inputs.promotion-type }} | |
| base-branch: ${{ needs.workflow-variables.outputs.base-branch }} | |
| current-branch: ${{ github.ref_name }} | |
| target-branch: ${{ needs.workflow-variables.outputs.target-branch }} | |
| pull-request-exists: ${{ needs.workflow-variables.outputs.pull-request-exists }} | |
| outputs: | |
| target-branch: ${{ env.target-branch }} | |
| steps: | |
| - name: 'Checkout ${{ github.head_ref || github.ref }}' | |
| uses: actions/checkout@v5 | |
| - name: 'Check promotion type' | |
| if: ${{ (env.promotion-type != 'release') && (env.promotion-type != 'preview') }} | |
| run: | | |
| echo "Invalid promotion type ${{ inputs.promotion-type }}" | |
| exit 1 | |
| - name: 'Validate current branch' | |
| if: ${{ (env.is-development-branch == 'false') && (env.is-maintenance-branch == 'false') }} | |
| run: | | |
| echo "Invalid current branch '${{ github.ref_name }}'" | |
| exit 1 | |
| - name: 'Validate default and current branch' | |
| if: ${{ env.base-branch == env.current-branch }} | |
| run: | | |
| echo "Default and current branch cannot be the same." | |
| echo "Default branch is '${{ env.base-branch }}'" | |
| echo "Current branch is '${{ env.current-branch }}'" | |
| exit 1 | |
| - name: 'Validate target and current branch' | |
| if: ${{ env.target-branch == env.current-branch }} | |
| run: | | |
| echo "Default and target branch cannot be the same." | |
| echo "Default branch is '${{ env.target-branch }}'" | |
| echo "Current branch is '${{ env.current-branch }}'" | |
| exit 1 | |
| - name: 'Validate pull request' | |
| if: ${{ env.pull-request-exists == 'true' }} | |
| run: | | |
| echo "Pull request exists." | |
| exit 1 | |
| promote-branch: | |
| name: 'Promote branch ${{ github.ref_name }} to ${{ needs.workflow-variables.outputs.target-branch }}' | |
| needs: [ workflow-variables, validate-promotion ] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: 'Checkout ${{ github.head_ref || github.ref }}' | |
| uses: actions/checkout@v5 | |
| - name: 'Setup .NET ${{ env.dotnet-sdk-version }}' | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: ${{ env.dotnet-sdk-version }} | |
| - name: 'Create target branch' | |
| if: ${{ needs.workflow-variables.outputs.target-branch-exists == 'false' }} | |
| run: | | |
| git config user.name "$(git log -n 1 --pretty=format:%an)" | |
| git config user.email "$(git log -n 1 --pretty=format:%ae)" | |
| git fetch origin | |
| git switch ${{ needs.workflow-variables.outputs.base-branch }} | |
| git checkout -b ${{ needs.workflow-variables.outputs.target-branch }} origin/${{ needs.workflow-variables.outputs.target-branch }} || git checkout -b ${{ needs.workflow-variables.outputs.target-branch }} | |
| git push --set-upstream origin ${{ needs.workflow-variables.outputs.target-branch }} | |
| - name: 'Create PR: "Promote ${{ env.current-branch }} to ${{ env.target-branch }}"' | |
| if: ${{ needs.workflow-variables.outputs.pull-request-exists == 'false' }} | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| current-branch: ${{ github.ref_name }} | |
| target-branch: ${{ needs.workflow-variables.outputs.target-branch }} | |
| run: | | |
| gh pr create --title "Promote ${{ env.current-branch }} to ${{ env.target-branch }}" --fill --base ${{ env.target-branch }} --head ${{ env.current-branch }} |