Skip to content

Commit 2a9455f

Browse files
Merge branch 'main' into PRMP-594
2 parents 9fc9b19 + ff79641 commit 2a9455f

15 files changed

+305
-29
lines changed

.github/workflows/automated-deploy-dev.yml

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ jobs:
6161
- name: Run Terraform Plan
6262
id: plan
6363
run: |
64-
terraform plan -input=false -no-color -var-file="${{vars.TF_VARS_FILE}}" -out tf.plan > plan_output.txt 2>&1
64+
terraform plan -lock-timeout=20m -input=false -no-color -var-file="${{vars.TF_VARS_FILE}}" -out tf.plan > plan_output.txt 2>&1
6565
terraform show -no-color tf.plan > tfplan.txt 2>&1
6666
6767
# Mask PEM certificates (BEGIN...END CERTIFICATE)
@@ -202,7 +202,7 @@ jobs:
202202
# Terraform apply will only occur on a push (merge request completion)
203203
- name: Run Terraform Apply
204204
if: github.ref == 'refs/heads/main'
205-
run: terraform apply -auto-approve -input=false tf.plan
205+
run: terraform apply -lock-timeout=20m -auto-approve -input=false tf.plan
206206
working-directory: ./infrastructure
207207

208208
deploy_lambdas:
@@ -220,3 +220,68 @@ jobs:
220220
uses: NHSDigital/national-document-repository/.github/workflows/ui-dev-to-main-ci.yml@main
221221
secrets:
222222
AWS_ASSUME_ROLE: ${{ secrets.AWS_ASSUME_ROLE }}
223+
224+
notify-slack:
225+
runs-on: ubuntu-latest
226+
needs: [terraform_plan_apply, deploy_lambdas, deploy_ui]
227+
if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/main'
228+
steps:
229+
- name: Configure AWS Credentials
230+
uses: aws-actions/configure-aws-credentials@v5
231+
with:
232+
role-to-assume: ${{ secrets.AWS_ASSUME_ROLE }}
233+
aws-region: ${{ vars.AWS_REGION }}
234+
235+
- name: Get slack bot token from SSM parameter store
236+
run: |
237+
slack_bot_token=$(aws ssm get-parameter --name "/ndr/alerting/slack/bot_token" --with-decryption --query "Parameter.Value" --output text)
238+
echo "::add-mask::$slack_bot_token"
239+
echo "SLACK_BOT_TOKEN=$slack_bot_token" >> $GITHUB_ENV
240+
241+
- name: Send Slack Notification
242+
uses: slackapi/[email protected]
243+
with:
244+
method: chat.postMessage
245+
token: ${{ env.SLACK_BOT_TOKEN }}
246+
payload: |
247+
{
248+
"channel": "${{ vars.ALERTS_SLACK_CHANNEL_ID }}",
249+
"attachments": [
250+
{
251+
"color": "#ff0000",
252+
"blocks": [
253+
{
254+
"type": "header",
255+
"text": {
256+
"type": "plain_text",
257+
"text": "❌ Workflow `${{ github.workflow }}` failed"
258+
}
259+
},
260+
{
261+
"type": "section",
262+
"text": {
263+
"type": "mrkdwn",
264+
"text": "*Triggered by:* `${{ github.actor }}`\n*Branch:* `${{ github.ref_name }}`\n*Workflow:* <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|${{ github.workflow }}>"
265+
}
266+
},
267+
{
268+
"type": "divider"
269+
},
270+
{
271+
"type": "section",
272+
"fields": [
273+
{ "type": "mrkdwn", "text": "*terraform_plan_apply:* ${{ needs.terraform_plan_apply.result == 'success' && ':white_check_mark:' || ':x:' }}" },
274+
{ "type": "mrkdwn", "text": "*deploy_lambdas:* ${{ needs.deploy_lambdas.result == 'success' && ':white_check_mark:' || ':x:' }}" },
275+
{ "type": "mrkdwn", "text": "*deploy_ui:* ${{ needs.deploy_ui.result == 'success' && ':white_check_mark:' || ':x:' }}" }
276+
]
277+
},
278+
{
279+
"type": "context",
280+
"elements": [
281+
{ "type": "mrkdwn", "text": "Environment: `development` | Sandbox: `ndr-dev`" }
282+
]
283+
}
284+
]
285+
}
286+
]
287+
}

