Skip to content

Commit d719ac7

Browse files
authored
Merge pull request #612 from NHSDigital/APIM-Azure-Pipeline
APIM Azure Pipeline
2 parents c5f5204 + 008394a commit d719ac7

3 files changed

Lines changed: 163 additions & 104 deletions

File tree

azure/common/apigee-deployment.yml

Lines changed: 96 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,20 @@ parameters:
2323
- name: fully_qualified_service_name
2424
displayName: Supply a custom name for your release (only valid for release pipeline)
2525
type: string
26-
default: ''
26+
default: ""
2727
- name: ping
2828
displayName: Toggle ping endpoint avaliablility
2929
type: boolean
3030
default: true
3131
- name: hosted_target_connection_path_suffix
3232
type: string
33-
default: ''
33+
default: ""
3434
- name: hosted_target_healthcheck_suffix
3535
type: string
36-
default: '/_status'
36+
default: "/_status"
3737
- name: jinja_templates
3838
type: object
39-
displayName: Key/values for custom jinja templating
39+
displayName: Key/values for custom jinja templating
4040
default: []
4141
- name: enable_monitoring
4242
type: boolean
@@ -85,7 +85,7 @@ parameters:
8585
- name: manual_approval_env
8686
displayName: Custom manual approval env overwrite
8787
type: string
88-
default: 'manual-approval'
88+
default: "manual-approval"
8989
- name: _scoped_pipeline_vars
9090
type: object
9191
displayName: All the pipeline parameters which support per-environment scoping.
@@ -121,12 +121,12 @@ parameters:
121121
- name: _pipeline_defaults
122122
type: object
123123
default:
124-
- name_suffix: '-Pull-Request'
124+
- name_suffix: "-Pull-Request"
125125
deploy_template: pr.yml
126126
environments:
127-
- internal-dev
128-
- internal-dev-sandbox
129-
- name_suffix: '-Release'
127+
- internal-dev
128+
- internal-dev-sandbox
129+
- name_suffix: "-Release"
130130
deploy_template: release.yml
131131
environments:
132132
- internal-dev
@@ -139,107 +139,106 @@ parameters:
139139
- prod
140140
# Deprecated pipeline variables.
141141
- name: product_display_name
142-
default: 'DEPRECATED'
142+
default: "DEPRECATED"
143143
- name: product_description
144-
default: 'DEPRECATED'
144+
default: "DEPRECATED"
145145
- name: portal_api_requires_callback_url
146-
default: 'DEPRECATED'
146+
default: "DEPRECATED"
147147
- name: make_spec_visible
148-
default: 'DEPRECATED'
148+
default: "DEPRECATED"
149149
- name: spec_file
150-
default: 'DEPRECATED'
150+
default: "DEPRECATED"
151151
- name: python_version
152152
type: string
153153
default: "3.13"
154154
- name: agent_pool
155155
type: string
156156
default: "AWS-ECS"
157157

158+
stages:
159+
- template: ./deploy-stages.yml
160+
parameters:
161+
${{ each param in parameters }}:
162+
${{ if notIn(param.key, 'apigee_deployments', '_scoped_pipeline_vars', '_scoped_step_list_vars', '_pipeline_defaults') }}:
163+
${{ if not(contains(join(',', parameters._scoped_pipeline_vars), param.key)) }}:
164+
${{ param.key }}: ${{ param.value }}
158165

159-
extends:
160-
template: ./deploy-stages.yml
161-
parameters:
162-
${{ each param in parameters }}:
163-
${{ if notIn(param.key, 'apigee_deployments', '_scoped_pipeline_vars', '_scoped_step_list_vars', '_pipeline_defaults') }}:
164-
${{ if not(contains(join(',', parameters._scoped_pipeline_vars), param.key)) }}:
165-
${{ param.key }}: ${{ param.value }}
166+
${{ each pipeline_default in parameters._pipeline_defaults }}:
167+
${{ if endsWith(variables['Build.DefinitionName'], pipeline_default.name_suffix) }}:
168+
deploy_template: ${{ pipeline_default.deploy_template }}
166169

