diff --git a/.github/workflows/manual_review_code_pipeline.yml b/.github/workflows/manual_review_code_pipeline.yml index 2ea0719ca..15e17b2ae 100644 --- a/.github/workflows/manual_review_code_pipeline.yml +++ b/.github/workflows/manual_review_code_pipeline.yml @@ -1,29 +1,51 @@ -name: Manual review app code pipeline +name: Manual review app build and deploy concurrency: - group: review-${{ inputs.review_app_key }} + group: deploy-review${{ inputs.pr_number }} on: workflow_dispatch: inputs: - review_app_key: + pr_number: required: true type: string - description: "The review app ID to deploy code for." + description: "The PR number of the review app to deploy code for. Note: this is NOT the ticket number" + +permissions: {} defaults: run: shell: bash jobs: + get_pr_head_sha: + name: Get PR HEAD SHA + runs-on: ubuntu-latest + outputs: + pr_head_sha: ${{ steps.get_sha.outputs.pr_head_sha }} + steps: + - name: Get PR HEAD SHA + id: get_sha + uses: actions/github-script@v7 + with: + script: | + const { data: pr } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: parseInt('${{ inputs.pr_number }}'), + }); + core.setOutput('pr_head_sha', pr.head.sha); + code: name: Deploy review app code + needs: [get_pr_head_sha] uses: ./.github/workflows/aws_deploy.yml with: aws_account_id: 837698168072 aws_role_prefix: core-dev - aws_task_prefix: core-review-${{ inputs.review_app_key }} - concurrency_tag: ${{ inputs.review_app_key }} + aws_task_prefix: core-review-${{ inputs.pr_number }} + concurrency_tag: ${{ inputs.pr_number }} environment: review + ref: ${{ needs.get_pr_head_sha.outputs.pr_head_sha }} permissions: id-token: write diff --git a/.github/workflows/production_pipeline.yml b/.github/workflows/production_pipeline.yml index b4a188415..45a31167f 100644 --- a/.github/workflows/production_pipeline.yml +++ b/.github/workflows/production_pipeline.yml @@ -3,7 +3,6 @@ name: Production CI/CD Pipeline on: release: types: [released] - workflow_dispatch: defaults: run: diff --git a/.github/workflows/review_pipeline.yml b/.github/workflows/review_pipeline.yml index 5c89d91e3..13b1fbf54 100644 --- a/.github/workflows/review_pipeline.yml +++ b/.github/workflows/review_pipeline.yml @@ -9,13 +9,18 @@ on: required: true type: string description: "The number of the PR for which to deploy a review app. Note: this is NOT the ticket number" + pull_request: + types: [synchronize] + +concurrency: + group: deploy-review${{ github.event.pull_request.number || inputs.pr_number || github.event.issue.number }} permissions: {} jobs: get_pr_details: name: Get PR details - if: github.event_name == 'workflow_dispatch' || (github.event.issue.pull_request && startsWith(github.event.comment.body, '/deploy-review')) + if: github.event_name == 'workflow_dispatch' || (github.event.issue.pull_request && startsWith(github.event.comment.body, '/deploy-review')) || github.event_name == 'pull_request' runs-on: ubuntu-latest outputs: pr_number: ${{ steps.get_pr_details.outputs.pr_number }} @@ -29,6 +34,8 @@ jobs: let prNumber; if (context.eventName === 'workflow_dispatch') { prNumber = '${{ inputs.pr_number }}'; + } else if (context.eventName === 'pull_request') { + prNumber = context.payload.pull_request.number.toString(); } else { prNumber = context.issue.number.toString(); } @@ -40,8 +47,52 @@ jobs: }); core.setOutput('pr_head_sha', pr.head.sha); + check_deployment_started: + name: Check if deployment has been started + if: github.event_name == 'pull_request' + needs: [get_pr_details] + runs-on: ubuntu-latest + permissions: + pull-requests: read + outputs: + started: ${{ steps.check.outputs.started }} + steps: + - name: Check for previous deployment workflow runs + id: check + uses: actions/github-script@v7 + with: + script: | + const prNumber = '${{ needs.get_pr_details.outputs.pr_number }}'; + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: parseInt(prNumber), + }); + const deployComment = comments.find(c => c.body === 'Starting review app deployment...'); + core.setOutput('started', deployComment ? 'true' : 'false'); + + deployment_started_comment: + name: Comment deployment started + if: github.event_name != 'pull_request' + needs: [get_pr_details] + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - name: Comment on PR + uses: actions/github-script@v7 + with: + script: | + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: ${{ needs.get_pr_details.outputs.pr_number }}, + body: 'Starting review app deployment...', + }); + infra: name: Deploy review app infrastructure + if: github.event_name != 'pull_request' needs: [get_pr_details] uses: communitiesuk/submit-social-housing-lettings-and-sales-data-infrastructure/.github/workflows/create_review_app_infra.yml@main with: @@ -52,6 +103,7 @@ jobs: code: name: Deploy review app code + if: github.event_name != 'pull_request' needs: [get_pr_details, infra] uses: ./.github/workflows/aws_deploy.yml with: @@ -64,8 +116,24 @@ jobs: permissions: id-token: write + auto_update_code: + name: Auto-update review app code + if: github.event_name == 'pull_request' && needs.check_deployment_started.outputs.started == 'true' + needs: [get_pr_details, check_deployment_started] + uses: ./.github/workflows/aws_deploy.yml + with: + aws_account_id: 837698168072 + aws_role_prefix: core-dev + aws_task_prefix: core-review-${{ needs.get_pr_details.outputs.pr_number }} + concurrency_tag: ${{ needs.get_pr_details.outputs.pr_number }} + environment: review + ref: ${{ needs.get_pr_details.outputs.pr_head_sha }} + permissions: + id-token: write + comment: name: Add link to PR + if: github.event_name != 'pull_request' needs: [get_pr_details, code] runs-on: ubuntu-latest permissions: diff --git a/.github/workflows/review_teardown_pipeline.yml b/.github/workflows/review_teardown_pipeline.yml index 8925b3340..0df3ad0b7 100644 --- a/.github/workflows/review_teardown_pipeline.yml +++ b/.github/workflows/review_teardown_pipeline.yml @@ -1,27 +1,85 @@ name: Review app teardown pipeline concurrency: - group: review-${{ github.event.pull_request.number }} + group: deploy-review${{ github.event.pull_request.number || inputs.pr_number }} on: pull_request: types: - closed workflow_dispatch: + inputs: + pr_number: + required: true + type: string + description: "The PR number of the review app to tear down. Note: this is NOT the ticket number" + +permissions: {} env: app_repo_role: arn:aws:iam::815624722760:role/core-application-repo aws_account_id: 837698168072 aws_region: eu-west-2 aws_role_prefix: core-dev - aws_task_prefix: core-review-${{ github.event.pull_request.number }} jobs: + get_pr_number: + name: Get PR number + runs-on: ubuntu-latest + outputs: + pr_number: ${{ steps.get.outputs.pr_number }} + steps: + - name: Get PR number + id: get + run: | + if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then + echo "pr_number=${{ inputs.pr_number }}" >> $GITHUB_OUTPUT + else + echo "pr_number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT + fi + + check_review_app_exists: + name: Check if review app exists + needs: [get_pr_number] + runs-on: ubuntu-latest + permissions: + id-token: write + outputs: + exists: ${{ steps.check.outputs.exists }} + steps: + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-region: ${{ env.aws_region }} + role-to-assume: ${{ env.app_repo_role }} + + - name: Configure AWS credentials for review environment + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-region: ${{ env.aws_region }} + role-to-assume: arn:aws:iam::${{ env.aws_account_id }}:role/${{ env.aws_role_prefix }}-deployment + role-chaining: true + + - name: Check if ECS service exists + id: check + env: + aws_task_prefix: core-review-${{ needs.get_pr_number.outputs.pr_number }} + run: | + if aws ecs describe-services --cluster ${{ env.aws_task_prefix }}-app --services ${{ env.aws_task_prefix }}-app --query "services[?status=='ACTIVE']" | grep -q 'serviceName'; then + echo "exists=true" >> $GITHUB_OUTPUT + else + echo "exists=false" >> $GITHUB_OUTPUT + fi + database: name: Drop database + if: needs.check_review_app_exists.outputs.exists == 'true' + needs: [get_pr_number, check_review_app_exists] runs-on: ubuntu-latest permissions: id-token: write + env: + aws_task_prefix: core-review-${{ needs.get_pr_number.outputs.pr_number }} steps: - name: Configure AWS credentials @@ -55,10 +113,11 @@ jobs: infra: name: Teardown review app - needs: [database] + if: needs.check_review_app_exists.outputs.exists == 'true' + needs: [get_pr_number, check_review_app_exists, database] uses: communitiesuk/submit-social-housing-lettings-and-sales-data-infrastructure/.github/workflows/destroy_review_app_infra.yml@main with: - key: ${{ github.event.pull_request.number }} + key: ${{ needs.get_pr_number.outputs.pr_number }} app_repo_role: arn:aws:iam::815624722760:role/core-application-repo permissions: id-token: write