.github/workflows/automated-sonarqube-cloud-analysis.yml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,60 @@ jobs:
2626
env:
2727
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
2828
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
29+
30+
notify-slack:
31+
runs-on: ubuntu-latest
32+
needs: [sonarqube_cloud]
33+
if: failure() && github.event_name == 'push' && github.ref == 'refs/heads/main'
34+
steps:
35+
- name: Configure AWS Credentials
36+
uses: aws-actions/configure-aws-credentials@v5
37+
with:
38+
role-to-assume: ${{ secrets.AWS_ASSUME_ROLE }}
39+
aws-region: ${{ vars.AWS_REGION }}
40+
41+
- name: Get slack bot token from SSM parameter store
42+
run: |
43+
slack_bot_token=$(aws ssm get-parameter --name "/ndr/alerting/slack/bot_token" --with-decryption --query "Parameter.Value" --output text)
44+
echo "::add-mask::$slack_bot_token"
45+
echo "SLACK_BOT_TOKEN=$slack_bot_token" >> $GITHUB_ENV
46+
47+
- name: Send Slack Notification
48+
uses: slackapi/[email protected]
49+
with:
50+
method: chat.postMessage
51+
token: ${{ env.SLACK_BOT_TOKEN }}
52+
payload: |
53+
{
54+
"channel": "${{ vars.ALERTS_SLACK_CHANNEL_ID }}",
55+
"attachments": [
56+
{
57+
"color": "#ff0000",
58+
"blocks": [
59+
{
60+
"type": "header",
61+
"text": {
62+
"type": "plain_text",
63+
"text": "❌ Workflow `${{ github.workflow }}` failed"
64+
}
65+
},
66+
{
67+
"type": "section",
68+
"text": {
69+
"type": "mrkdwn",
70+
"text": "*Triggered by:* `${{ github.actor }}`\n*Branch:* `${{ github.ref_name }}`\n*Workflow:* <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|${{ github.workflow }}>"
71+
}
72+
},
73+
{
74+
"type": "divider"
75+
},
76+
{
77+
"type": "section",
78+
"fields": [
79+
{ "type": "mrkdwn", "text": "*sonarqube_cloud:* ${{ needs.sonarqube_cloud.result == 'success' && ':white_check_mark:' || ':x:' }}" }
80+
]
81+
}
82+
]
83+
}
84+
]
85+
}

.github/workflows/cron-daily-health-check.yml

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ jobs:
160160
environment: development
161161
python_version: "3.11"
162162
secrets:
163-
AWS_ASSUME_ROLE: ${{ secrets.AWS_ASSUME_ROLE }}
163+
AWS_ASSUME_ROLE: ${{ secrets.AWS_ASSUME_ROLE }}
164164

