Skip to content

Commit d6551d9

Browse files
[GPCAPIM-260]-[Steel Thread integration testing]-[RP]-4
1 parent 5f845ce commit d6551d9

4 files changed

Lines changed: 138 additions & 426 deletions

File tree

.github/workflows/cicd-1-pull-request.yaml

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -83,17 +83,9 @@ jobs:
8383
IDP_AWS_REPORT_UPLOAD_REGION: ${{ secrets.IDP_AWS_REPORT_UPLOAD_REGION }}
8484
IDP_AWS_REPORT_UPLOAD_ROLE_NAME: ${{ secrets.IDP_AWS_REPORT_UPLOAD_ROLE_NAME }}
8585
IDP_AWS_REPORT_UPLOAD_BUCKET_ENDPOINT: ${{ secrets.IDP_AWS_REPORT_UPLOAD_BUCKET_ENDPOINT }}
86-
test-stage: # Recommended maximum execution time is 5 minutes
87-
name: "Test stage"
88-
needs: [metadata, commit-stage]
89-
uses: ./.github/workflows/stage-2-test.yaml
90-
with:
91-
python_version: "${{ needs.metadata.outputs.python_version }}"
92-
secrets:
93-
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
9486
build-stage: # Recommended maximum execution time is 3 minutes
9587
name: "Build stage"
96-
needs: [metadata, test-stage]
88+
needs: [metadata]
9789
uses: ./.github/workflows/stage-3-build.yaml
9890
if: needs.metadata.outputs.does_pull_request_exist == 'true' || (github.event_name == 'pull_request' && (github.event.action == 'opened' || github.event.action == 'reopened'))
9991
with:
@@ -104,16 +96,3 @@ jobs:
10496
python_version: "${{ needs.metadata.outputs.python_version }}"
10597
terraform_version: "${{ needs.metadata.outputs.terraform_version }}"
10698
version: "${{ needs.metadata.outputs.version }}"
107-
acceptance-stage: # Recommended maximum execution time is 10 minutes
108-
name: "Acceptance stage"
109-
needs: [metadata, build-stage]
110-
uses: ./.github/workflows/stage-4-acceptance.yaml
111-
if: needs.metadata.outputs.does_pull_request_exist == 'true' || (github.event_name == 'pull_request' && (github.event.action == 'opened' || github.event.action == 'reopened'))
112-
with:
113-
build_datetime: "${{ needs.metadata.outputs.build_datetime }}"
114-
build_timestamp: "${{ needs.metadata.outputs.build_timestamp }}"
115-
build_epoch: "${{ needs.metadata.outputs.build_epoch }}"
116-
nodejs_version: "${{ needs.metadata.outputs.nodejs_version }}"
117-
python_version: "${{ needs.metadata.outputs.python_version }}"
118-
terraform_version: "${{ needs.metadata.outputs.terraform_version }}"
119-
version: "${{ needs.metadata.outputs.version }}"

.github/workflows/preview-env.yml

Lines changed: 137 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,11 @@ jobs:
1717
name: Manage preview environment
1818
runs-on: ubuntu-latest
1919

20-
# Needed for OIDC → AWS (recommended)
2120
permissions:
2221
id-token: write
2322
contents: read
2423
pull-requests: write
2524

26-
# One job per branch at a time
2725
concurrency:
2826
group: preview-${{ github.head_ref || github.ref_name }}
2927
cancel-in-progress: true
@@ -35,7 +33,6 @@ jobs:
3533
- name: Checkout repo
3634
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
3735

