Skip to content

Commit 30806bc

Browse files
committed
feat(ci): update concourse config
1 parent f950661 commit 30806bc

File tree

5 files changed

+338
-113
lines changed

5 files changed

+338
-113
lines changed

concourse/ci.yml

Lines changed: 278 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
---
2-
# Kics linting thinks that the "password" and "github_access_token" keys are secrets, but they are not.
3-
# These instances are ignored appropriately.
1+
resource_types:
2+
- name: key-value
3+
type: registry-image
4+
source:
5+
repository: gstack/keyval-resource
46

57
resources:
68
- name: resource-repo
@@ -9,76 +11,298 @@ resources:
911
source:
1012
uri: https://github.com/ONS-Innovation/github-copilot-usage-lambda
1113
username: ((github_access_token))
12-
# kics-scan ignore-line
1314
password: x-oauth-basic # checkov:skip=CKV_SECRET_6:Checkov thinks this is a secret, but it is not
1415
branch: ((branch))
16+
- name: github-release
17+
type: github-release
18+
source:
19+
owner: ONS-Innovation
20+
repository: github-copilot-usage-lambda
21+
access_token: ((github_access_token))
22+
- name: github-release-tag
23+
type: key-value
24+
source:
25+
file: tag-output/tag
26+
27+
# TODO: Setup shared ECR for Address Book Lambda. Sample below for reference.
28+
29+
# - name: images-to-shared-ecr-backend
30+
# type: registry-image
31+
# source:
32+
# repository: github-copilot-usage-lambda
33+
# aws_role_arn: arn:aws:iam::((aws_account_sdp_((env)))):role/sdp-concourse-((env))
34+
# aws_account_id: ((aws_account_ecr_shared_account))
35+
# aws_region: eu-west-2
36+
37+
# Define the common terraform task as an anchor
38+
terraform-task: &terraform-task
39+
task: terraform-deploy
40+
privileged: true
41+
config:
42+
platform: linux
43+
image_resource:
44+
type: docker-image
45+
source:
46+
repository: hashicorp/terraform
47+
inputs:
48+
- name: resource-repo
49+
- name: github-release-tag
50+
params:
51+
secrets: ((sdp_((env))_copilot_usage_lambda_secrets))
52+
github_access_token: ((github_access_token))
53+
env: ((env))
54+
branch: ((branch))
55+
run:
56+
path: sh
57+
args:
58+
- -cx
59+
- |
60+
echo "DEBUG: Environment is ${env}"
61+
echo "DEBUG: Tag is ${tag}"
62+
export tag=$(cat github-release-tag/tag)
63+
if [[ "$env" == "prod" ]] && [[ "$branch" != "main" && "$branch" != "master" ]]; then
64+
echo "Not on main branch, skipping terraform for prod."
65+
exit 0
66+
fi
67+
apk add --no-cache jq curl
68+
if [[ "$env" == "prod" && ! "$tag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
69+
echo "ERROR: Tag '$tag' is not in semantic versioning format (vX.Y.Z)"
70+
exit 1
71+
fi
72+
chmod u+x ./resource-repo/concourse/scripts/terraform_infra.sh
73+
./resource-repo/concourse/scripts/terraform_infra.sh
74+
timeout: 30m
75+
76+
notify-azure-webhook-task: &notify-azure-webhook-task
77+
config:
78+
platform: linux
79+
params:
80+
secrets: ((sdp_azure_webhook_secrets))
81+
branch: ((branch))
82+
env: ((env))
83+
image_resource:
84+
type: registry-image
85+
source:
86+
repository: alpine
87+
tag: latest
88+
run:
89+
path: sh
90+
args:
91+
- -euc
92+
- |
93+
if [ "$branch" != "main" ]; then
94+
echo "Branch is '${branch}', skipping webhook notification."
95+
exit 0
96+
fi
97+
apk add --no-cache curl jq
98+
99+
AZURE_CLIENT_ID=$(echo "$secrets" | jq -r .azure_client_id)
100+
AZURE_CLIENT_SECRET=$(echo "$secrets" | jq -r .azure_client_secret)
101+
AZURE_SCOPE=$(echo "$secrets" | jq -r .azure_scope)
102+
AZURE_TENANT_ID=$(echo "$secrets" | jq -r .azure_tenant_id)
103+
AZURE_WEBHOOK_URL=$(echo "$secrets" | jq -r .azure_webhook_url)
104+
CHANNEL_ID=$(echo "$secrets" | jq -r .channel_id)
105+
106+
token_json="$(curl -sS -X POST \
107+
"https://login.microsoftonline.com/${AZURE_TENANT_ID}/oauth2/v2.0/token" \
108+
-H "Content-Type: application/x-www-form-urlencoded" \
109+
--data-urlencode "client_id=${AZURE_CLIENT_ID}" \
110+
--data-urlencode "client_secret=${AZURE_CLIENT_SECRET}" \
111+
--data-urlencode "grant_type=client_credentials" \
112+
--data-urlencode "scope=${AZURE_SCOPE}")"
113+
114+
access_token="$(printf '%s' "$token_json" | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p')"
115+
if [ -z "$access_token" ]; then
116+
echo "Failed to get access token. Response:"
117+
echo "$token_json"
118+
exit 1
119+
fi
120+
121+
msg="status:🚨 Concourse failure<br>service: Copilot Usage Lambda<br> event: Pipeline failure in the ${env} environment."
122+
123+
payload="$(cat <<JSON
124+
{"channel":"${CHANNEL_ID}","message":"${msg}"}
125+
JSON
126+
)"
127+
128+
curl -sS -X POST "$AZURE_WEBHOOK_URL" \
129+
-H "Authorization: Bearer ${access_token}" \
130+
-H "Content-Type: application/json" \
131+
-d "$payload"
15132
16133
jobs:
17-
- name: build-and-push
134+
- name: calculate-tag
18135
public: true
19136
plan:
137+
- get: github-release
138+
trigger: true
20139
- get: resource-repo
21-
timeout: 5m
22-
- task: build-image
23-
privileged: true
140+
trigger: false
141+
- task: calculate-tag
24142
config:
25143
platform: linux
26144
image_resource:
27145
type: docker-image
28146
source:
29-
repository: hashicorp/terraform
147+
repository: alpine
30148
inputs:
31149
- name: resource-repo
150+
- name: github-release
151+
outputs:
152+
- name: tag-output # Output directory for the tag
153+
- name: built-images # Output directory for built images
32154
params:
33-
aws_account_id: ((aws_account_sdp_((env))))
34-
aws_role_arn: arn:aws:iam::((aws_account_sdp_((env)))):role/sdp-concourse-((env))
35-
secrets: ((sdp_((env))_github_copilot_secrets))
36-
run: # binary used to build the image
37-
path: sh
38-
args:
39-
- -cx
40-
- |
41-
apk add --no-cache aws-cli podman jq iptables curl
42-
43-
if [[ "((env))" == "prod" ]]; then
44-
tag=$(curl "https://api.github.com/repos/ONS-Innovation/github-copilot-usage-lambda/releases" | jq -r '.[0].tag_name')
45-
export tag
46-
else
47-
export tag=((tag))
48-
fi
49-
git rev-parse --abbrev-ref HEAD
50-
chmod u+x ./resource-repo/concourse/scripts/assume_role.sh
51-
chmod u+x ./resource-repo/concourse/scripts/build_image.sh
52-
source ./resource-repo/concourse/scripts/assume_role.sh
53-
./resource-repo/concourse/scripts/build_image.sh
54-
timeout: 10m
55-
- task: terraform
56-
privileged: true
57-
config:
58-
platform: linux
59-
image_resource:
60-
type: docker-image
61-
source: { repository: hashicorp/terraform }
62-
inputs:
63-
- name: resource-repo
64-
params:
65-
secrets: ((sdp_((env))_github_copilot_secrets))
66-
# kics-scan ignore-line
67-
github_access_token: ((github_access_token))
155+
branch: ((branch))
68156
run:
69157
path: sh
70158
args:
71159
- -cx
72160
- |
73-
apk add --no-cache jq curl
74-
75-
if [[ "((env))" == "prod" ]]; then
76-
tag=$(curl "https://api.github.com/repos/ONS-Innovation/github-copilot-usage-lambda/releases" | jq -r '.[0].tag_name')
77-
export tag
161+
apk add --no-cache git
162+
echo "Calculating tag for branch: ${branch}"
163+
if [[ "$branch" == "main" || "$branch" == "master" ]]; then
164+
# Get the latest tag that matches the format vX.Y.Z
165+
tag=$(git -C resource-repo tag --list 'v[0-9]*.[0-9]*.[0-9]*' | sort -V | tail -n 1)
166+
if [[ -z "$tag" ]]; then
167+
echo "No valid semantic versioning tags (vX.Y.Z) found. Cannot set pipeline."
168+
exit 1
169+
fi
78170
else
79-
export tag=((tag))
171+
# Remove non-alphanumeric characters and take the first 7 characters
172+
tag=$(echo "${branch}" | tr -cd '[:alnum:]' | cut -c1-7)
80173
fi
81-
chmod u+x ./resource-repo/concourse/scripts/terraform_infra.sh
82-
export env=((env))
83-
./resource-repo/concourse/scripts/terraform_infra.sh
84-
timeout: 30m
174+
echo "Calculated tag: ${tag}"
175+
# Write the tag to a file for output
176+
echo "${tag}" > tag-output/tag
177+
- put: github-release-tag
178+
params:
179+
directory: tag-output
180+
181+
- name: deploy-after-github-release-dev
182+
public: true
183+
plan:
184+
- do:
185+
- get: github-release-tag
186+
passed: [calculate-tag]
187+
trigger: true
188+
- get: resource-repo
189+
trigger: false
190+
- task: deploy-release
191+
privileged: true
192+
config:
193+
platform: linux
194+
image_resource:
195+
type: docker-image
196+
source:
197+
repository: hashicorp/terraform
198+
inputs:
199+
- name: resource-repo
200+
- name: github-release-tag
201+
outputs:
202+
- name: built-images
203+
- name: release-tag-output
204+
params:
205+
aws_account_id: ((aws_account_sdp_dev))
206+
aws_role_arn: arn:aws:iam::((aws_account_sdp_dev)):role/sdp-concourse-dev
207+
secrets: ((sdp_dev_copilot_usage_lambda_secrets))
208+
env: dev
209+
tag: github-release-tag/tag # Use the release tag from the resource
210+
repo_name: ((repo_name))
211+
run:
212+
path: sh
213+
args:
214+
- -cx
215+
- |
216+
apk add --no-cache aws-cli podman jq iptables curl
217+
export repo_name=((repo_name))
218+
export tag=$(cat github-release-tag/tag)
219+
# Write the tag to a file for output
220+
echo "${tag}" > release-tag-output/tag
221+
echo "Using tag: ${tag}"
222+
chmod u+x ./resource-repo/concourse/scripts/assume_role.sh
223+
chmod u+x ./resource-repo/concourse/scripts/build_image.sh
224+
source ./resource-repo/concourse/scripts/assume_role.sh
225+
./resource-repo/concourse/scripts/build_image.sh
226+
timeout: 15m
227+
228+
# TODO: Setup shared ECR for Address Book Lambda. Sample below for reference.
229+
# - in_parallel:
230+
# - put: image-to-shared-ecr
231+
# inputs:
232+
# - built-images
233+
# - release-tag-output
234+
# params:
235+
# image: built-images/frontend.tar
236+
# additional_tags: release-tag-output/tag
237+
- <<: *terraform-task
238+
params:
239+
github_access_token: ((github_access_token))
240+
env: dev
241+
secrets: ((sdp_dev_copilot_usage_lambda_secrets))
242+
on_failure:
243+
do:
244+
- task: notify-azure-webhook
245+
<<: *notify-azure-webhook-task
246+
params:
247+
env: dev
248+
249+
- name: release-build-and-push-prod
250+
public: true
251+
plan:
252+
- do:
253+
- get: resource-repo
254+
passed: [deploy-after-github-release-dev]
255+
trigger: false # Manual trigger only
256+
timeout: 5m
257+
- get: github-release-tag
258+
passed: [deploy-after-github-release-dev]
259+
- task: build-image
260+
privileged: true
261+
config:
262+
platform: linux
263+
image_resource:
264+
type: docker-image
265+
source:
266+
repository: hashicorp/terraform
267+
inputs:
268+
- name: resource-repo
269+
- name: github-release-tag
270+
outputs:
271+
- name: built-images
272+
params:
273+
aws_account_id: ((aws_account_sdp_prod))
274+
aws_role_arn: arn:aws:iam::((aws_account_sdp_prod)):role/sdp-concourse-prod
275+
secrets: ((sdp_prod_copilot_usage_lambda_secrets))
276+
env: prod
277+
tag: github-release-tag/tag
278+
repo_name: ((repo_name))
279+
branch: ((branch))
280+
run:
281+
path: sh
282+
args:
283+
- -cx
284+
- |
285+
if [[ "$branch" != "main" ]]; then
286+
echo "Not on main branch, skipping build."
287+
exit 0
288+
fi
289+
apk add --no-cache aws-cli podman jq iptables curl
290+
export repo_name=((repo_name))
291+
export tag=$(cat github-release-tag/tag)
292+
echo "Using release tag: ${tag}"
293+
chmod u+x ./resource-repo/concourse/scripts/assume_role.sh
294+
chmod u+x ./resource-repo/concourse/scripts/build_image.sh
295+
source ./resource-repo/concourse/scripts/assume_role.sh
296+
./resource-repo/concourse/scripts/build_image.sh
297+
timeout: 10m
298+
- <<: *terraform-task
299+
params:
300+
github_access_token: ((github_access_token))
301+
env: prod
302+
secrets: ((sdp_prod_copilot_usage_lambda_secrets))
303+
on_failure:
304+
do:
305+
- task: notify-azure-webhook
306+
<<: *notify-azure-webhook-task
307+
params:
308+
env: prod