165165
deploy_lambdas:
166166
name: Deploy Lambdas
@@ -196,3 +196,72 @@ jobs:
196196
sandbox_name: ${{ needs.set_workspace.outputs.workspace }}
197197
environment: development
198198
secrets: inherit
199+
200+
notify-slack:
201+
runs-on: ubuntu-latest
202+
needs: [terraform_plan_apply, run_lambda_unit_tests, run_ui_unit_tests, run_cypress_tests, publish_lambda_layers, deploy_lambdas, deploy_ui]
203+
if: failure()
204+
steps:
205+
- name: Configure AWS Credentials
206+
uses: aws-actions/configure-aws-credentials@v5
207+
with:
208+
role-to-assume: ${{ secrets.AWS_ASSUME_ROLE }}
209+
aws-region: ${{ vars.AWS_REGION }}
210+
211+
- name: Get slack bot token from SSM parameter store
212+
run: |
213+
slack_bot_token=$(aws ssm get-parameter --name "/ndr/alerting/slack/bot_token" --with-decryption --query "Parameter.Value" --output text)
214+
echo "::add-mask::$slack_bot_token"
215+
echo "SLACK_BOT_TOKEN=$slack_bot_token" >> $GITHUB_ENV
216+
217+
- name: Send Slack Notification
218+
uses: slackapi/[email protected]
219+
with:
220+
method: chat.postMessage
221+
token: ${{ env.SLACK_BOT_TOKEN }}
222+
payload: |
223+
{
224+
"channel": "${{ vars.ALERTS_SLACK_CHANNEL_ID }}",
225+
"attachments": [
226+
{
227+
"color": "#ff0000",
228+
"blocks": [
229+
{
230+
"type": "header",
231+
"text": {
232+
"type": "plain_text",
233+
"text": "❌ Workflow `${{ github.workflow }}` failed"
234+
}
235+
},
236+
{
237+
"type": "section",
238+
"text": {
239+
"type": "mrkdwn",
240+
"text": "*Triggered by:* `Scheduled Job`\n*Workflow:* <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|${{ github.workflow }}>"
241+
}
242+
},
243+
{
244+
"type": "divider"
245+
},
246+
{
247+
"type": "section",
248+
"fields": [
249+
{ "type": "mrkdwn", "text": "*terraform_plan_apply:* ${{ needs.terraform_plan_apply.result == 'success' && ':white_check_mark:' || ':x:' }}" },
250+
{ "type": "mrkdwn", "text": "*run_lambda_unit_tests:* ${{ needs.run_lambda_unit_tests.result == 'success' && ':white_check_mark:' || ':x:' }}" },
251+
{ "type": "mrkdwn", "text": "*run_ui_unit_tests:* ${{ needs.run_ui_unit_tests.result == 'success' && ':white_check_mark:' || ':x:' }}" },
252+
{ "type": "mrkdwn", "text": "*run_cypress_tests:* ${{ needs.run_cypress_tests.result == 'success' && ':white_check_mark:' || ':x:' }}" },
253+
{ "type": "mrkdwn", "text": "*publish_lambda_layers:* ${{ needs.publish_lambda_layers.result == 'success' && ':white_check_mark:' || ':x:' }}" },
254+
{ "type": "mrkdwn", "text": "*deploy_lambdas:* ${{ needs.deploy_lambdas.result == 'success' && ':white_check_mark:' || ':x:' }}" },
255+
{ "type": "mrkdwn", "text": "*deploy_ui:* ${{ needs.deploy_ui.result == 'success' && ':white_check_mark:' || ':x:' }}" }
256+
]
257+
},
258+
{
259+
"type": "context",
260+
"elements": [
261+
{ "type": "mrkdwn", "text": "Environment: `development` | Sandbox: `${{ needs.set_workspace.outputs.workspace }}`" }
262+
]
263+
}
264+
]
265+
}
266+
]
267+
}

infrastructure/buckets.tf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,18 @@ module "migration-dynamodb-segment-store" {
8585
force_destroy = local.is_force_destroy
8686
}
8787

