Skip to content

Commit 15f6e70

Browse files
committed
Adds critical build flag
1 parent 1643a57 commit 15f6e70

File tree

4 files changed

+152
-29
lines changed

4 files changed

+152
-29
lines changed

build/ci-pipeline.yml

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
1-
# DESCRIPTION:
2-
# Builds, tests, and packages the solution for the main branch.
1+
# DESCRIPTION:
2+
# Builds, tests, and packages the solution for the main branch.
33

44
name: $(SourceBranchName)-$(Date:yyyyMMdd)$(Rev:-r)
55
trigger: none
66

7+
parameters:
8+
- name: buildCriticalOnly
9+
displayName: 'Build Critical Versions Only (skip R4B/R5)'
10+
type: boolean
11+
default: false
12+
713
variables:
814
- template: ci-variables.yml
915
- template: build-variables.yml
16+
- name: buildCriticalOnly
17+
value: ${{ parameters.buildCriticalOnly }}
1018

1119
stages:
1220
# *********************** Setup ***********************
@@ -124,17 +132,18 @@ stages:
124132
steps:
125133
- template: ./jobs/analyze.yml
126134

127-
- stage: DockerBuild
135+
- stage: DockerBuild
128136
displayName: 'Build images'
129137
dependsOn:
130138
- UpdateVersion
131139
variables:
132140
assemblySemFileVer: $[stageDependencies.UpdateVersion.Semver.outputs['SetVariablesFromGitVersion.assemblySemFileVer']]
133141
jobs:
134142
- template: ./jobs/docker-build-all.yml
135-
parameters:
143+
parameters:
136144
tag: $(ImageTag)
137145
buildPlatform: $(publicDockerImagePlatforms)
146+
buildCriticalOnly: ${{ parameters.buildCriticalOnly }}
138147

139148
# *********************** Stu3 ***********************
140149
- stage: redeployStu3
@@ -217,30 +226,33 @@ stages:
217226
# *********************** R4B ***********************
218227
- stage: redeployR4B
219228
displayName: 'Redeploy R4B CosmosDB Site'
229+
condition: eq(variables.buildCriticalOnly, false)
220230
dependsOn:
221231
- DockerBuild
222232
jobs:
223233
- template: ./jobs/redeploy-webapp.yml
224-
parameters:
234+
parameters:
225235
version: R4B
226236
webAppName: $(DeploymentEnvironmentNameR4B)
227237
subscription: $(ConnectedServiceName)
228238
imageTag: $(ImageTag)
229239

230240
- stage: redeployR4BSql
231241
displayName: 'Redeploy R4B SQL Site'
242+
condition: eq(variables.buildCriticalOnly, false)
232243
dependsOn:
233244
- DockerBuild
234245
jobs:
235246
- template: ./jobs/redeploy-webapp.yml
236-
parameters:
247+
parameters:
237248
version: R4B
238249
webAppName: $(DeploymentEnvironmentNameR4BSql)
239250
subscription: $(ConnectedServiceName)
240251
imageTag: $(ImageTag)
241252

242253
- stage: testR4B
243254
displayName: 'Run R4B Tests'
255+
condition: eq(variables.buildCriticalOnly, false)
244256
dependsOn:
245257
- BuildArtifacts
246258
- redeployR4B
@@ -256,30 +268,33 @@ stages:
256268
# *********************** R5 ***********************
257269
- stage: redeployR5
258270
displayName: 'Redeploy R5 CosmosDB Site'
271+
condition: eq(variables.buildCriticalOnly, false)
259272
dependsOn:
260273
- DockerBuild
261274
jobs:
262275
- template: ./jobs/redeploy-webapp.yml
263-
parameters:
276+
parameters:
264277
version: R5
265278
webAppName: $(DeploymentEnvironmentNameR5)
266279
subscription: $(ConnectedServiceName)
267280
imageTag: $(ImageTag)
268281

269282
- stage: redeployR5Sql
270283
displayName: 'Redeploy R5 SQL Site'
284+
condition: eq(variables.buildCriticalOnly, false)
271285
dependsOn:
272286
- DockerBuild
273287
jobs:
274288
- template: ./jobs/redeploy-webapp.yml
275-
parameters:
289+
parameters:
276290
version: R5
277291
webAppName: $(DeploymentEnvironmentNameR5Sql)
278292
subscription: $(ConnectedServiceName)
279293
imageTag: $(ImageTag)
280294

