Skip to content

Commit e237998

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

File tree

2 files changed

+184
-86
lines changed

2 files changed

+184
-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: 154 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,126 @@ 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+
with:
167+
script: |
168+
// Decision logic (returns: "build", "retag", or "skip"):
169+
// - release: always build
170+
// - workflow_dispatch: build if input is true, otherwise skip
171+
// - workflow_call: build if changes detected, retag if no changes
172+
// - push: only act if latest commit; build if changes, retag otherwise
173+
const event = process.env.EVENT_NAME;
174+
const needs = JSON.parse(process.env.NEEDS);
175+
const isLatestCommit = needs.is-latest-commit.outputs.is_latest === 'true';
176+
const isWorkflowCall = core.getBooleanInput('is_workflow_call');
177+
178+
const decideAction = (changes, manualInput) => {
179+
if (event === 'release') return 'build';
180+
if (event === 'workflow_dispatch') return manualInput ? 'build' : 'skip';
181+
if (event === 'push') return isLatestCommit ? (changes ? 'build' : 'retag') : 'skip';
182+
if (isWorkflowCall) return changes ? 'build' : 'retag';
183+
return 'skip';
184+
};
185+
186+
const services = {
187+
db_migration: { changes: needs.check-changes-db-migration.outputs.changes, input_name: 'build_db_migration' },
188+
gw_listener: { changes: needs.check-changes-gw-listener.outputs.changes, input_name: 'build_gw_listener' },
189+
kms_worker: { changes: needs.check-changes-kms-worker.outputs.changes, input_name: 'build_kms_worker' },
190+
tx_sender: { changes: needs.check-changes-tx-sender.outputs.changes, input_name: 'build_tx_sender' },
191+
};
192+
193+
core.info(`Event: ${event}, Is latest commit: ${isLatestCommit}, Is workflow call: ${isWorkflowCall}`);
194+
for (const [name, { changes, input_name }] of Object.entries(services)) {
195+
let manualInput = core.getBooleanInput(input_name);
196+
const action = decideAction(changes === 'true', manualInput);
197+
core.setOutput(name, action);
198+
core.info(`${name}: ${action} (changes: ${changes})`);
199+
}
200+
201+
########################################################################
202+
# DB MIGRATION #
203+
########################################################################
83204
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)
205+
needs: [build-decisions, check-changes-db-migration]
206+
concurrency:
207+
group: kms-connector-build-db-migration-${{ github.ref_name }}
208+
cancel-in-progress: true
209+
if: always() && needs.build-decisions.outputs.db_migration == 'build'
89210
uses: zama-ai/ci-templates/.github/workflows/common-docker.yml@3cf4c2b133947d29e7a313555638621f9ca0345c # v1.0.3
90211
secrets: &docker_secrets
91212
AWS_ACCESS_KEY_S3_USER: ${{ secrets.AWS_ACCESS_KEY_S3_USER }}
@@ -109,9 +230,8 @@ jobs:
109230
rust-toolchain-file-path: kms-connector/rust-toolchain.toml
110231

111232
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'
233+
needs: [build-decisions, check-changes-db-migration]
234+
if: always() && needs.build-decisions.outputs.db_migration == 'retag'
115235
permissions: &re-tag-image-permissions
116236
actions: 'read' # Required to read workflow run information
117237
contents: 'read' # Required to checkout repository code
@@ -126,28 +246,12 @@ jobs:
126246
########################################################################
127247
# GATEWAY LISTENER #
128248
########################################################################
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-
145249
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)
250+
needs: [build-decisions, check-changes-gw-listener]
251+
concurrency:
252+
group: kms-connector-build-gw-listener-${{ github.ref_name }}
253+
cancel-in-progress: true
254+
if: always() && needs.build-decisions.outputs.gw_listener == 'build'
151255
uses: zama-ai/ci-templates/.github/workflows/common-docker.yml@3cf4c2b133947d29e7a313555638621f9ca0345c # v1.0.3
152256
permissions: *docker_permissions
153257
secrets: *docker_secrets
@@ -160,9 +264,8 @@ jobs:
160264
rust-toolchain-file-path: kms-connector/rust-toolchain.toml
161265

162266
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'
267+
needs: [build-decisions, check-changes-gw-listener]
268+
if: always() && needs.build-decisions.outputs.gw_listener == 'retag'
166269
permissions: *re-tag-image-permissions
167270
uses: ./.github/workflows/re-tag-docker-image.yml
168271
with:
@@ -173,29 +276,12 @@ jobs:
173276
########################################################################
174277
# KMS WORKER #
175278
########################################################################
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-
193279
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)
280+
needs: [build-decisions, check-changes-kms-worker]
281+
concurrency:
282+
group: kms-connector-build-kms-worker-${{ github.ref_name }}
283+
cancel-in-progress: true
284+
if: always() && needs.build-decisions.outputs.kms_worker == 'build'
199285
uses: zama-ai/ci-templates/.github/workflows/common-docker.yml@3cf4c2b133947d29e7a313555638621f9ca0345c # v1.0.3
200286
permissions: *docker_permissions
201287
secrets: *docker_secrets
@@ -208,9 +294,8 @@ jobs:
208294
rust-toolchain-file-path: kms-connector/rust-toolchain.toml
209295

210296
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'
297+
needs: [build-decisions, check-changes-kms-worker]
298+
if: always() && needs.build-decisions.outputs.kms_worker == 'retag'
214299
permissions: *re-tag-image-permissions
215300
uses: ./.github/workflows/re-tag-docker-image.yml
216301
with:
@@ -221,28 +306,12 @@ jobs:
221306
########################################################################
222307
# TRANSACTION SENDER #
223308
########################################################################
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-
240309
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)
310+
needs: [build-decisions, check-changes-tx-sender]
311+
concurrency:
312+
group: kms-connector-build-tx-sender-${{ github.ref_name }}
313+
cancel-in-progress: true
314+
if: always() && needs.build-decisions.outputs.tx_sender == 'build'
246315
uses: zama-ai/ci-templates/.github/workflows/common-docker.yml@3cf4c2b133947d29e7a313555638621f9ca0345c # v1.0.3
247316
permissions: *docker_permissions
248317
secrets: *docker_secrets
@@ -255,9 +324,8 @@ jobs:
255324
rust-toolchain-file-path: kms-connector/rust-toolchain.toml
256325

257326
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'
327+
needs: [build-decisions, check-changes-tx-sender]
328+
if: always() && needs.build-decisions.outputs.tx_sender == 'retag'
261329
permissions: *re-tag-image-permissions
262330
uses: ./.github/workflows/re-tag-docker-image.yml
263331
with:

0 commit comments

Comments
 (0)