38-
# Configure AWS credentials (OIDC recommended)
3936
- name: Configure AWS credentials
4037
uses: aws-actions/configure-aws-credentials@4c2b9cc816c86555b61460789ac95da17d7e829b
4138
with:
@@ -49,35 +46,23 @@ jobs:
4946
- name: Compute branch metadata
5047
id: meta
5148
run: |
52-
# For PRs, head_ref is the source branch name
5349
RAW_BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME}}"
54-
55-
# Sanitize branch name for tags / hostnames (lowercase, only allowed chars)
5650
SANITIZED_BRANCH=$(
5751
printf '%s' "$RAW_BRANCH" \
5852
| tr '[:upper:]' '[:lower:]' \
5953
| tr '._' '-' \
6054
| tr -c 'a-z0-9-' '-' \
6155
| sed -E 's/-{2,}/-/g; s/^-+//; s/-+$//'
6256
)
63-
64-
# Last resort fallback if everything got stripped
6557
if [ -z "$SANITIZED_BRANCH" ]; then
6658
SANITIZED_BRANCH="invalid-branch-name"
6759
fi
68-
6960
echo "raw_branch=$RAW_BRANCH" >> $GITHUB_OUTPUT
7061
echo "branch_name=$SANITIZED_BRANCH" >> $GITHUB_OUTPUT
71-
72-
# ECR repo URL (must match core stack's ECR repo)
7362
ECR_URL="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${ECR_REPOSITORY_NAME}"
7463
echo "ecr_url=$ECR_URL" >> $GITHUB_OUTPUT
75-
76-
# Terraform state key for this preview env
7764
TF_STATE_KEY="${PREVIEW_STATE_PREFIX}${SANITIZED_BRANCH}.tfstate"
7865
echo "tf_state_key=$TF_STATE_KEY" >> $GITHUB_OUTPUT
79-
80-
# ALB listener rule priority - derive from PR number (must be unique per listener)
8166
if [ -n "${{ github.event.number }}" ]; then
8267
PRIORITY=$(( 1000 + ${{ github.event.number }} ))
8368
else
@@ -98,24 +83,20 @@ jobs:
9883
run: |
9984
IMAGE_TAG="${{ steps.meta.outputs.branch_name }}"
10085
ECR_URL="${{ steps.meta.outputs.ecr_url }}"
101-
10286
make build IMAGE_TAG="${IMAGE_TAG}" ECR_URL="${ECR_URL}"
10387
10488
- name: Push Docker image to ECR
10589
if: github.event.action != 'closed'
10690
run: |
10791
IMAGE_TAG="${{ steps.meta.outputs.branch_name }}"
10892
ECR_URL="${{ steps.meta.outputs.ecr_url }}"
109-
11093
docker push "${ECR_URL}:${IMAGE_TAG}"
11194
11295
- name: Setup Terraform
11396
uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd
11497
with:
11598
terraform_version: 1.14.0
11699

117-
# ---------- APPLY (PR opened / updated) ----------
118-
119100
- name: Terraform init (apply)
120101
if: github.event.action != 'closed'
121102
working-directory: infrastructure/environments/preview
@@ -133,25 +114,20 @@ jobs:
133114
TF_VAR_image_tag: ${{ steps.meta.outputs.branch_name }}
134115
TF_VAR_alb_rule_priority: ${{ steps.meta.outputs.alb_rule_priority }}
135116
run: |
136-
terraform apply \
137-
-auto-approve
117+
terraform apply -auto-approve
138118
139119
- name: Capture preview TF outputs
140120
if: github.event.action != 'closed'
141121
id: tf-output
142122
working-directory: infrastructure/environments/preview
143123
run: |
144124
terraform output -json > tf-output.json
145-
146125
URL=$(jq -r '.url.value' tf-output.json)
147126
echo "preview_url=$URL" >> $GITHUB_OUTPUT
148-
149127
TG=$(jq -r '.target_group_arn.value' tf-output.json)
150128
echo "target_group=$TG" >> $GITHUB_OUTPUT
151-
152129
ECS_SERVICE=$(jq -r '.ecs_service_name.value' tf-output.json)
153130
echo "ecs_service=$ECS_SERVICE" >> $GITHUB_OUTPUT
154-
155131
ECS_CLUSTER=$(jq -r '.ecs_cluster_name.value' tf-output.json)
156132
echo "ecs_cluster=$ECS_CLUSTER" >> $GITHUB_OUTPUT
157133
@@ -184,7 +160,6 @@ jobs:
184160
proxygen-api-name: ${{ vars.PROXYGEN_API_NAME }}
185161
proxygen-client-id: ${{ vars.PREVIEW_ENV_PROXYGEN_CLIENT_ID }}
186162

