Promote branch #186
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: '10.x' | |
| is-development-branch: ${{ startsWith(github.ref_name, 'develop') }} | |
| is-maintenance-branch: ${{ startsWith(github.ref_name, 'support') }} | |
| is-preview-branch: ${{ startsWith(github.ref_name, 'preview') }} | |
| 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@v6 | |
| - 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: 'Checkout ${{ github.head_ref || github.ref }}' | |
| uses: actions/checkout@v6 | |
| - 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@v6 | |
| - 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 source branch for preview promotion' | |
| if: ${{ env.promotion-type == 'preview' && (env.is-development-branch == 'false') && (env.is-maintenance-branch == 'false') }} | |
| run: | | |
| echo "Preview promotion requires a 'develop/**' or 'support/**' source branch. Current branch: '${{ github.ref_name }}'" | |
| exit 1 | |
| - name: 'Validate source branch for release promotion' | |
| if: ${{ env.promotion-type == 'release' && env.is-preview-branch == 'false' }} | |
| run: | | |
| echo "Release promotion requires a 'preview/**' source branch. 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@v6 | |
| - 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' }} | |
| env: | |
| base-branch: ${{ needs.workflow-variables.outputs.base-branch }} | |
| target-branch: ${{ needs.workflow-variables.outputs.target-branch }} | |
| run: | | |
| git fetch origin | |
| git push origin origin/${{ env.base-branch }}:refs/heads/${{ env.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: | | |
| git fetch origin ${{ env.target-branch }} | |
| gh pr create --title "Promote ${{ env.current-branch }} to ${{ env.target-branch }}" --fill --base ${{ env.target-branch }} --head ${{ env.current-branch }} |