Skip to content

Commit a966cdd

Browse files
committed
fix(ci): deterministic docker build cancellation
1 parent fa77399 commit a966cdd

File tree

2 files changed

+185
-86
lines changed

2 files changed

+185
-86
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: is-latest-commit
2+
3+
on:
4+
workflow_call:
5+
outputs:
6+
is_latest:
7+
description: "Whether the current commit is the latest on the target branch"
8+
value: ${{ jobs.check.outputs.is_latest }}
9+
10+
permissions: {}
11+
12+
jobs:
13+
check:
14+
runs-on: ubuntu-latest
15+
outputs:
16+
is_latest: ${{ steps.check.outputs.is_latest }}
17+
steps:
18+
- name: Check if current commit is latest on target branch
19+
id: check
20+
env:
21+
CURRENT_COMMIT: ${{ github.sha }}
22+
run: |
23+
LATEST_COMMIT=$(git ls-remote https://github.com/${{ github.repository }}.git refs/heads/${{ github.ref_name }} | cut -f1)
24+
if [ "$LATEST_COMMIT" == "$CURRENT_COMMIT" ]; then
25+
echo "is_latest=true" >> $GITHUB_OUTPUT
26+
echo "Current commit $CURRENT_COMMIT is the latest on ${{ github.ref_name }}"
27+
else
28+
echo "is_latest=false" >> $GITHUB_OUTPUT
29+
echo "Current commit $CURRENT_COMMIT is not the latest on ${{ github.ref_name }} (latest: $LATEST_COMMIT)."
30+
fi

.github/workflows/kms-connector-docker-build.yml

Lines changed: 155 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@ name: kms-connector-docker-build
22

33
on:
44
workflow_call:
5+
inputs:
6+
is_workflow_call:
7+
description: "Indicates if the workflow is called from another workflow"
8+
type: boolean
9+
default: true
10+
required: false
511
secrets:
612
AWS_ACCESS_KEY_S3_USER:
713
required: true
@@ -55,16 +61,17 @@ on:
5561

5662
permissions: {}
5763

58-
concurrency:
59-
group: kms-connector-build-${{ github.ref_name }}
60-
cancel-in-progress: true
61-
6264
jobs:
6365
########################################################################
64-
# DB MIGRATION #
66+
# PRE-BUILD CHECKS #
6567
########################################################################
68+
is-latest-commit:
69+
uses: ./.github/workflows/is-latest-commit.yml
70+
if: github.event_name == 'push'
71+
6672
check-changes-db-migration:
6773
uses: ./.github/workflows/check-changes-for-docker-build.yml
74+
if: github.event_name == 'push' || inputs.is_workflow_call
6875
secrets: &check_changes_secrets
6976
GHCR_READ_TOKEN: ${{ secrets.GHCR_READ_TOKEN }}
7077
permissions: &check_changes_permissions
@@ -80,12 +87,127 @@ jobs:
8087
- .github/workflows/kms-connector-docker-build.yml
8188
- kms-connector/connector-db/**
8289
90+
check-changes-gw-listener:
91+
uses: ./.github/workflows/check-changes-for-docker-build.yml
92+
if: github.event_name == 'push' || inputs.is_workflow_call
93+
secrets: *check_changes_secrets
94+
permissions: *check_changes_permissions
95+
with:
96+
caller-workflow-event-name: ${{ github.event_name }}
97+
caller-workflow-event-before: ${{ github.event.before }}
98+
docker-image: fhevm/kms-connector/gw-listener
99+
filters: |
100+
gw-listener:
101+
- .github/workflows/kms-connector-docker-build.yml
102+
- kms-connector/crates/gw-listener/**
103+
- kms-connector/crates/utils/**
104+
- kms-connector/Cargo.*
105+
- gateway-contracts/rust-bindings/**
106+
107+
check-changes-kms-worker:
108+
uses: ./.github/workflows/check-changes-for-docker-build.yml
109+
if: github.event_name == 'push' || inputs.is_workflow_call
110+
secrets: *check_changes_secrets
111+
permissions: *check_changes_permissions
112+
with:
113+
caller-workflow-event-name: ${{ github.event_name }}
114+
caller-workflow-event-before: ${{ github.event.before }}
115+
docker-image: fhevm/kms-connector/kms-worker
116+
filters: |
117+
kms-worker:
118+
- .github/workflows/kms-connector-docker-build.yml
119+
- kms-connector/crates/kms-worker/**
120+
- kms-connector/crates/utils/**
121+
- kms-connector/Cargo.*
122+
- gateway-contracts/rust-bindings/**
123+
- host-contracts/rust-bindings/**
124+
125+
check-changes-tx-sender:
126+
uses: ./.github/workflows/check-changes-for-docker-build.yml
127+
if: github.event_name == 'push' || inputs.is_workflow_call
128+
secrets: *check_changes_secrets
129+
permissions: *check_changes_permissions
130+
with:
131+
caller-workflow-event-name: ${{ github.event_name }}
132+
caller-workflow-event-before: ${{ github.event.before }}
133+
docker-image: fhevm/kms-connector/tx-sender
134+
filters: |
135+
tx-sender:
136+
- .github/workflows/kms-connector-docker-build.yml
137+
- kms-connector/crates/tx-sender/**
138+
- kms-connector/crates/utils/**
139+
- kms-connector/Cargo.*
140+
- gateway-contracts/rust-bindings/**
141+
142+
########################################################################
143+
# BUILD DECISIONS #
144+
# Centralizes all build/re-tag logic in one place for maintainability #
145+
########################################################################
146+
build-decisions:
147+
runs-on: ubuntu-latest
148+
if: always()
149+
needs:
150+
- is-latest-commit
151+
- check-changes-db-migration
152+
- check-changes-gw-listener
153+
- check-changes-kms-worker
154+
- check-changes-tx-sender
155+
outputs:
156+
db_migration: ${{ steps.decide.outputs.db_migration }}
157+
gw_listener: ${{ steps.decide.outputs.gw_listener }}
158+
kms_worker: ${{ steps.decide.outputs.kms_worker }}
159+
tx_sender: ${{ steps.decide.outputs.tx_sender }}
160+
steps:
161+
- id: decide
162+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v0.8.0
163+
env:
164+
EVENT_NAME: ${{ github.event_name }}
165+
NEEDS: ${{ toJSON(needs) }}
166+
INPUTS: ${{ toJSON(inputs) }}
167+
with:
168+
script: |
169+
// Decision logic (returns: "build", "retag", or "skip"):
170+
// - release: always build
171+
// - push: only act if latest commit; build if changes, retag otherwise
172+
// - workflow_call: build if changes detected, otherwise skip
173+
// - workflow_dispatch: build if input is true, otherwise skip
174+
const event = process.env.EVENT_NAME;
175+
const needs = JSON.parse(process.env.NEEDS);
176+
const inputs = JSON.parse(process.env.INPUTS);
177+
const isLatestCommit = needs['is-latest-commit'].outputs?.is_latest === 'true' || false;
178+
const isWorkflowCall = inputs.is_workflow_call ?? false;
179+
180+
const decideAction = (changes, manualInput) => {
181+
if (event === 'release') return 'build';
182+
if (event === 'push') return isLatestCommit ? (changes ? 'build' : 'retag') : 'skip';
183+
if (isWorkflowCall) return changes ? 'build' : 'skip';
184+
if (!isWorkflowCall && event === 'workflow_dispatch') return manualInput ? 'build' : 'skip';
185+
return 'skip';
186+
};
187+
188+
const services = {
189+
db_migration: { changes: needs['check-changes-db-migration'].outputs?.changes, build_input: inputs.build_db_migration },
190+
gw_listener: { changes: needs['check-changes-gw-listener'].outputs?.changes, build_input: inputs.build_gw_listener },
191+
kms_worker: { changes: needs['check-changes-kms-worker'].outputs?.changes, build_input: inputs.build_kms_worker },
192+
tx_sender: { changes: needs['check-changes-tx-sender'].outputs?.changes, build_input: inputs.build_tx_sender },
193+
};
194+
195+
core.info(`Event: ${event}, Is latest commit: ${isLatestCommit}, Is workflow call: ${isWorkflowCall}`);
196+
for (const [name, { changes, build_input }] of Object.entries(services)) {
197+
const action = decideAction(changes === 'true', build_input ?? false);
198+
core.setOutput(name, action);
199+
core.info(`${name}: ${action} (changes: ${changes}, build_input: ${build_input})`);
200+
}
201+
202+
########################################################################
203+
# DB MIGRATION #
204+
########################################################################
83205
build-db-migration:
84-
needs: check-changes-db-migration
85-
if: |
86-
github.event_name == 'release'
87-
|| (github.event_name != 'workflow_dispatch' && needs.check-changes-db-migration.outputs.changes == 'true')
88-
|| (github.event_name == 'workflow_dispatch' && inputs.build_db_migration)
206+
needs: [build-decisions, check-changes-db-migration]
207+
concurrency:
208+
group: kms-connector-build-db-migration-${{ github.ref_name }}
209+
cancel-in-progress: true
210+
if: always() && needs.build-decisions.outputs.db_migration == 'build'
89211
uses: zama-ai/ci-templates/.github/workflows/common-docker.yml@3cf4c2b133947d29e7a313555638621f9ca0345c # v1.0.3
90212
secrets: &docker_secrets
91213
AWS_ACCESS_KEY_S3_USER: ${{ secrets.AWS_ACCESS_KEY_S3_USER }}
@@ -109,9 +231,8 @@ jobs:
109231
rust-toolchain-file-path: kms-connector/rust-toolchain.toml
110232

111233
re-tag-db-migration-image:
112-
needs: check-changes-db-migration
113-
if: |
114-
needs.check-changes-db-migration.outputs.changes != 'true' && github.event_name == 'push'
234+
needs: [build-decisions, check-changes-db-migration]
235+
if: always() && needs.build-decisions.outputs.db_migration == 'retag'
115236
permissions: &re-tag-image-permissions
116237
actions: 'read' # Required to read workflow run information
117238
contents: 'read' # Required to checkout repository code
@@ -126,28 +247,12 @@ jobs:
126247
########################################################################
127248
# GATEWAY LISTENER #
128249
########################################################################
129-
check-changes-gw-listener:
130-
uses: ./.github/workflows/check-changes-for-docker-build.yml
131-
secrets: *check_changes_secrets
132-
permissions: *check_changes_permissions
133-
with:
134-
caller-workflow-event-name: ${{ github.event_name }}
135-
caller-workflow-event-before: ${{ github.event.before }}
136-
docker-image: fhevm/kms-connector/gw-listener
137-
filters: |
138-
gw-listener:
139-
- .github/workflows/kms-connector-docker-build.yml
140-
- kms-connector/crates/gw-listener/**
141-
- kms-connector/crates/utils/**
142-
- kms-connector/Cargo.*
143-
- gateway-contracts/rust-bindings/**
144-
145250
build-gw-listener:
146-
needs: check-changes-gw-listener
147-
if: |
148-
github.event_name == 'release'
149-
|| (github.event_name != 'workflow_dispatch' && needs.check-changes-gw-listener.outputs.changes == 'true')
150-
|| (github.event_name == 'workflow_dispatch' && inputs.build_gw_listener)
251+
needs: [build-decisions, check-changes-gw-listener]
252+
concurrency:
253+
group: kms-connector-build-gw-listener-${{ github.ref_name }}
254+
cancel-in-progress: true
255+
if: always() && needs.build-decisions.outputs.gw_listener == 'build'
151256
uses: zama-ai/ci-templates/.github/workflows/common-docker.yml@3cf4c2b133947d29e7a313555638621f9ca0345c # v1.0.3
152257
permissions: *docker_permissions
153258
secrets: *docker_secrets
@@ -160,9 +265,8 @@ jobs:
160265
rust-toolchain-file-path: kms-connector/rust-toolchain.toml
161266

162267
re-tag-gw-listener-image:
163-
needs: check-changes-gw-listener
164-
if: |
165-
needs.check-changes-gw-listener.outputs.changes != 'true' && github.event_name == 'push'
268+
needs: [build-decisions, check-changes-gw-listener]
269+
if: always() && needs.build-decisions.outputs.gw_listener == 'retag'
166270
permissions: *re-tag-image-permissions
167271
uses: ./.github/workflows/re-tag-docker-image.yml
168272
with:
@@ -173,29 +277,12 @@ jobs:
173277
########################################################################
174278
# KMS WORKER #
175279
########################################################################
176-
check-changes-kms-worker:
177-
uses: ./.github/workflows/check-changes-for-docker-build.yml
178-
secrets: *check_changes_secrets
179-
permissions: *check_changes_permissions
180-
with:
181-
caller-workflow-event-name: ${{ github.event_name }}
182-
caller-workflow-event-before: ${{ github.event.before }}
183-
docker-image: fhevm/kms-connector/kms-worker
184-
filters: |
185-
kms-worker:
186-
- .github/workflows/kms-connector-docker-build.yml
187-
- kms-connector/crates/kms-worker/**
188-
- kms-connector/crates/utils/**
189-
- kms-connector/Cargo.*
190-
- gateway-contracts/rust-bindings/**
191-
- host-contracts/rust-bindings/**
192-
193280
build-kms-worker:
194-
needs: check-changes-kms-worker
195-
if: |
196-
github.event_name == 'release'
197-
|| (github.event_name != 'workflow_dispatch' && needs.check-changes-kms-worker.outputs.changes == 'true')
198-
|| (github.event_name == 'workflow_dispatch' && inputs.build_kms_worker)
281+
needs: [build-decisions, check-changes-kms-worker]
282+
concurrency:
283+
group: kms-connector-build-kms-worker-${{ github.ref_name }}
284+
cancel-in-progress: true
285+
if: always() && needs.build-decisions.outputs.kms_worker == 'build'
199286
uses: zama-ai/ci-templates/.github/workflows/common-docker.yml@3cf4c2b133947d29e7a313555638621f9ca0345c # v1.0.3
200287
permissions: *docker_permissions
201288
secrets: *docker_secrets
@@ -208,9 +295,8 @@ jobs:
208295
rust-toolchain-file-path: kms-connector/rust-toolchain.toml
209296

210297
re-tag-kms-worker-image:
211-
needs: check-changes-kms-worker
212-
if: |
213-
needs.check-changes-kms-worker.outputs.changes != 'true' && github.event_name == 'push'
298+
needs: [build-decisions, check-changes-kms-worker]
299+
if: always() && needs.build-decisions.outputs.kms_worker == 'retag'
214300
permissions: *re-tag-image-permissions
215301
uses: ./.github/workflows/re-tag-docker-image.yml
216302
with:
@@ -221,28 +307,12 @@ jobs:
221307
########################################################################
222308
# TRANSACTION SENDER #
223309
########################################################################
224-
check-changes-tx-sender:
225-
uses: ./.github/workflows/check-changes-for-docker-build.yml
226-
secrets: *check_changes_secrets
227-
permissions: *check_changes_permissions
228-
with:
229-
caller-workflow-event-name: ${{ github.event_name }}
230-
caller-workflow-event-before: ${{ github.event.before }}
231-
docker-image: fhevm/kms-connector/tx-sender
232-
filters: |
233-
tx-sender:
234-
- .github/workflows/kms-connector-docker-build.yml
235-
- kms-connector/crates/tx-sender/**
236-
- kms-connector/crates/utils/**
237-
- kms-connector/Cargo.*
238-
- gateway-contracts/rust-bindings/**
239-
240310
build-tx-sender:
241-
needs: check-changes-tx-sender
242-
if: |
243-
github.event_name == 'release'
244-
|| (github.event_name != 'workflow_dispatch' && needs.check-changes-tx-sender.outputs.changes == 'true')
245-
|| (github.event_name == 'workflow_dispatch' && inputs.build_tx_sender)
311+
needs: [build-decisions, check-changes-tx-sender]
312+
concurrency:
313+
group: kms-connector-build-tx-sender-${{ github.ref_name }}
314+
cancel-in-progress: true
315+
if: always() && needs.build-decisions.outputs.tx_sender == 'build'
246316
uses: zama-ai/ci-templates/.github/workflows/common-docker.yml@3cf4c2b133947d29e7a313555638621f9ca0345c # v1.0.3
247317
permissions: *docker_permissions
248318
secrets: *docker_secrets
@@ -255,9 +325,8 @@ jobs:
255325
rust-toolchain-file-path: kms-connector/rust-toolchain.toml
256326

257327
re-tag-tx-sender-image:
258-
needs: check-changes-tx-sender
259-
if: |
260-
needs.check-changes-tx-sender.outputs.changes != 'true' && github.event_name == 'push'
328+
needs: [build-decisions, check-changes-tx-sender]
329+
if: always() && needs.build-decisions.outputs.tx_sender == 'retag'
261330
permissions: *re-tag-image-permissions
262331
uses: ./.github/workflows/re-tag-docker-image.yml
263332
with:

0 commit comments

Comments
 (0)