Skip to content

Commit dd64202

Browse files
committed
ci: add pinned-packages drift detection after docker builds
After each Docker image build, extract installed packages with dpkg -l and diff against the committed pinned-packages.txt files. Fails CI if Dockerfile changes cause package drift without regenerating the pinned lists. This catches the scenario where someone modifies a Dockerfile (e.g., adds a new apt package or updates the base image) but forgets to run build-image.sh to regenerate pinned-packages.txt.
1 parent 74a1b18 commit dd64202

2 files changed

Lines changed: 135 additions & 13 deletions

File tree

.github/workflows/docker-build-check.yml

Lines changed: 97 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ jobs:
4343
fi
4444
echo "All shared build scripts are in sync."
4545
46-
kms:
46+
gateway:
4747
runs-on: ubuntu-latest
4848
needs: check-shared-scripts
4949
steps:
@@ -52,24 +52,40 @@ jobs:
5252
- name: Set up Docker Buildx
5353
uses: docker/setup-buildx-action@v3
5454

55-
- name: Build KMS Docker image
55+
- name: Build Gateway Docker image
5656
uses: docker/build-push-action@v5
5757
with:
58-
context: kms/dstack-app/builder
58+
context: gateway/dstack-app/builder
5959
push: false
60-
platforms: linux/amd64
60+
load: true
61+
tags: dstack-gateway-check:latest
6162
provenance: false
6263
build-args: |
6364
DSTACK_REV=${{ github.event.pull_request.head.sha || github.sha }}
6465
DSTACK_SRC_URL=${{ github.server_url }}/${{ github.repository }}
6566
66-
- name: Build KMS contracts
67+
- name: Verify pinned packages
6768
run: |
68-
cd kms/auth-eth
69-
npm ci
70-
npx hardhat compile
69+
build/shared/verify-pinned-packages.sh dstack-gateway-check:latest \
70+
gateway/dstack-app/builder/shared/pinned-packages.txt
7171
72-
gateway:
72+
- name: Build gateway-builder target
73+
run: |
74+
docker buildx build \
75+
--load \
76+
--target gateway-builder \
77+
--tag gateway-builder-check:latest \
78+
--provenance=false \
79+
--build-arg "DSTACK_REV=${{ github.event.pull_request.head.sha || github.sha }}" \
80+
--build-arg "DSTACK_SRC_URL=${{ github.server_url }}/${{ github.repository }}" \
81+
gateway/dstack-app/builder
82+
83+
- name: Verify builder pinned packages
84+
run: |
85+
build/shared/verify-pinned-packages.sh gateway-builder-check:latest \
86+
gateway/dstack-app/builder/shared/builder-pinned-packages.txt
87+
88+
kms:
7389
runs-on: ubuntu-latest
7490
needs: check-shared-scripts
7591
steps:
@@ -78,17 +94,45 @@ jobs:
7894
- name: Set up Docker Buildx
7995
uses: docker/setup-buildx-action@v3
8096