167-
${{ each pipeline_default in parameters._pipeline_defaults }}:
168-
${{ if endsWith(variables['Build.DefinitionName'], pipeline_default.name_suffix) }}:
169-
deploy_template: ${{ pipeline_default.deploy_template }}
170+
# If apigee_deployments was specified, accept it regardless of which pipeline we are in
171+
${{ if gt(length(parameters.apigee_deployments), 0) }}:
172+
apigee_deployments:
173+
- ${{ each apigee_deployment in parameters.apigee_deployments }}:
174+
- ${{ if and(eq(apigee_deployment.environment, 'prod'), parameters.prod_requires_approval) }}:
175+
- environment: manual-approval
176+
stage_name: manual_approval
177+
depends_on: []
178+
manual_approval_prod: true
179+
producer_approval: ${{ parameters.prod_producer_approval }}
180+
${{ each var in parameters._scoped_pipeline_vars }}:
181+
${{ var }}: ${{ parameters[var] }}
182+
- ${{ each apigee_deployment in parameters.apigee_deployments }}:
183+
- environment: ${{ apigee_deployment.environment }}
184+
stage_name: ${{ replace(coalesce (apigee_deployment.stage_name, apigee_deployment.environment), '-', '_') }}
185+
${{ each var in parameters._scoped_pipeline_vars }}:
186+
${{ if apigee_deployment[var] }}:
187+
${{ if containsValue(parameters._scoped_step_list_vars, var) }}:
188+
${{ var }}:
189+
- ${{ each step in apigee_deployment[var] }}:
190+
${{ each pair in step }}:
191+
# Assume scoped template paths are
192+
# relative to azure/ in @self repo
193+
${{ if and(eq(pair.key, 'template'), not(contains(pair.value, '@'))) }}:
194+
${{ pair.key }}: azure/${{ pair.value }}@self
195+
${{ if not(and(eq(pair.key, 'template'), not(contains(pair.value, '@')))) }}:
196+
${{ pair.key }}: ${{ pair.value }}
197+
${{ if not(containsValue(parameters._scoped_step_list_vars, var)) }}:
198+
${{ var }}: ${{ apigee_deployment[var] }}
199+
${{ if not(apigee_deployment[var]) }}:
200+
${{ var }}: ${{ parameters[var] }}
201+
${{ if not(apigee_deployment.depends_on) }}:
202+
${{ if or(startsWith(apigee_deployment.environment, 'internal-'), eq(apigee_deployment.environment, 'manual-approval')) }}:
203+
depends_on: []
204+
${{ if and(not(startsWith(apigee_deployment.environment, 'internal-')), ne(apigee_deployment.environment, 'manual-approval')) }}:
205+
depends_on:
206+
- internal_qa
207+
- ${{ if and(eq(apigee_deployment.environment, 'prod'), parameters.prod_requires_approval) }}:
208+
- manual_approval
209+
${{ if apigee_deployment.depends_on }}:
210+
depends_on:
211+
- ${{ each depend_on in apigee_deployment.depends_on }}:
212+
- ${{ depend_on }}
213+
- ${{ if and(eq(apigee_deployment.environment, 'prod'), parameters.prod_requires_approval) }}:
214+
- manual_approval
170215