187-
# ---------- Ensure re-deployment (PR updated) ----------
188163
- name: Force ECS service redeployment
189164
if: github.event.action == 'synchronize'
190165
id: await-redeployment
@@ -195,7 +170,6 @@ jobs:
195170
--force-new-deployment \
196171
--region ${{ env.AWS_REGION }}
197172
198-
# ---------- DESTROY (PR closed) ----------
199173
- name: Terraform init (destroy)
200174
if: github.event.action == 'closed'
201175
working-directory: infrastructure/environments/preview
@@ -215,14 +189,13 @@ jobs:
215189
run: |
216190
terraform destroy -auto-approve
217191
218-
# ---------- Wait on AWS tasks and notify ----------
219192
- name: Await deployment completion
220193
if: github.event.action != 'closed'
221194
run: |
222195
aws ecs wait services-stable \
223-
--cluster ${{ steps.tf-output.outputs.ecs_cluster }} \
224-
--services ${{ steps.tf-output.outputs.ecs_service }} \
225-
--region ${{ env.AWS_REGION }}
196+
--cluster ${{ steps.tf-output.outputs.ecs_cluster }} \
197+
--services ${{ steps.tf-output.outputs.ecs_service }} \
198+
--region ${{ env.AWS_REGION }}
226199
227200
- name: Get mTLS certs for testing
228201
if: github.event.action != 'closed'
@@ -246,8 +219,6 @@ jobs:
246219
echo "http_result=missing-url" >> "$GITHUB_OUTPUT"
247220
exit 0
248221
fi
249-
250-
# Reachability check: allow 404 (app routes might not exist yet) but fail otherwise
251222
printf '%s' "$_cds_gateway_dev_mtls_client1_key_secret" > /tmp/client1-key.pem
252223
printf '%s' "$_cds_gateway_dev_mtls_client1_key_public" > /tmp/client1-cert.pem
253224
STATUS=$(curl \
@@ -285,6 +256,138 @@ jobs:
285256
echo "http_result=unexpected-status" >> "$GITHUB_OUTPUT"
286257
exit 0
287258
259+
- name: Prepare mTLS cert files for tests
260+
if: github.event.action != 'closed'
261+
run: |
262+
printf '%s' "$_cds_gateway_dev_mtls_client1_key_secret" > /tmp/client1-key.pem
263+
printf '%s' "$_cds_gateway_dev_mtls_client1_key_public" > /tmp/client1-cert.pem
264+
chmod 600 /tmp/client1-key.pem /tmp/client1-cert.pem
265+
266+
- name: Run unit tests against preview
267+
if: github.event.action != 'closed'
268+
env:
269+
BASE_URL: ${{ steps.tf-output.outputs.preview_url }}
270+
MTLS_CERT: /tmp/client1-cert.pem
271+
MTLS_KEY: /tmp/client1-key.pem
272+
run: |
273+
echo "Running unit tests pointing at ${BASE_URL}"
274+
make test-unit
275+
276+
- name: Upload unit test results
277+
if: always()
278+
uses: actions/upload-artifact@v5
279+
with:
280+
name: unit-test-results
281+
path: gateway-api/test-artefacts/
282+
retention-days: 30
283+
284+
- name: Publish unit test results to summary
285+
if: always()
286+
uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86
287+
with:
288+
paths: gateway-api/test-artefacts/unit-tests.xml
289+
290+
- name: Run contract tests against preview
291+
if: github.event.action != 'closed'
292+
env:
293+
BASE_URL: ${{ steps.tf-output.outputs.preview_url }}
294+
MTLS_CERT: /tmp/client1-cert.pem
295+
MTLS_KEY: /tmp/client1-key.pem
296+
run: |
297+
echo "Running contract tests pointing at ${BASE_URL}"
298+
make test-contract
299+
300+
- name: Upload contract test results
301+
if: always()
302+
uses: actions/upload-artifact@v5
303+
with:
304+
name: contract-test-results
305+
path: gateway-api/test-artefacts/
306+
retention-days: 30
307+
308+
- name: Publish contract test results to summary
309+
if: always()
310+
uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86
311+
with:
312+
paths: gateway-api/test-artefacts/contract-tests.xml
313+
314+
- name: Run schema validation tests against preview
315+
if: github.event.action != 'closed'
316+
env:
317+
BASE_URL: ${{ steps.tf-output.outputs.preview_url }}
318+
MTLS_CERT: /tmp/client1-cert.pem
319+
MTLS_KEY: /tmp/client1-key.pem
320+
run: |
321+
echo "Running schema validation tests pointing at ${BASE_URL}"
322+
make test-schema
323+
324+
- name: Upload schema test results
325+
if: always()
326+
uses: actions/upload-artifact@v5
327+
with:
328+
name: schema-test-results
329+
path: gateway-api/test-artefacts/
330+
retention-days: 30
331+
332+
- name: Publish schema test results to summary
333+
if: always()
334+
uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86
335+
with:
336+
paths: gateway-api/test-artefacts/schema-tests.xml
337+
338+
- name: Run integration tests against preview
339+
if: github.event.action != 'closed'
340+
env:
341+
BASE_URL: ${{ steps.tf-output.outputs.preview_url }}
342+
MTLS_CERT: /tmp/client1-cert.pem
343+
MTLS_KEY: /tmp/client1-key.pem
344+
run: |
345+
echo "Running integration tests pointing at ${BASE_URL}"
346+
make test-integration
347+
348+
- name: Upload integration test results
349+
if: always()
350+
uses: actions/upload-artifact@v5
351+
with:
352+
name: integration-test-results
353+
path: gateway-api/test-artefacts/
354+
retention-days: 30
355+
356+
- name: Publish integration test results to summary
357+
if: always()
358+
uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86
359+
with:
360+
paths: gateway-api/test-artefacts/integration-tests.xml
361+
362+
- name: Run acceptance tests against preview
363+
if: github.event.action != 'closed'
364+
env:
365+
BASE_URL: ${{ steps.tf-output.outputs.preview_url }}
366+
MTLS_CERT: /tmp/client1-cert.pem
367+
MTLS_KEY: /tmp/client1-key.pem
368+
run: |
369+
echo "Running acceptance tests pointing at ${BASE_URL}"
370+
make test-acceptance
371+
372+
- name: Upload acceptance test results
373+
if: always()
374+
uses: actions/upload-artifact@v5
375+
with:
376+
name: acceptance-test-results
377+
path: gateway-api/test-artefacts/
378+
retention-days: 30
379+
380+
- name: Publish acceptance test results to summary
381+
if: always()
382+
uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86
383+
with:
384+
paths: gateway-api/test-artefacts/acceptance-tests.xml
385+
386+
- name: Remove mTLS temp files
387+
if: github.event.action != 'closed'
388+
run: |
389+
rm -f /tmp/client1-key.pem /tmp/client1-cert.pem || true
390+
288391
- name: Comment function name on PR
289392
if: github.event_name == 'pull_request' && github.event.action != 'closed'
290393
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd
@@ -300,27 +403,22 @@ jobs:
300403
const issueNumber = context.issue.number;
301404
const smokeStatus = '${{ steps.smoke-test.outputs.http_status }}' || 'n/a';
302405
const smokeResult = '${{ steps.smoke-test.outputs.http_result }}' || 'not-run';
303-
304406
const smokeLabels = {
305407
success: ':white_check_mark: Passed',
306408
'allowed-404': ':white_check_mark: Allowed 404',
307409
'unexpected-status': ':x: Unexpected status',
308410
'missing-url': ':x: Missing URL',
309411
};
310-
311412
const smokeReadable = smokeLabels[smokeResult] ?? smokeResult;
312-
313413
const { data: comments } = await github.rest.issues.listComments({
314414
owner,
315415
repo,
316416
issue_number: issueNumber,
317417
per_page: 100,
318418
});
319-
320419
for (const comment of comments) {
321420
const isBot = comment.user?.login === 'github-actions[bot]';
322421
const isPreviewUpdate = comment.body?.includes('Deployment Complete');
323-
324422
if (isBot && isPreviewUpdate) {
325423
await github.rest.issues.deleteComment({
326424
owner,
@@ -329,7 +427,6 @@ jobs:
329427
});
330428
}
331429
}
332-
333430
const lines = [
334431
'**Deployment Complete**',
335432
`- Preview URL: [${url}](${url}) — [Health endpoint](${url}/health)`,
@@ -339,15 +436,13 @@ jobs:
339436
`- ECS Service: \`${service}\``,
340437
`- ALB Target: \`${alb}\``,
341438
];
342-
343439
await github.rest.issues.createComment({
344440
owner,
345441
repo,
346442
issue_number: issueNumber,
347443
body: lines.join('\n'),
348444
});
349445
350-
# ---------- Security scanning ----------
351446
- name: Trivy filesystem scan
352447
if: github.event.action != 'closed'
353448
uses: nhs-england-tools/trivy-action/image-scan@3456c1657a37d500027fd782e6b08911725392da
@@ -356,8 +451,8 @@ jobs:
356451
artifact-name: trivy-scan-${{ steps.meta.outputs.branch_name }}
357452

358453
- name: Generate SBOM
359-
uses: nhs-england-tools/trivy-action/sbom-scan@3456c1657a37d500027fd782e6b08911725392da
360454
if: github.event.action != 'closed'
455+
uses: nhs-england-tools/trivy-action/sbom-scan@3456c1657a37d500027fd782e6b08911725392da
361456
with:
362457
image-ref: ${{steps.meta.outputs.ecr_url}}:${{steps.meta.outputs.branch_name}}
363458
artifact-name: trivy-sbom-${{ steps.meta.outputs.branch_name }}

0 commit comments

Comments
 (0)