81-
- name: Build Gateway Docker image
97+
- name: Build KMS Docker image
8298
uses: docker/build-push-action@v5
8399
with:
84-
context: gateway/dstack-app/builder
100+
context: kms/dstack-app/builder
85101
push: false
86-
platforms: linux/amd64
102+
load: true
103+
tags: dstack-kms-check:latest
87104
provenance: false
88105
build-args: |
89106
DSTACK_REV=${{ github.event.pull_request.head.sha || github.sha }}
90107
DSTACK_SRC_URL=${{ github.server_url }}/${{ github.repository }}
91108
109+
- name: Verify pinned packages (qemu stage)
110+
run: |
111+
build/shared/verify-pinned-packages.sh dstack-kms-check:latest \
112+
kms/dstack-app/builder/shared/qemu-pinned-packages.txt
113+
114+
- name: Build kms-builder target
115+
run: |
116+
docker buildx build \
117+
--load \
118+
--target kms-builder \
119+
--tag kms-builder-check:latest \
120+
--provenance=false \
121+
--build-arg "DSTACK_REV=${{ github.event.pull_request.head.sha || github.sha }}" \
122+
--build-arg "DSTACK_SRC_URL=${{ github.server_url }}/${{ github.repository }}" \
123+
kms/dstack-app/builder
124+
125+
- name: Verify builder pinned packages
126+
run: |
127+
build/shared/verify-pinned-packages.sh kms-builder-check:latest \
128+
kms/dstack-app/builder/shared/builder-pinned-packages.txt
129+
130+
- name: Build KMS contracts
131+
run: |
132+
cd kms/auth-eth
133+
npm ci
134+
npx hardhat compile
135+
92136
verifier:
93137
runs-on: ubuntu-latest
94138
needs: check-shared-scripts
@@ -104,8 +148,48 @@ jobs:
104148
context: verifier
105149
file: verifier/builder/Dockerfile
106150
push: false
107-
platforms: linux/amd64
151+
load: true
152+
tags: dstack-verifier-check:latest
108153
provenance: false
109154
build-args: |
110155
DSTACK_REV=${{ github.event.pull_request.head.sha || github.sha }}
111156
DSTACK_SRC_URL=${{ github.server_url }}/${{ github.repository }}
157+
158+
- name: Verify pinned packages (runtime)
159+
run: |
160+
build/shared/verify-pinned-packages.sh dstack-verifier-check:latest \
161+
verifier/builder/shared/pinned-packages.txt
162+
163+
- name: Build verifier-builder target
164+
run: |
165+
docker buildx build \
166+
--load \
167+
--target verifier-builder \
168+
--tag verifier-builder-check:latest \
169+
--provenance=false \
170+
--file verifier/builder/Dockerfile \
171+
--build-arg "DSTACK_REV=${{ github.event.pull_request.head.sha || github.sha }}" \
172+
--build-arg "DSTACK_SRC_URL=${{ github.server_url }}/${{ github.repository }}" \
173+
verifier
174+
175+
- name: Verify builder pinned packages
176+
run: |
177+
build/shared/verify-pinned-packages.sh verifier-builder-check:latest \
178+
verifier/builder/shared/builder-pinned-packages.txt
179+
180+
- name: Build acpi-builder target
181+
run: |
182+
docker buildx build \
183+
--load \
184+
--target acpi-builder \
185+
--tag verifier-acpi-check:latest \
186+
--provenance=false \
187+
--file verifier/builder/Dockerfile \
188+
--build-arg "DSTACK_REV=${{ github.event.pull_request.head.sha || github.sha }}" \
189+
--build-arg "DSTACK_SRC_URL=${{ github.server_url }}/${{ github.repository }}" \
190+
verifier
191+
192+
- name: Verify qemu pinned packages
193+
run: |
194+
build/shared/verify-pinned-packages.sh verifier-acpi-check:latest \
195+
verifier/builder/shared/qemu-pinned-packages.txt
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/bin/bash
2+
3+
# SPDX-FileCopyrightText: © 2025 Phala Network <dstack@phala.network>
4+
#
5+
# SPDX-License-Identifier: Apache-2.0
6+
7+
# Verify that installed packages in a Docker image match the committed
8+
# pinned-packages file. Detects when Dockerfile changes cause package
9+
# drift without regenerating the pinned-packages list.
10+
#
11+
# Usage: verify-pinned-packages.sh <image> <pinned-packages-file>
12+
13+
set -euo pipefail
14+
15+
IMAGE=$1
16+
PKG_FILE=$2
17+
18+
if [ -z "$IMAGE" ] || [ -z "$PKG_FILE" ]; then
19+
echo "Usage: $0 <image> <pinned-packages-file>" >&2
20+
exit 1
21+
fi
22+
23+
ACTUAL=$(docker run --rm --entrypoint bash "$IMAGE" \
24+
-c "dpkg -l | grep '^ii' | awk '{print \$2\"=\"\$3}' | sort")
25+
26+
EXPECTED=$(sort "$PKG_FILE")
27+
28+
if [ "$ACTUAL" = "$EXPECTED" ]; then
29+
echo "OK: packages in $IMAGE match $PKG_FILE"
30+
exit 0
31+
fi
32+
33+
echo "ERROR: packages in $IMAGE differ from $PKG_FILE" >&2
34+
echo "" >&2
35+
diff --unified <(echo "$EXPECTED") <(echo "$ACTUAL") >&2 || true
36+
echo "" >&2
37+
echo "Regenerate pinned packages by running the service's build-image.sh" >&2
38+
exit 1

0 commit comments

Comments
 (0)