171-
# If apigee_deployments was specified, accept it regardless of which pipeline we are in
172-
${{ if gt(length(parameters.apigee_deployments), 0) }}:
173-
apigee_deployments:
174-
- ${{ each apigee_deployment in parameters.apigee_deployments }}:
175-
- ${{ if and(eq(apigee_deployment.environment, 'prod'), parameters.prod_requires_approval) }}:
176-
- environment: manual-approval
177-
stage_name: manual_approval
178-
depends_on: []
179-
manual_approval_prod: true
180-
producer_approval: ${{ parameters.prod_producer_approval }}
181-
${{ each var in parameters._scoped_pipeline_vars }}:
182-
${{ var }}: ${{ parameters[var] }}
183-
- ${{ each apigee_deployment in parameters.apigee_deployments }}:
184-
- environment: ${{ apigee_deployment.environment }}
185-
stage_name: ${{ replace(coalesce (apigee_deployment.stage_name, apigee_deployment.environment), '-', '_') }}
186-
${{ each var in parameters._scoped_pipeline_vars }}:
187-
${{ if apigee_deployment[var] }}:
188-
${{ if containsValue(parameters._scoped_step_list_vars, var) }}:
189-
${{ var }}:
190-
- ${{ each step in apigee_deployment[var] }}:
191-
${{ each pair in step }}:
192-
# Assume scoped template paths are
193-
# relative to azure/ in @self repo
194-
${{ if and(eq(pair.key, 'template'), not(contains(pair.value, '@'))) }}:
195-
${{ pair.key }}: azure/${{ pair.value }}@self
196-
${{ if not(and(eq(pair.key, 'template'), not(contains(pair.value, '@')))) }}:
197-
${{ pair.key }}: ${{ pair.value }}
198-
${{ if not(containsValue(parameters._scoped_step_list_vars, var)) }}:
199-
${{ var }}: ${{ apigee_deployment[var] }}
200-
${{ if not(apigee_deployment[var]) }}:
201-
${{ var }}: ${{ parameters[var] }}
202-
${{ if not(apigee_deployment.depends_on) }}:
203-
${{ if or(startsWith(apigee_deployment.environment, 'internal-'), eq(apigee_deployment.environment, 'manual-approval')) }}:
216+
# otherwise set the default parameters for this pipeline
217+
${{ if eq(0, length(parameters.apigee_deployments)) }}:
218+
apigee_deployments:
219+
- ${{ each environment in pipeline_default.environments }}:
220+
- ${{ if notIn(environment, 'internal-dev-sandbox') }}:
221+
- environment: ${{ environment }}
222+
stage_name: ${{ replace(environment, '-', '_') }}
223+
${{ if startsWith(environment, 'internal-') }}:
224+
depends_on: []
225+
${{ if not(startsWith(environment, 'internal-')) }}:
226+
depends_on:
227+
- internal_qa
228+
- internal_qa_sandbox
229+
- ${{ if and(parameters.prod_requires_approval, eq(environment, 'prod')) }}:
230+
- manual_approval
231+
${{ each var in parameters._scoped_pipeline_vars }}:
232+
${{ var }}: ${{ parameters[var] }}
233+
- ${{ if parameters.deploy_review_sandbox }}:
234+
- environment: internal-dev-sandbox
235+
stage_name: internal_dev_sandbox
204236
depends_on: []
205-
${{ if and(not(startsWith(apigee_deployment.environment, 'internal-')), ne(apigee_deployment.environment, 'manual-approval')) }}:
206-
depends_on:
207-
- internal_qa
208-
- ${{ if and(eq(apigee_deployment.environment, 'prod'), parameters.prod_requires_approval) }}:
209-
- manual_approval
210-
${{ if apigee_deployment.depends_on }}:
211-
depends_on:
212-
- ${{ each depend_on in apigee_deployment.depends_on }}:
213-
- ${{ depend_on }}
214-
- ${{ if and(eq(apigee_deployment.environment, 'prod'), parameters.prod_requires_approval) }}:
215-
- manual_approval
216-
217-
# otherwise set the default parameters for this pipeline
218-
${{ if eq(0, length(parameters.apigee_deployments)) }}:
219-
apigee_deployments:
220-
- ${{ each environment in pipeline_default.environments }}:
221-
- ${{ if notIn(environment, 'internal-dev-sandbox') }}:
222-
- environment: ${{ environment }}
223-
stage_name: ${{ replace(environment, '-', '_') }}
224-
${{ if startsWith(environment, 'internal-') }}:
237+
${{ each var in parameters._scoped_pipeline_vars }}:
238+
${{ var }}: ${{ parameters[var] }}
239+
- ${{ if and(parameters.prod_requires_approval, containsValue(pipeline_default.environments, 'prod')) }}:
240+
- environment: manual-approval
241+
stage_name: manual_approval
225242
depends_on: []
226-
${{ if not(startsWith(environment, 'internal-')) }}:
227-
depends_on:
228-
- internal_qa
229-
- internal_qa_sandbox
230-
- ${{ if and(parameters.prod_requires_approval, eq(environment, 'prod')) }}:
231-
- manual_approval
232-
${{ each var in parameters._scoped_pipeline_vars }}:
233-
${{ var }}: ${{ parameters[var] }}
234-
- ${{ if parameters.deploy_review_sandbox }}:
235-
- environment: internal-dev-sandbox
236-
stage_name: internal_dev_sandbox
237-
depends_on: []
238-
${{ each var in parameters._scoped_pipeline_vars }}:
239-
${{ var }}: ${{ parameters[var] }}
240-
- ${{ if and(parameters.prod_requires_approval, containsValue(pipeline_default.environments, 'prod')) }}:
241-
- environment: manual-approval
242-
stage_name: manual_approval
243-
depends_on: []
244-
${{ each var in parameters._scoped_pipeline_vars }}:
245-
${{ var }}: ${{ parameters[var] }}
243+
${{ each var in parameters._scoped_pipeline_vars }}:
244+
${{ var }}: ${{ parameters[var] }}

