diff --git a/.github/scripts/dispatch_internal_repo_workflow.sh b/.github/scripts/dispatch_internal_repo_workflow.sh new file mode 100755 index 000000000..2e2e89e07 --- /dev/null +++ b/.github/scripts/dispatch_internal_repo_workflow.sh @@ -0,0 +1,252 @@ +#!/bin/bash + +# Triggers a remote GitHub workflow in nhs-notify-internal and waits for completion. + +# Usage: +# ./dispatch_internal_repo_workflow.sh \ +# --infraRepoName \ +# --releaseVersion \ +# --targetWorkflow \ +# --targetEnvironment \ +# --targetComponent \ +# --targetAccountGroup \ +# --terraformAction \ +# --internalRef \ +# --overrides \ +# --overrideProjectName \ +# --overrideRoleName + +# +# All arguments are required except terraformAction, and internalRef. +# Example: +# ./dispatch_internal_repo_workflow.sh \ +# --infraRepoName "nhs-notify-web-template-management" \ +# --releaseVersion "v1.2.3" \ +# --targetWorkflow "deploy.yaml" \ +# --targetEnvironment "prod" \ +# --targetComponent "web" \ +# --targetAccountGroup "core" \ +# --terraformAction "apply" \ +# --internalRef "main" \ +# --overrides "tf_var=someString" \ +# --overrideProjectName nhs \ +# --overrideRoleName nhs-service-iam-role + +set -e + +while [[ $# -gt 0 ]]; do + case $1 in + --infraRepoName) # Name of the infrastructure repo in NHSDigital org (required) + infraRepoName="$2" + shift 2 + ;; + --releaseVersion) # Release version, commit, or tag to deploy (required) + releaseVersion="$2" + shift 2 + ;; + --targetWorkflow) # Name of the workflow file to call in nhs-notify-internal (required) + targetWorkflow="$2" + shift 2 + ;; + --targetEnvironment) # Terraform environment to deploy (required) + targetEnvironment="$2" + shift 2 + ;; + --targetComponent) # Terraform component to deploy (required) + targetComponent="$2" + shift 2 + ;; + --targetAccountGroup) # Terraform account group to deploy (required) + targetAccountGroup="$2" + shift 2 + ;; + --terraformAction) # Terraform action to run (optional) + terraformAction="$2" + shift 2 + ;; + --internalRef) # Internal repo reference branch or tag (optional, default: "main") + internalRef="$2" + shift 2 + ;; + --overrides) # Terraform overrides for passing in extra variables (optional) + overrides="$2" + shift 2 + ;; + --overrideProjectName) # Override the project name (optional) + overrideProjectName="$2" + shift 2 + ;; + --overrideRoleName) # Override the role name (optional) + overrideRoleName="$2" + shift 2 + ;; + *) + echo "[ERROR] Unknown argument: $1" + exit 1 + ;; + esac +done + +# Set default values if not provided +if [[ -z "$PR_TRIGGER_PAT" ]]; then + echo "[ERROR] PR_TRIGGER_PAT environment variable is not set or is empty." + exit 1 +fi + +if [[ -z "$overrides" ]]; then + overrides="" +fi + +if [[ -z "$internalRef" ]]; then + internalRef="main" +fi + +echo "==================== Workflow Dispatch Parameters ====================" +echo " infraRepoName: $infraRepoName" +echo " releaseVersion: $releaseVersion" +echo " targetWorkflow: $targetWorkflow" +echo " targetEnvironment: $targetEnvironment" +echo " targetComponent: $targetComponent" +echo " targetAccountGroup: $targetAccountGroup" +echo " terraformAction: $terraformAction" +echo " internalRef: $internalRef" +echo " overrides: $overrides" +echo " overrideProjectName: $overrideProjectName" +echo " overrideRoleName: $overrideRoleName" +echo " targetProject: $targetProject" + +DISPATCH_EVENT=$(jq -ncM \ + --arg infraRepoName "$infraRepoName" \ + --arg releaseVersion "$releaseVersion" \ + --arg targetEnvironment "$targetEnvironment" \ + --arg targetAccountGroup "$targetAccountGroup" \ + --arg targetComponent "$targetComponent" \ + --arg terraformAction "$terraformAction" \ + --arg targetWorkflow "$targetWorkflow" \ + --arg overrides "$overrides" \ + --arg overrideProjectName "$overrideProjectName" \ + --arg overrideRoleName "$overrideRoleName" \ + --arg targetProject "$targetProject" \ + '{ + "ref": "'"$internalRef"'", + "inputs": ( + (if $infraRepoName != "" then { "infraRepoName": $infraRepoName } else {} end) + + (if $terraformAction != "" then { "terraformAction": $terraformAction } else {} end) + + (if $overrideProjectName != "" then { "overrideProjectName": $overrideProjectName } else {} end) + + (if $overrideRoleName != "" then { "overrideRoleName": $overrideRoleName } else {} end) + + (if $targetProject != "" then { "targetProject": $targetProject } else {} end) + + { + "releaseVersion": $releaseVersion, + "targetEnvironment": $targetEnvironment, + "targetAccountGroup": $targetAccountGroup, + "targetComponent": $targetComponent, + "overrides": $overrides, + } + ) + }') + +echo "[INFO] Triggering workflow '$targetWorkflow' in nhs-notify-internal..." + +trigger_response=$(curl -s -L \ + --fail \ + -X POST \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${PR_TRIGGER_PAT}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/NHSDigital/nhs-notify-internal/actions/workflows/$targetWorkflow/dispatches" \ + -d "$DISPATCH_EVENT" 2>&1) + +if [[ $? -ne 0 ]]; then + echo "[ERROR] Failed to trigger workflow. Response: $trigger_response" + exit 1 +fi + +echo "[INFO] Workflow trigger request sent successfully, waiting for completion..." + +sleep 10 # Wait a few seconds before checking for the presence of the api to account for GitHub updating + +# Poll GitHub API to check the workflow status +workflow_run_url="" + +for _ in {1..18}; do + + response=$(curl -s -L \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${PR_TRIGGER_PAT}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "https://api.github.com/repos/NHSDigital/nhs-notify-internal/actions/runs?event=workflow_dispatch") + + if ! echo "$response" | jq empty 2>/dev/null; then + echo "[ERROR] Invalid JSON response from GitHub API during workflow polling:" + echo "$response" + exit 1 + fi + + workflow_run_url=$(echo "$response" | jq -r \ + --arg targetWorkflow "$targetWorkflow" \ + --arg targetEnvironment "$targetEnvironment" \ + --arg targetAccountGroup "$targetAccountGroup" \ + --arg targetComponent "$targetComponent" \ + --arg terraformAction "$terraformAction" \ + '.workflow_runs[] + | select(.path == ".github/workflows/" + $targetWorkflow) + | select(.name + | contains($targetEnvironment) + and contains($targetAccountGroup) + and contains($targetComponent) + and contains($terraformAction) + ) + | .url') + + if [[ -n "$workflow_run_url" && "$workflow_run_url" != null ]]; then + # Workflow_run_url is a list of all workflows which were run for this combination of inputs, but are the API uri + workflow_run_url=$(echo "$workflow_run_url" | head -n 1) + + # Take the first and strip it back to being an accessible url + # Example https://api.github.com/repos/MyOrg/my-repo/actions/runs/12346789 becomes + # becomes https://github.com/MyOrg/my-repo/actions/runs/12346789 + workflow_run_ui_url=${workflow_run_url/api./} # Strips the api. prefix + workflow_run_ui_url=${workflow_run_ui_url/\/repos/} # Strips the repos/ uri + echo "[INFO] Found workflow run url: $workflow_run_ui_url" + break + fi + + echo "[$(date '+%Y-%m-%d %H:%M:%S')] Waiting for workflow to start..." + sleep 10 +done + +if [[ -z "$workflow_run_url" || "$workflow_run_url" == null ]]; then + echo "[ERROR] Failed to get the workflow run url. Exiting." + exit 1 +fi + +# Wait for workflow completion +while true; do + sleep 10 + response=$(curl -s -L \ + -H "Authorization: Bearer ${PR_TRIGGER_PAT}" \ + -H "Accept: application/vnd.github+json" \ + "$workflow_run_url") + + status=$(echo "$response" | jq -r '.status') + echo "[$(date '+%Y-%m-%d %H:%M:%S')] Workflow status: $status" + + if [ "$status" == "completed" ]; then + conclusion=$(echo "$response" | jq -r '.conclusion') + echo "[$(date '+%Y-%m-%d %H:%M:%S')] Workflow conclusion: $conclusion" + + if [ -z "$conclusion" ] || [ "$conclusion" == "null" ]; then + echo "[WARN] Workflow marked completed but conclusion not yet available, retrying..." + sleep 5 + continue + fi + + if [ "$conclusion" == "success" ]; then + echo "[SUCCESS] Workflow completed successfully!" + exit 0 + else + echo "[FAIL] Workflow failed with conclusion: $conclusion" + exit 1 + fi + fi +done diff --git a/.github/workflows/cicd-1-pull-request.yaml b/.github/workflows/cicd-1-pull-request.yaml index 67f2ce3a8..ac56de064 100644 --- a/.github/workflows/cicd-1-pull-request.yaml +++ b/.github/workflows/cicd-1-pull-request.yaml @@ -27,6 +27,7 @@ jobs: terraform_version: ${{ steps.variables.outputs.terraform_version }} version: ${{ steps.variables.outputs.version }} does_pull_request_exist: ${{ steps.pr_exists.outputs.does_pull_request_exist }} + pr_number: ${{ steps.pr_exists.outputs.pr_number }} steps: - name: "Checkout code" uses: actions/checkout@v5.0.0 @@ -50,12 +51,18 @@ jobs: run: | branch_name=${GITHUB_HEAD_REF:-$(echo $GITHUB_REF | sed 's#refs/heads/##')} echo "Current branch is '$branch_name'" - if gh pr list --head $branch_name | grep -q .; then - echo "Pull request exists" + + pr_json=$(gh pr list --head "$branch_name" --state open --json number --limit 1) + pr_number=$(echo "$pr_json" | jq -r '.[0].number // empty') + + if [[ -n "$pr_number" ]]; then + echo "Pull request exists: #$pr_number" echo "does_pull_request_exist=true" >> $GITHUB_OUTPUT + echo "pr_number=$pr_number" >> $GITHUB_OUTPUT else echo "Pull request doesn't exist" echo "does_pull_request_exist=false" >> $GITHUB_OUTPUT + echo "pr_number=" >> $GITHUB_OUTPUT fi - name: "List variables" run: | @@ -68,6 +75,7 @@ jobs: export TERRAFORM_VERSION="${{ steps.variables.outputs.terraform_version }}" export VERSION="${{ steps.variables.outputs.version }}" export DOES_PULL_REQUEST_EXIST="${{ steps.pr_exists.outputs.does_pull_request_exist }}" + export IS_VERSION_PRERELEASE="${{ steps.variables.outputs.is_version_prerelease }}" make list-variables commit-stage: # Recommended maximum execution time is 2 minutes name: "Commit stage" @@ -99,4 +107,7 @@ jobs: name: "Acceptance stage" needs: [metadata, test-stage] uses: ./.github/workflows/stage-4-acceptance.yaml + if: needs.metadata.outputs.does_pull_request_exist == 'true' || (github.event_name == 'pull_request' && (github.event.action == 'opened' || github.event.action == 'reopened')) || (github.event_name == 'push' && github.ref == 'refs/heads/main') secrets: inherit + with: + pr_number: ${{ needs.metadata.outputs.pr_number }} diff --git a/.github/workflows/dispatch_internal_repo_workflow.yaml b/.github/workflows/dispatch_internal_repo_workflow.yaml deleted file mode 100644 index 526bc563c..000000000 --- a/.github/workflows/dispatch_internal_repo_workflow.yaml +++ /dev/null @@ -1,171 +0,0 @@ -name: Call Notify Internal Infrastructure Workflow - -on: - workflow_call: - inputs: - jobName: - type: string - description: The name of the job triggering the remote workflow - required: true - infraRepoName: - type: string - description: Repository (this one) in the NHSDigital Github Org to deploy from - default: "" - releaseVersion: - type: string - description: The Github release version, commit, or tag. - default: main - targetWorkflow: - type: string - description: The name of the github workflow to call. - required: true - targetEnvironment: - type: string - description: The Terraform environment to deploy - default: main - targetComponent: - type: string - description: The Terraform component to deploy - required: true - targetAccountGroup: - type: string - description: The Terraform group to deploy - required: true - terraformAction: - type: string - description: The Terraform action to run - default: "" - internalRef: - type: string - description: Internal repo reference (branch or tag) - default: "main" - -permissions: - id-token: write - contents: read - -concurrency: - group: ${{ inputs.targetEnvironment }}-${{ inputs.targetAccountGroup }}-${{ inputs.targetComponent }}-${{ inputs.terraformAction }} - -jobs: - trigger: - name: ${{ inputs.jobName }} - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v5.0.0 - - - name: Trigger nhs-notify-internal workflow - shell: bash - run: | - callerRunId="${GITHUB_RUN_ID}-${{ inputs.jobName }}-${GITHUB_RUN_ATTEMPT}" - - DISPATCH_EVENT=$(jq -ncM \ - --arg infraRepoName "${{ inputs.infraRepoName }}" \ - --arg releaseVersion "${{ inputs.releaseVersion }}" \ - --arg targetEnvironment "${{ inputs.targetEnvironment }}" \ - --arg targetAccountGroup "${{ inputs.targetAccountGroup }}" \ - --arg targetComponent "${{ inputs.targetComponent }}" \ - --arg terraformAction "${{ inputs.terraformAction }}" \ - --arg callerRunId "$callerRunId" \ - --arg targetWorkflow "${{ inputs.targetWorkflow }}" \ - '{ - "ref": "${{ inputs.internalRef }}", - "inputs": ( - (if $infraRepoName != "" then { "infraRepoName": $infraRepoName } else {} end) + - (if $terraformAction != "" then { "terraformAction": $terraformAction } else {} end) + - { - "releaseVersion": $releaseVersion, - "targetEnvironment": $targetEnvironment, - "targetAccountGroup": $targetAccountGroup, - "targetComponent": $targetComponent - } + - (if ($targetWorkflow | test("dispatch-(acceptance|contextual|product|security)-tests-.*\\.yaml")) - then { "callerRunId": $callerRunId } else {} end) - ) - }') - - # Trigger The workflow - curl -L \ - --fail \ - --silent \ - -X POST \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${{ secrets.PR_TRIGGER_PAT }}" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "https://api.github.com/repos/NHSDigital/nhs-notify-internal/actions/workflows/${{ inputs.targetWorkflow }}/dispatches" \ - -d "${DISPATCH_EVENT}" - - echo "Workflow triggered. Waiting for the workflow to complete.." - - # Poll GitHub API to check the workflow status - - workflow_run_url="" - for i in {1..18}; do - workflow_run_url=$(curl -s \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${{ secrets.PR_TRIGGER_PAT }}" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "https://api.github.com/repos/NHSDigital/nhs-notify-internal/actions/runs?event=workflow_dispatch" \ - | jq -r \ - --arg callerRunId "$callerRunId" \ - --arg targetWorkflow "${{ inputs.targetWorkflow }}" \ - --arg targetEnvironment "${{ inputs.targetEnvironment }}" \ - --arg targetAccountGroup "${{ inputs.targetAccountGroup }}" \ - --arg targetComponent "${{ inputs.targetComponent }}" \ - --arg terraformAction "${{ inputs.terraformAction }}" \ - '.workflow_runs[] - | select(.path == ".github/workflows/" + $targetWorkflow) - | select(.name - | contains($targetEnvironment) - and contains($targetAccountGroup) - and contains($targetComponent) - and contains($terraformAction) - ) - | if ($targetWorkflow | test("dispatch-(acceptance|contextual|product|security)-tests-.*\\.yaml")) - then select(.name | contains("caller:" + $callerRunId)) - else . - end - | .url') - - if [[ -n "$workflow_run_url" && "$workflow_run_url" != null ]]; then - ui_url=${workflow_run_url/api./} - ui_url=${ui_url/\/repos/} - echo "Found workflow run url: $ui_url" - echo "workflow_run_url=$workflow_run_url" >> $GITHUB_ENV - break - fi - - echo "Waiting for workflow to start..." - sleep 10 - done - - if [[ -z "$workflow_run_url" || "$workflow_run_url" == null ]]; then - echo "Failed to get the workflow run url. Exiting." - exit 1 - fi - - # Wait for workflow completion - while true; do - sleep 10 - response=$(curl -s -L \ - -H "Authorization: Bearer ${{ secrets.PR_TRIGGER_PAT }}" \ - -H "Accept: application/vnd.github+json" \ - $workflow_run_url) - - status=$(echo "$response" | jq -r '.status') - conclusion=$(echo "$response" | jq -r '.conclusion') - - if [ "$status" == "completed" ]; then - if [ "$conclusion" == "success" ]; then - echo "Workflow completed successfully." - exit 0 - else - echo "Workflow failed with conclusion: $conclusion" - exit 1 - fi - fi - - echo "Workflow still running..." - sleep 20 - done diff --git a/.github/workflows/pr_closed.yaml b/.github/workflows/pr_closed.yaml index 5d939d305..c73a1bb61 100644 --- a/.github/workflows/pr_closed.yaml +++ b/.github/workflows/pr_closed.yaml @@ -34,6 +34,7 @@ jobs: deploy-main: needs: check-merge-or-workflow-dispatch name: Deploy changes to main in dev AWS account + runs-on: ubuntu-latest if: needs.check-merge-or-workflow-dispatch.outputs.deploy == 'true' permissions: @@ -45,15 +46,21 @@ jobs: matrix: component: [acct, app] - uses: ./.github/workflows/reusable_internal_repo_build.yaml - secrets: inherit - with: - releaseVersion: main - targetWorkflow: "dispatch-deploy-static-notify-web-template-management-env.yaml" - targetEnvironment: "main" - targetAccountGroup: "nhs-notify-template-management-dev" - targetComponent: ${{ matrix.component }} - terraformAction: "apply" + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Updating Main Environment + env: + PR_TRIGGER_PAT: ${{ secrets.PR_TRIGGER_PAT }} + run: | + bash .github/scripts/dispatch_internal_repo_workflow.sh \ + --releaseVersion "main" \ + --targetWorkflow "dispatch-deploy-static-notify-web-template-management-env.yaml" \ + --targetEnvironment "main" \ + --targetAccountGroup "nhs-notify-template-management-dev" \ + --targetComponent "${{ matrix.component }}" \ + --terraformAction "apply" check-event-schemas-version-change: name: Check for event schemas package version change diff --git a/.github/workflows/pr_create_dynamic_env.yaml b/.github/workflows/pr_create_dynamic_env.yaml index 12b4ad69d..5457b7977 100644 --- a/.github/workflows/pr_create_dynamic_env.yaml +++ b/.github/workflows/pr_create_dynamic_env.yaml @@ -1,4 +1,3 @@ - name: PR Create Environment on: @@ -9,42 +8,27 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: false +permissions: + id-token: write + contents: read + jobs: create-dynamic-environment: name: Create Dynamic Environment runs-on: ubuntu-latest - steps: - - name: Trigger nhs-notify-internal dynamic environment workflow + - uses: actions/checkout@v5.0.0 + - name: Trigger dynamic environment creation + env: + PR_TRIGGER_PAT: ${{ secrets.PR_TRIGGER_PAT }} shell: bash run: | - set -x - this_repo_name=$(echo ${{ github.repository }} | cut -d'/' -f2) - - DISPATCH_EVENT=$(jq -ncM \ - --arg infraRepoName "${this_repo_name}" \ - --arg releaseVersion "${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" \ - --arg targetEnvironment "pr${{ github.event.number }}" \ - --arg targetAccountGroup "nhs-notify-template-management-dev" \ - --arg targetComponent "branch" \ - --arg terraformAction "apply" \ - --arg overrides "branch_name=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" \ - '{ "ref": "main", - "inputs": { - "infraRepoName": $infraRepoName, - "releaseVersion", $releaseVersion, - "targetEnvironment", $targetEnvironment, - "targetAccountGroup", $targetAccountGroup, - "targetComponent", $targetComponent, - "terraformAction", $terraformAction, - "overrides", $overrides, - } - }') - - curl --fail -L \ - -X POST \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${{ secrets.PR_TRIGGER_PAT }}" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - https://api.github.com/repos/NHSDigital/nhs-notify-internal/actions/workflows/dispatch-deploy-dynamic-env.yaml/dispatches \ - -d "${DISPATCH_EVENT}" + .github/scripts/dispatch_internal_repo_workflow.sh \ + --infraRepoName "$(echo ${{ github.repository }} | cut -d'/' -f2)" \ + --releaseVersion "${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" \ + --targetWorkflow "dispatch-deploy-dynamic-env.yaml" \ + --targetEnvironment "pr${{ github.event.number }}" \ + --targetComponent "branch" \ + --targetAccountGroup "nhs-notify-template-management-dev" \ + --terraformAction "apply" \ + --overrides "branch_name=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" diff --git a/.github/workflows/pr_destroy_dynamic_env.yaml b/.github/workflows/pr_destroy_dynamic_env.yaml index 05e71482a..9aecf4e00 100644 --- a/.github/workflows/pr_destroy_dynamic_env.yaml +++ b/.github/workflows/pr_destroy_dynamic_env.yaml @@ -8,40 +8,47 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: false +permissions: + id-token: write + contents: read + jobs: - create-dynamic-environment: + destroy-dynamic-environment: name: Destroy Dynamic Environment runs-on: ubuntu-latest - steps: - - name: Trigger nhs-notify-internal dynamic environment destruction + - uses: actions/checkout@v5.0.0 + + - name: Trigger dynamic environment destruction + env: + PR_TRIGGER_PAT: ${{ secrets.PR_TRIGGER_PAT }} shell: bash run: | - set -x - this_repo_name=$(echo ${{ github.repository }} | cut -d'/' -f2) + .github/scripts/dispatch_internal_repo_workflow.sh \ + --infraRepoName "$(echo ${{ github.repository }} | cut -d'/' -f2)" \ + --releaseVersion "main" \ + --targetWorkflow "dispatch-deploy-dynamic-env.yaml" \ + --targetEnvironment "pr${{ github.event.number }}" \ + --targetComponent "branch" \ + --targetAccountGroup "nhs-notify-template-management-dev" \ + --terraformAction "destroy" - DISPATCH_EVENT=$(jq -ncM \ - --arg infraRepoName "${this_repo_name}" \ - --arg releaseVersion "main" \ - --arg targetEnvironment "pr${{ github.event.number }}" \ - --arg targetAccountGroup "nhs-notify-template-management-dev" \ - --arg targetComponent "branch" \ - --arg terraformAction "destroy" \ - '{ "ref": "main", - "inputs": { - "infraRepoName": $infraRepoName, - "releaseVersion", $releaseVersion, - "targetEnvironment", $targetEnvironment, - "targetAccountGroup", $targetAccountGroup, - "targetComponent", $targetComponent, - "terraformAction", $terraformAction, - } - }') + sandbox-tear-down: + name: Destroy Sandbox Environment + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5.0.0 - curl --fail -L \ - -X POST \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${{ secrets.PR_TRIGGER_PAT }}" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - https://api.github.com/repos/NHSDigital/nhs-notify-internal/actions/workflows/dispatch-deploy-dynamic-env.yaml/dispatches \ - -d "${DISPATCH_EVENT}" + - name: Trigger sandbox environment destruction + shell: bash + env: + PR_TRIGGER_PAT: ${{ secrets.PR_TRIGGER_PAT }} + run: | + .github/scripts/dispatch_internal_repo_workflow.sh \ + --infraRepoName "nhs-notify-web-template-management" \ + --releaseVersion "${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" \ + --targetWorkflow "dispatch-deploy-dynamic-env.yaml" \ + --targetEnvironment "pr${{ github.event.number }}" \ + --targetAccountGroup "nhs-notify-template-management-dev" \ + --targetComponent "sandbox" \ + --terraformAction "destroy" diff --git a/.github/workflows/release_created.yaml b/.github/workflows/release_created.yaml index 5e88dfdeb..a3c45f2f8 100644 --- a/.github/workflows/release_created.yaml +++ b/.github/workflows/release_created.yaml @@ -11,6 +11,7 @@ concurrency: jobs: deploy-main: name: Deploy changes to main in nonprod AWS Account + runs-on: ubuntu-latest permissions: id-token: write @@ -21,12 +22,18 @@ jobs: matrix: component: [acct, app] - uses: ./.github/workflows/reusable_internal_repo_build.yaml - secrets: inherit - with: - releaseVersion: ${{ github.event.release.tag_name }} - targetWorkflow: "dispatch-deploy-static-notify-web-template-management-env.yaml" - targetEnvironment: "main" - targetAccountGroup: "nhs-notify-template-management-nonprod" - targetComponent: ${{ matrix.component }} - terraformAction: "apply" + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Deploy Nonprod Environment + env: + PR_TRIGGER_PAT: ${{ secrets.PR_TRIGGER_PAT }} + run: | + bash .github/scripts/dispatch_internal_repo_workflow.sh \ + --releaseVersion "${{ github.event.release.tag_name }}" \ + --targetWorkflow "dispatch-deploy-static-notify-web-template-management-env.yaml" \ + --targetEnvironment "main" \ + --targetAccountGroup "nhs-notify-template-management-nonprod" \ + --targetComponent "${{ matrix.component }}" \ + --terraformAction "apply" diff --git a/.github/workflows/reusable_internal_repo_build.yaml b/.github/workflows/reusable_internal_repo_build.yaml deleted file mode 100644 index c9a778dd3..000000000 --- a/.github/workflows/reusable_internal_repo_build.yaml +++ /dev/null @@ -1,142 +0,0 @@ -name: Call Notify Internal Infrastructure Deployment -## Sub workflow which plans and deploys Notify components as part of the workflow. -## Review Gates may be required to proceed on triggered builds. - -on: - workflow_call: - inputs: - releaseVersion: - type: string - description: The Github release version, commit, or tag. - default: main - targetWorkflow: - type: string - description: The name of the github workflow to call. - default: main - targetEnvironment: - type: string - description: The Terraform environment to deploy - default: main - targetComponent: - type: string - description: The Terraform component to deploy - required: true - targetAccountGroup: - type: string - description: The Terraform group to deploy - required: true - terraformAction: - type: string - description: The Terraform component to deploy - default: plan - -concurrency: - group: ${{ inputs.targetEnvironment }}-${{ inputs.targetAccountGroup }}-${{ inputs.targetComponent }}-${{ inputs.terraformAction }} - -jobs: - trigger: - runs-on: ubuntu-latest - - permissions: - id-token: write - contents: read - - steps: - - uses: actions/checkout@v5.0.0 - - - name: Trigger nhs-notify-internal static environment workflow deployment - shell: bash - run: | - set -x - - DISPATCH_EVENT=$(jq -ncM \ - --arg releaseVersion ${{ inputs.releaseVersion }} \ - --arg targetEnvironment ${{ inputs.targetEnvironment }} \ - --arg targetAccountGroup ${{ inputs.targetAccountGroup }} \ - --arg targetComponent ${{ inputs.targetComponent }} \ - --arg terraformAction ${{ inputs.terraformAction }} \ - '{ "ref": "main", - "inputs": { - "releaseVersion", $releaseVersion, - "targetEnvironment", $targetEnvironment, - "targetAccountGroup", $targetAccountGroup, - "targetComponent", $targetComponent, - "terraformAction", $terraformAction - } - }') - - # Trigger The workflow - curl -L \ - --fail \ - --silent \ - -X POST \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${{ secrets.PR_TRIGGER_PAT }}" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "https://api.github.com/repos/NHSDigital/nhs-notify-internal/actions/workflows/${{ inputs.targetWorkflow }}/dispatches" \ - -d "${DISPATCH_EVENT}" - - echo "Workflow triggered successfully. HTTP response. Waiting for the workflow to complete.." - - # Poll GitHub API to check the workflow status - run_id="" - for i in {1..12}; do - in_progress=$(curl -s \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${{ secrets.PR_TRIGGER_PAT }}" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "https://api.github.com/repos/NHSDigital/nhs-notify-internal/actions/runs?event=workflow_dispatch&status=in_progress") - - run_id=$(echo "$in_progress" | jq -r \ - --arg env "${{ inputs.targetEnvironment }}" \ - --arg component "${{ inputs.targetComponent }}" \ - --arg group "${{ inputs.targetAccountGroup }}" \ - --arg releaseVersion "${{ inputs.releaseVersion }}" \ - '.workflow_runs[] - | select(.name | contains($env) and contains($component) and contains($group) and contains($releaseVersion)) - | .id' | head -n 1) - - if [[ -n "$run_id" && "$run_id" != null ]]; then - echo "Found workflow run with ID: $run_id" - break - fi - - echo "Waiting for workflow to start..." - sleep 10 - done - - if [[ -z "$run_id" || "$run_id" == null ]]; then - echo "Failed to get the workflow run ID. Exiting." - exit 1 - fi - - # Wait for workflow completion - while true; do - sleep 10 - status=$(curl -s \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${{ secrets.PR_TRIGGER_PAT }}" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "https://api.github.com/repos/NHSDigital/nhs-notify-internal/actions/runs/$run_id" \ - | jq -r '.status') - - conclusion=$(curl -s \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${{ secrets.PR_TRIGGER_PAT }}" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "https://api.github.com/repos/NHSDigital/nhs-notify-internal/actions/runs/$run_id" \ - | jq -r '.conclusion') - - if [ "$status" == "completed" ]; then - if [ "$conclusion" == "success" ]; then - echo "Workflow completed successfully." - exit 0 - else - echo "Workflow failed with conclusion: $conclusion" - exit 1 - fi - fi - - echo "Workflow still running..." - sleep 20 - done diff --git a/.github/workflows/stage-4-acceptance.yaml b/.github/workflows/stage-4-acceptance.yaml index c16eb0447..903658572 100644 --- a/.github/workflows/stage-4-acceptance.yaml +++ b/.github/workflows/stage-4-acceptance.yaml @@ -2,76 +2,46 @@ name: Acceptance stage on: workflow_call: + inputs: + pr_number: + required: true + type: string + permissions: id-token: write contents: read jobs: - generate-sandbox-name: - name: Generate sandbox name + run-acceptance-tests: + name: Run Acceptance Tests runs-on: ubuntu-latest - outputs: - SANDBOX_NAME: ${{ steps.normalize_branch_name.outputs.normalized_branch_name }} - timeout-minutes: 3 steps: - - name: "Checkout code" - uses: actions/checkout@v5.0.0 - - name: "Get normalized branch name" - id: normalize_branch_name - uses: ./.github/actions/normalize-branch-name - - - sandbox-set-up: - name: Step 1 - needs: generate-sandbox-name - uses: ./.github/workflows/dispatch_internal_repo_workflow.yaml - secrets: inherit - with: - jobName: Sandbox set up - infraRepoName: nhs-notify-web-template-management - releaseVersion: ${{ github.head_ref || github.ref_name }} - targetWorkflow: dispatch-deploy-dynamic-env.yaml - targetEnvironment: ${{ needs.generate-sandbox-name.outputs.SANDBOX_NAME }} - targetAccountGroup: nhs-notify-template-management-dev - targetComponent: sandbox - terraformAction: apply - - acceptance-tests: - name: Step 2 - needs: - - sandbox-set-up - - generate-sandbox-name - - # Calls out to the nhs-notify-internal repo. - # The nhs-notify-internal repo will run the tests - # setup in ./.github/actions/acceptance-tests/action.yaml - uses: ./.github/workflows/dispatch_internal_repo_workflow.yaml - secrets: inherit - with: - jobName: Acceptance tests - infraRepoName: nhs-notify-web-template-management - releaseVersion: ${{ github.head_ref || github.ref_name }} - targetWorkflow: dispatch-contextual-tests-dynamic-env.yaml - targetEnvironment: ${{ needs.generate-sandbox-name.outputs.SANDBOX_NAME }} - targetAccountGroup: nhs-notify-template-management-dev - targetComponent: sandbox - - sandbox-tear-down: - name: Step 3 - needs: - - acceptance-tests - - generate-sandbox-name - if: always() - - uses: ./.github/workflows/dispatch_internal_repo_workflow.yaml - secrets: inherit - with: - jobName: Sandbox tear down - infraRepoName: nhs-notify-web-template-management - releaseVersion: ${{ github.head_ref || github.ref_name }} - targetWorkflow: dispatch-deploy-dynamic-env.yaml - targetEnvironment: ${{ needs.generate-sandbox-name.outputs.SANDBOX_NAME }} - targetAccountGroup: nhs-notify-template-management-dev - targetComponent: sandbox - terraformAction: destroy + - uses: actions/checkout@v5.0.0 + + - name: Trigger Sandbox Environment Build + shell: bash + env: + PR_TRIGGER_PAT: ${{ secrets.PR_TRIGGER_PAT }} + run: | + .github/scripts/dispatch_internal_repo_workflow.sh \ + --infraRepoName "nhs-notify-web-template-management" \ + --releaseVersion "${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" \ + --targetWorkflow "dispatch-deploy-dynamic-env.yaml" \ + --targetEnvironment "pr${{ inputs.pr_number }}" \ + --targetAccountGroup "nhs-notify-template-management-dev" \ + --targetComponent "sandbox" \ + --terraformAction "apply" + + - name: Trigger Acceptance Tests + shell: bash + env: + PR_TRIGGER_PAT: ${{ secrets.PR_TRIGGER_PAT }} + run: | + .github/scripts/dispatch_internal_repo_workflow.sh \ + --infraRepoName "nhs-notify-web-template-management" \ + --releaseVersion "${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" \ + --targetWorkflow "dispatch-contextual-tests-dynamic-env.yaml" \ + --targetEnvironment "pr${{ inputs.pr_number }}" \ + --targetAccountGroup "nhs-notify-template-management-dev" \ + --targetComponent "sandbox" diff --git a/package-lock.json b/package-lock.json index 0f328bd82..30c5a1de6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17505,9 +17505,10 @@ } }, "node_modules/@smithy/core": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.8.0.tgz", - "integrity": "sha512-EYqsIYJmkR1VhVE9pccnk353xhs+lB6btdutJEtsp7R055haMJp2yE16eSxw8fv+G0WUY6vqxyYOP8kOqawxYQ==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.9.0.tgz", + "integrity": "sha512-B/GknvCfS3llXd/b++hcrwIuqnEozQDnRL4sBmOac5/z/dr0/yG1PURNPOyU4Lsiy1IyTj8scPxVqRs5dYWf6A==", + "license": "Apache-2.0", "dependencies": { "@smithy/middleware-serde": "^4.0.9", "@smithy/protocol-http": "^5.1.3", @@ -17720,11 +17721,12 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.18.tgz", - "integrity": "sha512-ZhvqcVRPZxnZlokcPaTwb+r+h4yOIOCJmx0v2d1bpVlmP465g3qpVSf7wxcq5zZdu4jb0H4yIMxuPwDJSQc3MQ==", + "version": "4.1.19", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.19.tgz", + "integrity": "sha512-EAlEPncqo03siNZJ9Tm6adKCQ+sw5fNU8ncxWwaH0zTCwMPsgmERTi6CEKaermZdgJb+4Yvh0NFm36HeO4PGgQ==", + "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.8.0", + "@smithy/core": "^3.9.0", "@smithy/middleware-serde": "^4.0.9", "@smithy/node-config-provider": "^4.1.4", "@smithy/shared-ini-file-loader": "^4.0.5", @@ -17738,14 +17740,15 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "4.1.19", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.19.tgz", - "integrity": "sha512-X58zx/NVECjeuUB6A8HBu4bhx72EoUz+T5jTMIyeNKx2lf+Gs9TmWPNNkH+5QF0COjpInP/xSpJGJ7xEnAklQQ==", + "version": "4.1.20", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.20.tgz", + "integrity": "sha512-T3maNEm3Masae99eFdx1Q7PIqBBEVOvRd5hralqKZNeIivnoGNx5OFtI3DiZ5gCjUkl0mNondlzSXeVxkinh7Q==", + "license": "Apache-2.0", "dependencies": { "@smithy/node-config-provider": "^4.1.4", "@smithy/protocol-http": "^5.1.3", "@smithy/service-error-classification": "^4.0.7", - "@smithy/smithy-client": "^4.4.10", + "@smithy/smithy-client": "^4.5.0", "@smithy/types": "^4.3.2", "@smithy/util-middleware": "^4.0.5", "@smithy/util-retry": "^4.0.7", @@ -17902,12 +17905,13 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "4.4.10", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.4.10.tgz", - "integrity": "sha512-iW6HjXqN0oPtRS0NK/zzZ4zZeGESIFcxj2FkWed3mcK8jdSdHzvnCKXSjvewESKAgGKAbJRA+OsaqKhkdYRbQQ==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.5.0.tgz", + "integrity": "sha512-ZSdE3vl0MuVbEwJBxSftm0J5nL/gw76xp5WF13zW9cN18MFuFXD5/LV0QD8P+sCU5bSWGyy6CTgUupE1HhOo1A==", + "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.8.0", - "@smithy/middleware-endpoint": "^4.1.18", + "@smithy/core": "^3.9.0", + "@smithy/middleware-endpoint": "^4.1.19", "@smithy/middleware-stack": "^4.0.5", "@smithy/protocol-http": "^5.1.3", "@smithy/types": "^4.3.2", @@ -18006,12 +18010,13 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.0.26", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.26.tgz", - "integrity": "sha512-xgl75aHIS/3rrGp7iTxQAOELYeyiwBu+eEgAk4xfKwJJ0L8VUjhO2shsDpeil54BOFsqmk5xfdesiewbUY5tKQ==", + "version": "4.0.27", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.27.tgz", + "integrity": "sha512-i/Fu6AFT5014VJNgWxKomBJP/GB5uuOsM4iHdcmplLm8B1eAqnRItw4lT2qpdO+mf+6TFmf6dGcggGLAVMZJsQ==", + "license": "Apache-2.0", "dependencies": { "@smithy/property-provider": "^4.0.5", - "@smithy/smithy-client": "^4.4.10", + "@smithy/smithy-client": "^4.5.0", "@smithy/types": "^4.3.2", "bowser": "^2.11.0", "tslib": "^2.6.2" @@ -18021,15 +18026,16 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.0.26", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.26.tgz", - "integrity": "sha512-z81yyIkGiLLYVDetKTUeCZQ8x20EEzvQjrqJtb/mXnevLq2+w3XCEWTJ2pMp401b6BkEkHVfXb/cROBpVauLMQ==", + "version": "4.0.27", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.27.tgz", + "integrity": "sha512-3W0qClMyxl/ELqTA39aNw1N+pN0IjpXT7lPFvZ8zTxqVFP7XCpACB9QufmN4FQtd39xbgS7/Lekn7LmDa63I5w==", + "license": "Apache-2.0", "dependencies": { "@smithy/config-resolver": "^4.1.5", "@smithy/credential-provider-imds": "^4.0.7", "@smithy/node-config-provider": "^4.1.4", "@smithy/property-provider": "^4.0.5", - "@smithy/smithy-client": "^4.4.10", + "@smithy/smithy-client": "^4.5.0", "@smithy/types": "^4.3.2", "tslib": "^2.6.2" },