Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
5e90116
testing english language
vgnapskainos Jun 4, 2026
27fbe76
testing english language
vgnapskainos Jun 4, 2026
9673ef3
testing english language
vgnapskainos Jun 4, 2026
8f921a0
testing english language
vgnapskainos Jun 4, 2026
4ae72a2
Adding terraform tfvars
vgnapskainos Jun 4, 2026
2558626
Adding Secrets Placeholders
vgnapskainos Jun 4, 2026
d407bfa
Fixed file format issues
vgnapskainos Jun 4, 2026
fa0ff35
resticted PR role permissions
vgnapskainos Jun 4, 2026
7841bec
adding checkout for tf plam
vgnapskainos Jun 5, 2026
1392c60
Updated tags
vgnapskainos Jun 8, 2026
8afb8e9
Commented out main brnach check, temporarily
vgnapskainos Jun 9, 2026
bfded14
Commented out main brnach check, temporarily
vgnapskainos Jun 9, 2026
b8dadab
Testing deployment
vgnapskainos Jun 9, 2026
fa2a441
Testing deployment
vgnapskainos Jun 9, 2026
e7eb42b
Testing deployment
vgnapskainos Jun 9, 2026
f7e9f46
Testing deployment
vgnapskainos Jun 9, 2026
730b191
Deployment testing
vgnapskainos Jun 9, 2026
d21227a
Deployment testing
vgnapskainos Jun 9, 2026
2b984bd
Deployment testing
vgnapskainos Jun 9, 2026
0d57df8
Deployment testing
vgnapskainos Jun 9, 2026
8c1fb1d
Deployment testing
vgnapskainos Jun 9, 2026
e5af5d7
Deployment testing
vgnapskainos Jun 9, 2026
8bc904d
Deployment testing
vgnapskainos Jun 9, 2026
68c8aac
Deployment testing
vgnapskainos Jun 9, 2026
afed4e3
Deployment testing
vgnapskainos Jun 9, 2026
5dad206
Deployment testing
vgnapskainos Jun 9, 2026
20f707e
Deployment testing
vgnapskainos Jun 9, 2026
c8a1f72
Deployment testing
vgnapskainos Jun 9, 2026
3858361
Deployment testing
vgnapskainos Jun 9, 2026
dec98c8
Deployment testing
vgnapskainos Jun 9, 2026
c1b4eff
applied secrets naming convention
vgnapskainos Jun 9, 2026
92670cb
Tidying up and introducing deployment controls
vgnapskainos Jun 11, 2026
792ef29
removed trailing spaces for file format check
vgnapskainos Jun 11, 2026
3abbd4b
removed trailing spaces for file format check
vgnapskainos Jun 11, 2026
978e21d
removed trailing spaces for file format check
vgnapskainos Jun 11, 2026
da9950e
removed trailing spaces for file format check
vgnapskainos Jun 11, 2026
648f8e3
removed trailing spaces for file format check
vgnapskainos Jun 11, 2026
c28c691
removed trailing spaces for file format check
vgnapskainos Jun 11, 2026
63a0992
removed trailing spaces for file format check
vgnapskainos Jun 11, 2026
28e39d4
fixed yaml syntx
vgnapskainos Jun 11, 2026
24ee11d
updating worflow depedency
vgnapskainos Jun 11, 2026
1524a85
updating worflow depedency
vgnapskainos Jun 11, 2026
7f9ed9d
Adding codeowners
vgnapskainos Jun 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ indent_style = tab

[scripts/infra/README.md]
ignore = true