281295
- stage: testR5
282296
displayName: 'Run R5 Tests'
297+
condition: eq(variables.buildCriticalOnly, false)
283298
dependsOn:
284299
- BuildArtifacts
285300
- redeployR5
@@ -295,6 +310,15 @@ stages:
295310
# *********************** Finalize ***********************
296311
- stage: DockerAddTag
297312
displayName: 'Docker add main tag'
313+
# Run if all tests succeed, or if critical-only mode and Stu3/R4 succeed (R4B/R5 skipped)
314+
condition: |
315+
and(
316+
succeeded(),
317+
or(
318+
and(eq(variables.buildCriticalOnly, false), succeeded('testR4B'), succeeded('testR5')),
319+
and(eq(variables.buildCriticalOnly, true), succeeded('testStu3'), succeeded('testR4'))
320+
)
321+
)
298322
dependsOn:
299323
- testStu3
300324
- testR4

build/jobs/docker-build-all.yml

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,38 @@
1-
# DESCRIPTION:
1+
# DESCRIPTION:
22
# Builds and pushes images for all supported FHIR versions
33

44
parameters:
55
- name: tag
66
type: string
77
- name: buildPlatform
88
type: string
9+
- name: buildCriticalOnly
10+
type: boolean
11+
default: false
912

1013
jobs:
1114
- template: docker-build-push.yml
12-
parameters:
15+
parameters:
1316
version: "R4"
1417
tag: ${{parameters.tag}}
1518
buildPlatform: ${{parameters.buildPlatform}}
1619

17-
- template: docker-build-push.yml
18-
parameters:
19-
version: "R4B"
20-
tag: ${{parameters.tag}}
21-
buildPlatform: ${{parameters.buildPlatform}}
20+
- ${{ if eq(parameters.buildCriticalOnly, false) }}:
21+
- template: docker-build-push.yml
22+
parameters:
23+
version: "R4B"
24+
tag: ${{parameters.tag}}
25+
buildPlatform: ${{parameters.buildPlatform}}
2226

2327
- template: docker-build-push.yml
24-
parameters:
28+
parameters:
2529
version: "Stu3"
2630
tag: ${{parameters.tag}}
2731
buildPlatform: ${{parameters.buildPlatform}}
2832

29-
- template: docker-build-push.yml
30-
parameters:
31-
version: "R5"
32-
tag: ${{parameters.tag}}
33-
buildPlatform: ${{parameters.buildPlatform}}
33+
- ${{ if eq(parameters.buildCriticalOnly, false) }}:
34+
- template: docker-build-push.yml
35+
parameters:
36+
version: "R5"
37+
tag: ${{parameters.tag}}
38+
buildPlatform: ${{parameters.buildPlatform}}

build/pr-pipeline.yml

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
1-
# DESCRIPTION:
2-
# Builds, tests, and packages the solution for all PR requests.
1+
# DESCRIPTION:
2+
# Builds, tests, and packages the solution for all PR requests.
33

44
trigger: none
55

6+
parameters:
7+
- name: buildCriticalOnly
8+
displayName: 'Build Critical Versions Only (skip R4B/R5)'
9+
type: boolean
10+
default: false
11+
612
variables:
713
- template: pr-variables.yml
814
- template: build-variables.yml
15+
- name: buildCriticalOnly
16+
value: ${{ parameters.buildCriticalOnly }}
917

1018
stages:
1119
- stage: UpdateVersion
@@ -95,17 +103,18 @@ stages:
95103
steps:
96104
- template: ./jobs/analyze.yml
97105

98-
- stage: DockerBuild
106+
- stage: DockerBuild
99107
displayName: 'Build images'
100108
dependsOn:
101109
- UpdateVersion
102110
variables:
103111
assemblySemFileVer: $[stageDependencies.UpdateVersion.Semver.outputs['SetVariablesFromGitVersion.assemblySemFileVer']]
104112
jobs:
105113
- template: ./jobs/docker-build-all.yml
106-
parameters:
114+
parameters:
107115
tag: $(ImageTag)
108116
buildPlatform: $(testDockerImagePlatforms)
117+
buildCriticalOnly: ${{ parameters.buildCriticalOnly }}
109118