concourse/scripts/assume_role.sh

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
1-
#!/usr/bin/env bash
1+
#!/bin/sh
2+
3+
# shellcheck disable=SC2154,SC3040
24

3-
# shellcheck disable=SC3040,SC2154,SC2148
45
set -euo pipefail
56

6-
AWS_ACCESS_KEY_ID="$(cat AccessKeyId)"
7-
AWS_SECRET_ACCESS_KEY="$(cat SecretAccessKey)"
8-
AWS_SESSION_TOKEN="$(cat SessionToken)"
7+
apk add --no-cache aws-cli podman jq iptables
98

10-
# shellcheck disable=SC3040,SC2154
119
aws sts assume-role --output text \
1210
--role-arn "${aws_role_arn}" \
1311
--role-session-name concourse-pipeline-run \
1412
--query "Credentials.[AccessKeyId,SecretAccessKey,SessionToken]" |
1513
awk -F '\t' '{print $1 > ("AccessKeyId")}{print $2 > ("SecretAccessKey")}{print $3 > ("SessionToken")}'
1614

17-
# shellcheck disable=SC3040,SC2154
15+
AWS_ACCESS_KEY_ID="$(cat AccessKeyId)"
16+
AWS_SECRET_ACCESS_KEY="$(cat SecretAccessKey)"
17+
AWS_SESSION_TOKEN="$(cat SessionToken)"
18+
1819
export AWS_ACCESS_KEY_ID
1920
export AWS_SECRET_ACCESS_KEY
2021
export AWS_SESSION_TOKEN

0 commit comments

Comments
 (0)