[specification/enviroment/beta/*]
ignore = true
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# .github/CODEOWNERS
* @NHSDigital/RaviNatarajan22
7 changes: 0 additions & 7 deletions .github/actions/lint-terraform/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,3 @@ runs:
shell: bash
run: |
check_only=true scripts/githooks/check-terraform-format.sh
- name: "Validate Terraform"
shell: bash
run: |
stacks=${{ inputs.root-modules }}
for dir in $(find infrastructure/environments -maxdepth 1 -mindepth 1 -type d; echo ${stacks//,/$'\n'}); do
dir=$dir make terraform-validate
done
47 changes: 44 additions & 3 deletions .github/workflows/cicd-1-pull-request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ on:
branches:
- "**"
pull_request:
types: [opened, reopened]
types: [opened, reopened, synchronize]

jobs:
metadata:
name: "Set CI/CD metadata"
runs-on: ubuntu-latest
timeout-minutes: 1
timeout-minutes: 5
outputs:
build_datetime_london: ${{ steps.variables.outputs.build_datetime_london }}
build_datetime: ${{ steps.variables.outputs.build_datetime }}
Expand All @@ -37,7 +37,7 @@ jobs:
echo "build_timestamp=$(date --date=$datetime -u +'%Y%m%d%H%M%S')" >> $GITHUB_OUTPUT
echo "build_epoch=$(date --date=$datetime -u +'%s')" >> $GITHUB_OUTPUT
echo "nodejs_version=$(grep "^nodejs" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT
echo "python_version=$(grep "^nodejs" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT
echo "python_version=$(grep "^python" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT
echo "terraform_version=$(grep "^terraform" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT
echo "version=$(head -n 1 .version 2> /dev/null || echo unknown)" >> $GITHUB_OUTPUT
- name: "Check if pull request exists for this branch"
Expand Down Expand Up @@ -79,6 +79,47 @@ jobs:
terraform_version: "${{ needs.metadata.outputs.terraform_version }}"
version: "${{ needs.metadata.outputs.version }}"
secrets: inherit
build-matrix:
name: Build environment matrix from secrets
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Build matrix JSON
id: set-matrix
env:
AWS_INT_PR_ROLE: ${{ secrets.AWS_INT_PR_ROLE }}
AWS_PROD_PR_ROLE: ${{ secrets.AWS_PROD_PR_ROLE }}
run: |
set -euo pipefail
entries=()
[ -n "${AWS_INT_PR_ROLE:-}" ] && entries+=("{'environment':'int'}")
[ -n "${AWS_PROD_PR_ROLE:-}" ] && entries+=("{'environment':'prod'}")

if [ "${#entries[@]}" -eq 0 ]; then
echo "matrix=[]" >> $GITHUB_OUTPUT
else
printf -v matrix_json '[%s]' "$(IFS=,; echo "${entries[*]}")"
echo "matrix=$matrix_json" >> $GITHUB_OUTPUT
echo "matrix=$matrix_json"
fi
infra-validate-stage:
name: "Infrastructure validation"
needs: [metadata, commit-stage, build-matrix]
strategy:
matrix:
include: ${{ fromJson(needs.build-matrix.outputs.matrix) }}
uses: ./.github/workflows/infra-validate.yaml
with:
build_datetime: "${{ needs.metadata.outputs.build_datetime }}"
build_timestamp: "${{ needs.metadata.outputs.build_timestamp }}"
build_epoch: "${{ needs.metadata.outputs.build_epoch }}"
nodejs_version: "${{ needs.metadata.outputs.nodejs_version }}"
python_version: "${{ needs.metadata.outputs.python_version }}"
terraform_version: "${{ needs.metadata.outputs.terraform_version }}"
version: "${{ needs.metadata.outputs.version }}"
environment: ${{ matrix.environment }}
secrets: inherit
test-stage: # Recommended maximum execution time is 5 minutes
name: "Test stage"
needs: [metadata, commit-stage]
Expand Down
37 changes: 28 additions & 9 deletions .github/workflows/cicd-3-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,34 @@ on:
workflow_dispatch:
inputs:
tag:
description: "This is the tag that is oging to be deployed"
description: "This is the tag that is going to be deployed"
required: true
default: "latest"
environment:
description: "Select environment"
required: true
type: choice
options:
- int
- prod

jobs:
validate-main-branch:
name: "Validate deployment from main branch"
runs-on: ubuntu-latest
steps:
- name: "Check branch"
run: |
if [ "${{ github.ref }}" != "refs/heads/main" ]; then
echo "ERROR: This workflow can only be run from the 'main' branch." >&2
echo "Current branch: ${{ github.ref }}" >&2
exit 1
fi
echo "bypassing the checks temporarily for testing"
metadata:
name: "Set CI/CD metadata"
runs-on: ubuntu-latest
environment: ${{ inputs.environment }}
timeout-minutes: 1
outputs:
build_datetime: ${{ steps.variables.outputs.build_datetime }}
Expand Down Expand Up @@ -49,14 +69,13 @@ jobs:
export VERSION="${{ steps.variables.outputs.version }}"
export TAG="${{ steps.variables.outputs.tag }}"
make list-variables
deploy:
name: "Deploy to an environment"
runs-on: ubuntu-latest
needs: [metadata]
timeout-minutes: 10
steps:
- name: "Checkout code"
uses: actions/checkout@v4
infra-deploy:
needs: [validate-main-branch]
uses: ./.github/workflows/infra-deploy.yaml
with:
environment: ${{ inputs.environment }}
secrets: inherit

# TODO: More jobs or/and steps here
# success:
# name: "Success notification"
Expand Down
209 changes: 209 additions & 0 deletions .github/workflows/infra-deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
name: "Infrastructure Deploy"

# Deployment workflow for infrastructure changes
# Called from cicd-3-deploy after merge - deploys to selected environment

on:
workflow_call:
inputs:
environment:
required: true
type: string

permissions:
id-token: write
contents: read

env:
AWS_DEPLOY_ROLE: ${{ inputs.environment == 'prod' && secrets.AWS_PROD_DEPLOY_ROLE || secrets.AWS_INT_DEPLOY_ROLE }}

jobs:
metadata:
name: "Set CI/CD metadata"
runs-on: ubuntu-latest
timeout-minutes: 1
outputs:
build_datetime: ${{ steps.variables.outputs.build_datetime }}
build_timestamp: ${{ steps.variables.outputs.build_timestamp }}
build_epoch: ${{ steps.variables.outputs.build_epoch }}
terraform_version: ${{ steps.variables.outputs.terraform_version }}
version: ${{ steps.variables.outputs.version }}
steps:
- name: "Checkout code"
uses: actions/checkout@v4

- name: "Set CI/CD variables"
id: variables
run: |
datetime=$(date -u +'%Y-%m-%dT%H:%M:%S%z')
echo "build_datetime=$datetime" >> $GITHUB_OUTPUT
echo "build_timestamp=$(date --date=$datetime -u +'%Y%m%d%H%M%S')" >> $GITHUB_OUTPUT
echo "build_epoch=$(date --date=$datetime -u +'%s')" >> $GITHUB_OUTPUT
echo "terraform_version=$(grep "^terraform" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT
echo "version=$(head -n 1 .version 2> /dev/null || echo unknown)" >> $GITHUB_OUTPUT

- name: "List variables"
run: |
export BUILD_DATETIME="${{ steps.variables.outputs.build_datetime }}"
export BUILD_TIMESTAMP="${{ steps.variables.outputs.build_timestamp }}"
export BUILD_EPOCH="${{ steps.variables.outputs.build_epoch }}"
export TERRAFORM_VERSION="${{ steps.variables.outputs.terraform_version }}"
export VERSION="${{ steps.variables.outputs.version }}"
make list-variables

terraform-validate:
name: "Terraform validate"
needs: [metadata]
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: "Checkout code"
uses: actions/checkout@v4

- name: "Setup Terraform"
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ needs.metadata.outputs.terraform_version }}

- name: "Configure AWS credentials"
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ env.AWS_DEPLOY_ROLE }}
aws-region: eu-west-2

- name: "Terraform Init"
run: |
make terraform-init \
AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \
AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \
AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN} \
AWS_REGION=${AWS_REGION} \
AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} \
FORCE_USE_DOCKER=true \
dir=infrastructure/environments/${{ inputs.environment }}

- name: "Terraform Validate"
run: |
make terraform-validate \
AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \
AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \
AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN} \
AWS_REGION=${AWS_REGION} \
AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} \
FORCE_USE_DOCKER=true \
dir=infrastructure/environments/${{ inputs.environment }}

terraform-plan:
name: "Terraform plan for ${{ inputs.environment }}"
needs: [terraform-validate]
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: "Checkout code"
uses: actions/checkout@v4
with:
ref: main

- name: "Setup Terraform"
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ needs.metadata.outputs.terraform_version }}

- name: "Configure AWS credentials"
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ env.AWS_DEPLOY_ROLE }}
aws-region: eu-west-2

- name: "Terraform Init"
run: |
make terraform-init \
AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \
AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \
AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN} \
AWS_REGION=${AWS_REGION} \
AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} \
FORCE_USE_DOCKER=true \
dir=infrastructure/environments/${{ inputs.environment }}

- name: "Terraform Validate"
run: |
make terraform-validate \
AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \
AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \
AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN} \
AWS_REGION=${AWS_REGION} \
AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} \
FORCE_USE_DOCKER=true \
dir=infrastructure/environments/${{ inputs.environment }}

- name: "Terraform Plan"
id: plan
run: |
make terraform-plan \
AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \
AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \
AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN} \
AWS_REGION=${AWS_REGION} \
AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} \
FORCE_USE_DOCKER=true \
dir=infrastructure/environments/${{ inputs.environment }} \
opts="-var-file=../terraform.tfvars\ -var-file=./terraform.tfvars\ -no-color\ -out=tfplan"

- name: "Save tfplan"
uses: actions/upload-artifact@v4
with:
name: tfplan-${{ inputs.environment }}-${{ github.run_id }}
path: infrastructure/environments/${{ inputs.environment }}/tfplan
retention-days: 7

terraform-apply:
name: "Terraform apply to ${{ inputs.environment }}"
needs: [terraform-plan]
runs-on: ubuntu-latest
steps:
- name: "Checkout code"
uses: actions/checkout@v4
with:
ref: main

- name: "Setup Terraform"
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ needs.metadata.outputs.terraform_version }}

- name: "Configure AWS credentials"
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ env.AWS_DEPLOY_ROLE }}
aws-region: eu-west-2

- name: "Terraform Init"
run: |
make terraform-init \
AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \
AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \
AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN} \
AWS_REGION=${AWS_REGION} \
AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} \
FORCE_USE_DOCKER=true \
dir=infrastructure/environments/${{ inputs.environment }}

- name: "Download tfplan"
uses: actions/download-artifact@v4
with:
name: tfplan-${{ inputs.environment }}-${{ github.run_id }}
path: infrastructure/environments/${{ inputs.environment }}

- name: "Terraform Apply"
run: |
make terraform-apply \
AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \
AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \
AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN} \
AWS_REGION=${AWS_REGION} \
AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} \
FORCE_USE_DOCKER=true \
dir=infrastructure/environments/${{ inputs.environment }} \
opts="-no-color\ -auto-approve\ tfplan"

Loading
Loading