110119
- stage: provisionEnvironment
111120
displayName: Provision Environment
@@ -271,13 +280,14 @@ stages:
271280

272281
- stage: deployR4B
273282
displayName: 'Deploy R4B CosmosDB Site'
283+
condition: eq(variables.buildCriticalOnly, false)
274284
dependsOn:
275285
- DockerBuild
276286
- setupEnvironment
277287
- createNsp
278288
jobs:
279289
- template: ./jobs/provision-deploy.yml
280-
parameters:
290+
parameters:
281291
version: R4B
282292
webAppName: $(DeploymentEnvironmentNameR4B)
283293
appServicePlanName: '$(appServicePlanName)-cosmos'
@@ -290,13 +300,14 @@ stages:
290300

291301
- stage: deployR4BSql
292302
displayName: 'Deploy R4B SQL Site'
303+
condition: eq(variables.buildCriticalOnly, false)
293304
dependsOn:
294305
- DockerBuild
295306
- setupEnvironment
296307
- deploySqlServer
297308
jobs:
298309
- template: ./jobs/provision-deploy.yml
299-
parameters:
310+
parameters:
300311
version: R4B
301312
sql: true
302313
webAppName: $(DeploymentEnvironmentNameR4BSql)
@@ -313,13 +324,14 @@ stages:
313324

314325
- stage: deployR5
315326
displayName: 'Deploy R5 CosmosDB Site'
327+
condition: eq(variables.buildCriticalOnly, false)
316328
dependsOn:
317329
- DockerBuild
318330
- setupEnvironment
319331
- createNsp
320332
jobs:
321333
- template: ./jobs/provision-deploy.yml
322-
parameters:
334+
parameters:
323335
version: R5
324336
webAppName: $(DeploymentEnvironmentNameR5)
325337
appServicePlanName: '$(appServicePlanName)-cosmos'
@@ -332,13 +344,14 @@ stages:
332344

333345
- stage: deployR5Sql
334346
displayName: 'Deploy R5 SQL Site'
347+
condition: eq(variables.buildCriticalOnly, false)
335348
dependsOn:
336349
- DockerBuild
337350
- setupEnvironment
338351
- deploySqlServer
339352
jobs:
340353
- template: ./jobs/provision-deploy.yml
341-
parameters:
354+
parameters:
342355
version: R5
343356
sql: true
344357
webAppName: $(DeploymentEnvironmentNameR5Sql)
@@ -385,6 +398,7 @@ stages:
385398

386399
- stage: testR4B
387400
displayName: 'Run R4B Tests'
401+
condition: eq(variables.buildCriticalOnly, false)
388402
dependsOn:
389403
- BuildArtifacts
390404
- setupEnvironment
@@ -400,6 +414,7 @@ stages:
400414

401415
- stage: testR5
402416
displayName: 'Run R5 Tests'
417+
condition: eq(variables.buildCriticalOnly, false)
403418
dependsOn:
404419
- BuildArtifacts
405420
- setupEnvironment
@@ -415,6 +430,15 @@ stages:
415430