azure/common/deploy-stage.yml

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,40 @@ stages:
167167

168168
- ${{ if parameters.notify }}:
169169
- bash: |
170-
if [[ -z $(NOTIFY_COMMIT_SHA) ]]; then
171-
export NOTIFY_COMMIT_SHA=`echo "$(Build.SourceVersionMessage)" | cut -d' ' -f2`
172-
echo "##vso[task.setvariable variable=NOTIFY_COMMIT_SHA]$NOTIFY_COMMIT_SHA"
170+
echo "Build.SourceBranch: $(Build.SourceBranch)"
171+
echo "Build.SourceVersion: $(Build.SourceVersion)"
172+
echo "Build.SourceVersionMessage: $(Build.SourceVersionMessage)"
173+
echo "System.PullRequest.SourceCommitId: $(System.PullRequest.SourceCommitId)"
174+
175+
if [[ ! -z "$(NOTIFY_COMMIT_SHA)" ]]; then
176+
echo "##[debug]Using already provided NOTIFY_COMMIT_SHA=$(NOTIFY_COMMIT_SHA)"
173177
else
174-
echo "##[debug]Using already provided NOTIFY_COMMIT_SHA=$(NOTIFY_COMMIT_SHA)"
178+
NOTIFY_COMMIT_SHA=""
179+
180+
if [[ "$(Build.SourceBranch)" =~ ^refs/pull/.+$ ]]; then
181+
if [[ ! -z "$(System.PullRequest.SourceCommitId)" ]]; then
182+
echo "##[debug]Build appears to be a pull request build"
183+
echo "##[debug]Using System.PullRequest.SourceCommitId as NOTIFY_COMMIT_SHA"
184+
NOTIFY_COMMIT_SHA="$(System.PullRequest.SourceCommitId)"
185+
else
186+
echo "##[debug]Build appears to be a pull request build"
187+
echo "##[debug]Extracting NOTIFY_COMMIT_SHA from Build.SourceVersionMessage"
188+
NOTIFY_COMMIT_SHA=$(echo "$(Build.SourceVersionMessage)" | cut -d' ' -f2)
189+
fi
190+
fi
191+
192+
if [[ "$(Build.SourceBranch)" =~ ^refs/tags/.+$ ]] && [[ -z "$NOTIFY_COMMIT_SHA" ]]; then
193+
echo "##[debug]Build appears to be a tag build"
194+
echo "##[debug]Using Build.SourceVersion as NOTIFY_COMMIT_SHA"
195+
NOTIFY_COMMIT_SHA="$(Build.SourceVersion)"
196+
fi
197+
198+
if [[ -z "$NOTIFY_COMMIT_SHA" ]]; then
199+
echo "##[debug]Using Build.SourceVersion as NOTIFY_COMMIT_SHA"
200+
NOTIFY_COMMIT_SHA="$(Build.SourceVersion)"
201+
fi
202+
203+
echo "##vso[task.setvariable variable=NOTIFY_COMMIT_SHA]$NOTIFY_COMMIT_SHA"
175204
fi
176205
displayName: Set NOTIFY_COMMIT_SHA
177206
@@ -180,6 +209,7 @@ stages:
180209
state: pending
181210
description: "Deploy to ${{ parameters.environment }} started"
182211
environment: ${{ parameters.environment }}
212+
stage_name: ${{ parameters.stage_name }}
183213