88+
module "migration-failed-items-store" {
89+
source = "./modules/s3/"
90+
access_logs_enabled = local.is_production
91+
access_logs_bucket_id = local.access_logs_bucket_id
92+
bucket_name = var.migration_failed_items_store_bucket_name
93+
enable_cors_configuration = false
94+
enable_bucket_versioning = true
95+
environment = var.environment
96+
owner = var.owner
97+
force_destroy = local.is_force_destroy
98+
}
99+
88100
module "statistical-reports-store" {
89101
source = "./modules/s3/"
90102
access_logs_enabled = local.is_production

infrastructure/dynamo_db_review.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
module "document_review_dynamodb_table" {
2+
count = local.is_production ? 0 : 1
23
source = "./modules/dynamo_db"
34
table_name = var.document_review_table_name
45
hash_key = "ID"

infrastructure/lambda-bulk-upload-metadata-processor.tf

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,47 @@ module "bulk-upload-metadata-processor-alarm-topic" {
7272

7373
depends_on = [module.bulk-upload-metadata-processor-lambda, module.sns_encryption_key]
7474
}
75+
76+
resource "aws_cloudwatch_event_rule" "bulk_upload_metadata_processor_lambda_expedite" {
77+
name = "${terraform.workspace}-staging-bulk-store-expedite-folder-object-created-rule"
78+
description = "Trigger bulk_upload_metadata_processor_lambda when a file is added to the expedite/ folder in the staging-bulk-store bucket"
79+
event_pattern = jsonencode({
80+
"source" : ["aws.s3"],
81+
"detail-type" : ["Object Created"],
82+
"detail" : {
83+
"bucket" : {
84+
"name" : [module.ndr-bulk-staging-store.bucket_id]
85+
},
86+
"object" : {
87+
"key" : [{
88+
"prefix" : "expedite/"
89+
}]
90+
}
91+
}
92+
})
93+
depends_on = [
94+
module.ndr-bulk-staging-store
95+
]
96+
}
97+
98+
resource "aws_cloudwatch_event_target" "bulk_upload_metadata_processor_lambda" {
99+
rule = aws_cloudwatch_event_rule.bulk_upload_metadata_processor_lambda_expedite.name
100+
arn = module.bulk-upload-metadata-processor-lambda.lambda_arn
101+
target_id = "bulk-upload-metadata-processor-lambda"
102+
depends_on = [
103+
module.bulk-upload-metadata-processor-lambda,
104+
aws_cloudwatch_event_rule.bulk_upload_metadata_processor_lambda_expedite
105+
]
106+
}
107+
108+
resource "aws_lambda_permission" "bulk_upload_metadata_processor_lambda_expedite" {
109+
statement_id = "AllowEventBridgeInvoke"
110+
action = "lambda:InvokeFunction"
111+
function_name = module.bulk-upload-metadata-processor-lambda.function_name
112+
principal = "events.amazonaws.com"
113+
source_arn = aws_cloudwatch_event_rule.bulk_upload_metadata_processor_lambda_expedite.arn
114+
depends_on = [
115+
module.bulk-upload-metadata-processor-lambda,
116+
aws_cloudwatch_event_rule.bulk_upload_metadata_processor_lambda_expedite
117+
]
118+
}

infrastructure/lambda-dynamodb-migration.tf

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ module "migration-dynamodb-lambda" {
1010
module.ndr-bulk-staging-store.s3_read_policy_document,
1111
module.ndr-lloyd-george-store.s3_read_policy_document,
1212
aws_iam_policy.ssm_access_policy.policy,
13-
module.ndr-app-config.app_config_policy
13+
module.ndr-app-config.app_config_policy,
14+
module.migration-failed-items-store.s3_write_policy_document
1415
]
1516

1617
kms_deletion_window = var.kms_deletion_window
@@ -20,10 +21,11 @@ module "migration-dynamodb-lambda" {
2021
is_invoked_from_gateway = false
2122

2223
lambda_environment_variables = {
23-
WORKSPACE = terraform.workspace
24-
APPCONFIG_APPLICATION = module.ndr-app-config.app_config_application_id
25-
APPCONFIG_ENVIRONMENT = module.ndr-app-config.app_config_environment_id
26-
APPCONFIG_CONFIGURATION = module.ndr-app-config.app_config_configuration_profile_id
24+
WORKSPACE = terraform.workspace
25+
APPCONFIG_APPLICATION = module.ndr-app-config.app_config_application_id
26+
APPCONFIG_ENVIRONMENT = module.ndr-app-config.app_config_environment_id
27+
APPCONFIG_CONFIGURATION = module.ndr-app-config.app_config_configuration_profile_id
28+
MIGRATION_FAILED_ITEMS_STORE_BUCKET_NAME = "${terraform.workspace}-${var.migration_failed_items_store_bucket_name}"
2729
}
2830

2931
lambda_timeout = 900
@@ -35,5 +37,6 @@ module "migration-dynamodb-lambda" {
3537
module.bulk_upload_report_dynamodb_table,
3638
module.ndr-app-config,
3739
aws_iam_policy.ssm_access_policy,
40+
module.migration-failed-items-store
3841
]
3942
}

infrastructure/lambda-mns-notification.tf

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ module "mns-notification-lambda" {
88
module.sqs-mns-notification-queue[0].sqs_write_policy_document,
99
module.lloyd_george_reference_dynamodb_table.dynamodb_write_policy_document,
1010
module.lloyd_george_reference_dynamodb_table.dynamodb_read_policy_document,
11-
module.document_review_dynamodb_table.dynamodb_write_policy_document,
12-
module.document_review_dynamodb_table.dynamodb_read_policy_document,
11+
local.is_production ? "" : module.document_review_dynamodb_table[0].dynamodb_write_policy_document,
12+
local.is_production ? "" : module.document_review_dynamodb_table[0].dynamodb_read_policy_document,
1313
aws_iam_policy.ssm_access_policy.policy,
1414
module.ndr-app-config.app_config_policy,
1515
aws_iam_policy.kms_mns_lambda_access[0].policy,
@@ -23,7 +23,7 @@ module "mns-notification-lambda" {
2323
APPCONFIG_CONFIGURATION = module.ndr-app-config.app_config_configuration_profile_id
2424
WORKSPACE = terraform.workspace
2525
LLOYD_GEORGE_DYNAMODB_NAME = module.lloyd_george_reference_dynamodb_table.table_name
26-
DOCUMENT_REVIEW_DYNAMODB_NAME = module.document_review_dynamodb_table.table_name
26+
DOCUMENT_REVIEW_DYNAMODB_NAME = local.is_production ? "" : module.document_review_dynamodb_table[0].table_name
2727
MNS_NOTIFICATION_QUEUE_URL = module.sqs-mns-notification-queue[0].sqs_url
2828
PDS_FHIR_IS_STUBBED = local.is_sandbox
2929
}

infrastructure/lambda-search-doc-references.tf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ module "search-document-references-lambda" {
6363
module.lloyd_george_reference_dynamodb_table.dynamodb_write_policy_document,
6464
module.ndr-lloyd-george-store.s3_read_policy_document,
6565
module.ndr-document-store.s3_read_policy_document,
66-
module.ndr-app-config.app_config_policy
66+
module.ndr-app-config.app_config_policy,
67+
aws_iam_policy.ssm_access_policy.policy
6768
]
6869
kms_deletion_window = var.kms_deletion_window
6970
rest_api_id = aws_api_gateway_rest_api.ndr_doc_store_api.id

infrastructure/modules/app_config/configurations/dev.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"enabled": "true"
3131
},
3232
"uploadArfWorkflowEnabled": {
33-
"enabled": "true"
33+
"enabled": "false"
3434
},
3535
"useSmartcardAuth": {
3636
"enabled": "false"
@@ -39,10 +39,10 @@
3939
"enabled": "true"
4040
},
4141
"uploadDocumentIteration2Enabled": {
42-
"enabled": "true"
42+
"enabled": "false"
4343
},
4444
"uploadDocumentIteration3Enabled": {
45-
"enabled": "true"
45+
"enabled": "false"
4646
}
4747
},
4848
"version": "1"

0 commit comments

Comments
 (0)