416431
- stage: cleanup
417432
displayName: 'Cleanup Azure Environment'
433+
# Run if all tests succeed, or if critical-only mode and Stu3/R4 succeed (R4B/R5 skipped)
434+
condition: |
435+
and(
436+
or(succeeded(), failed()),
437+
or(
438+
and(eq(variables.buildCriticalOnly, false), in(dependencies.testR4B.result, 'Succeeded', 'Failed'), in(dependencies.testR5.result, 'Succeeded', 'Failed')),
439+
and(eq(variables.buildCriticalOnly, true), in(dependencies.testStu3.result, 'Succeeded', 'Failed'), in(dependencies.testR4.result, 'Succeeded', 'Failed'))
440+
)
441+
)
418442
dependsOn:
419443
- testStu3
420444
- testR4
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# ADR 2510: Critical-Only Build Flag for CI/PR Pipelines
2+
Labels: [CI/CD](https://github.com/microsoft/fhir-server/labels/Area-CI-CD)
3+
4+
## Context
5+
The FHIR server supports four FHIR specification versions: STU3, R4, R4B, and R5. In production environments, the majority of deployments use STU3 and R4, which are mature and widely adopted specifications. R4B and R5 are newer versions with limited production usage.
6+
7+
The current CI and PR pipelines build, deploy, and test all four versions for every commit. Each version requires:
8+
- Docker image builds (multi-platform for CI)
9+
- Deployment to test environments (CosmosDB + SQL variants)
10+
- Integration tests (CosmosDB + SQL)
11+
- End-to-end tests (CosmosDB + SQL)
12+
13+
This comprehensive validation is essential for ensuring quality across all supported versions. However, when shipping critical hotfixes or iterating rapidly on production issues affecting only R4 or STU3, the time spent deploying and testing R4B and R5 represents significant overhead. A typical full CI build takes substantial time, with R4B and R5 stages accounting for approximately 40% of deployment and test time.
14+
15+
We need a mechanism to accelerate builds when working exclusively on R4 and STU3 production issues, while maintaining the default behavior of comprehensive multi-version validation.
16+
17+
## Decision
18+
We will add a `buildCriticalOnly` parameter to both the CI and PR pipeline definitions. When set to `true`, this parameter will:
19+
20+
1. **Skip deployment and test stages** for R4B and R5 versions:
21+
- Deployment stages (CosmosDB + SQL)
22+
- Integration test jobs
23+
- End-to-end test jobs
24+
25+
2. **Skip Docker image builds** for R4B and R5 versions in the `docker-build-all.yml` job template
26+
27+
3. **Continue to build all code** in the solution, including R4B and R5 projects, during the build stages. This ensures that changes to shared code (e.g., Core libraries) do not introduce compilation errors in non-critical versions.
28+
29+
The parameter will default to `false`, ensuring that the standard behavior remains comprehensive validation across all versions. Developers and release engineers can opt into the fast path explicitly when appropriate.
30+
31+
### Implementation Approach
32+
- Add `buildCriticalOnly` parameter (type: boolean, default: false) to pipeline definitions
33+
- Use Azure Pipelines conditional syntax (`condition: eq(variables.buildCriticalOnly, false)`) on R4B and R5 stages
34+
- Update stage dependencies to handle conditionally skipped stages
35+
- Use template conditionals (`${{ if }}`) to skip R4B/R5 Docker builds
36+
37+
### Usage Guidelines
38+
**When to use `buildCriticalOnly: true`:**
39+
- Hotfixes for production R4 or STU3 issues
40+
- Rapid iteration during R4/STU3 feature development
41+
- Cost-sensitive CI runs when R4B/R5 validation is not required
42+
43+
**When NOT to use it:**
44+
- Before merging to main branch (full validation recommended)
45+
- When changes affect shared Core libraries (cross-version validation needed)
46+
- Release builds
47+
- When explicitly developing or fixing R4B/R5 functionality
48+
49+
## Status
50+
Accepted
51+
52+
## Consequences
53+
### Benefits:
54+
- **Reduced build time**: 20-30% time savings by skipping ~40% of deployment and test stages
55+
- **Faster hotfix delivery**: Critical R4/STU3 fixes can be validated and shipped more quickly
56+
- **Lower build costs**: Reduced Azure DevOps agent minutes and Azure resource usage for test environments
57+
- **Preserved safety**: Default behavior remains unchanged; full validation is opt-out, not opt-in
58+
59+
### Adverse Effects:
60+
- **Maintenance overhead**: New parameter must be propagated when adding future FHIR versions
61+
- **Risk of misuse**: Developers might use the flag inappropriately, skipping validation when it's needed
62+
- **Incomplete time savings**: All code still compiles, so savings are less than a full solution filter approach would provide
63+
64+
### Neutral Effects:
65+
- **No impact on default behavior**: Existing builds and processes remain unchanged
66+
67+
## References
68+
- CI Pipeline: `build/ci-pipeline.yml`
69+
- PR Pipeline: `build/pr-pipeline.yml`
70+
- Docker Build Template: `build/jobs/docker-build-all.yml`

0 commit comments

Comments
 (0)