184214
- ${{ each param in parameters }}:
185215
- ${{ if not(containsValue(parameters._expose_blacklist, param.key)) }}:
@@ -290,10 +320,12 @@ stages:
290320
on_success: true
291321
description: "Deploy to ${{ parameters.environment }} succeeded"
292322
environment: ${{ parameters.environment }}
323+
stage_name: ${{ parameters.stage_name }}
293324

294325
- template: "../components/update-github-status.yml"
295326
parameters:
296327
state: failure
297328
on_failure: true
298329
description: "Deploy to ${{ parameters.environment }} failed"
299330
environment: ${{ parameters.environment }}
331+
stage_name: ${{ parameters.stage_name }}

azure/components/update-github-status.yml

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ parameters:
1414
displayName: Apigee environment deploying against
1515
type: string
1616
default: ""
17+
- name: stage_name
18+
displayName: Azure stage name for unique status context
19+
type: string
20+
default: ""
1721
# Been through a lot of pain to try to get these next two to work. Unfortunately due to how templates
1822
# are expanded, flagging like this is the only way I could find to get it to evaluate properly
1923
- name: on_success
@@ -33,17 +37,41 @@ steps:
3337
export NOTIFY_GITHUB_REPOSITORY=$(Build.Repository.Name)
3438
fi
3539
40+
BUILD_RESULTS_URL="$(System.CollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId)&view=results"
41+
42+
3643
if [[ "$(NOTIFY_COMMIT_SHA)" =~ ^[0-9a-f]+$ ]]; then
37-
echo "Reporting state ${{ parameters.state }} to ${NOTIFY_GITHUB_REPOSITORY}"
38-
echo "##[debug] Hitting https://api.github.com/repos/${NOTIFY_GITHUB_REPOSITORY}/statuses/$(NOTIFY_COMMIT_SHA)"
39-
curl --fail -q -X POST "https://api.github.com/repos/${NOTIFY_GITHUB_REPOSITORY}/statuses/$(NOTIFY_COMMIT_SHA)" -d '{"state": "${{ parameters.state }}", "context": "$(Build.DefinitionName) $environment", "description": "$description", "target_url": "https://dev.azure.com/NHSD-APIM/API Platform/_build/results?buildId=$(Build.BuildID)"}' --user $(GITHUB_USER):$(GITHUB_ACCESS_TOKEN)
44+
if [[ -n "${environment}" && -n "${stage_name}" ]]; then
45+
context_name="$(Build.DefinitionName)[${environment}][${stage_name}]"
46+
elif [[ -n "${environment}" ]]; then
47+
context_name="$(Build.DefinitionName)[${environment}]"
48+
else
49+
context_name="$(Build.DefinitionName)"
50+
fi
51+
52+
echo "Reporting state ${{ parameters.state }} to ${NOTIFY_GITHUB_REPOSITORY}"
53+
echo "##[debug] Hitting https://api.github.com/repos/${NOTIFY_GITHUB_REPOSITORY}/statuses/$(NOTIFY_COMMIT_SHA)"
54+
55+
payload=$(jq -nc \
56+
--arg state "${{ parameters.state }}" \
57+
--arg context "$context_name" \
58+
--arg description "${description}" \
59+
--arg target_url "${BUILD_RESULTS_URL}" \
60+
'{state: $state, context: $context, description: $description, target_url: $target_url}')
61+
62+
curl --fail -q \
63+
-H "Accept: application/vnd.github+json" \
64+
-X POST "https://api.github.com/repos/${NOTIFY_GITHUB_REPOSITORY}/statuses/$(NOTIFY_COMMIT_SHA)" \
65+
-d "${payload}" \
66+
--user $(GITHUB_USER):$(GITHUB_ACCESS_TOKEN)
4067
else
4168
echo "##[warning]$(NOTIFY_COMMIT_SHA) doesn't look like a commit hash"
4269
echo "##[task.logissue type=warning]Task wasn't able to find the right commit sha value to notify github."
4370
fi
4471
env:
4572
description: ${{ parameters.description }}
4673
environment: ${{ parameters.environment }}
74+
stage_name: ${{ parameters.stage_name }}
4775
displayName: "Notify GitHub: ${{ parameters.state }}"
4876
condition: |
4977
or(

0 commit comments

Comments
 (0)