fix(ci): deploy only apps whose build actually succeeded
ci / tc_operator (push) Successful in 22s
ci / tc_website (push) Successful in 19s
ci / build_booking (push) Successful in 41s
ci / deploy (push) Successful in 8s
ci / build_operator (push) Successful in 37s
ci / build_platform_api (push) Successful in 36s
ci / tc_portal (push) Failing after 26s
ci / build_portal (push) Has been skipped
ci / changes (push) Successful in 4s
ci / tc_booking (push) Successful in 22s
ci / tc_platform_api (push) Successful in 22s
ci / test_platform_api (push) Successful in 32s

When an app's typecheck failed, its build job was SKIPPED — which the
deploy condition tolerates (so other apps still ship) — but the deploy
script keyed on the change flags alone and pinned the never-built image
tag, ImagePullBackOff'ing the app (happened to portal on f6bac10).
Deployable now means changed AND build result == success; otherwise the
app keeps its live image, including in the manifest-apply path.
This commit is contained in:
Ronni Baslund
2026-06-11 07:45:08 +02:00
parent acf0d082e4
commit a5d82903af
+17 -2
View File
@@ -239,6 +239,13 @@ jobs:
- name: Deploy to k3s - name: Deploy to k3s
env: env:
KUBECONFIG_B64: ${{ secrets.KUBECONFIG_B64 }} KUBECONFIG_B64: ${{ secrets.KUBECONFIG_B64 }}
# Build results, not just change flags: an app whose typecheck/test
# failed has result=skipped on its build — its image for this SHA
# does NOT exist, and pinning it would ImagePullBackOff the app.
BUILT_PORTAL: ${{ needs.build_portal.result }}
BUILT_BOOKING: ${{ needs.build_booking.result }}
BUILT_OPERATOR: ${{ needs.build_operator.result }}
BUILT_PLATFORM_API: ${{ needs.build_platform_api.result }}
run: | run: |
export KUBECONFIG=/tmp/kubeconfig export KUBECONFIG=/tmp/kubeconfig
echo "$KUBECONFIG_B64" | base64 -d > "$KUBECONFIG" echo "$KUBECONFIG_B64" | base64 -d > "$KUBECONFIG"
@@ -250,6 +257,14 @@ jobs:
[operator]=${{ needs.changes.outputs.operator }} [operator]=${{ needs.changes.outputs.operator }}
[platform-api]=${{ needs.changes.outputs.platform_api }} [platform-api]=${{ needs.changes.outputs.platform_api }}
) )
declare -A BUILT=(
[portal]=$BUILT_PORTAL
[booking]=$BUILT_BOOKING
[operator]=$BUILT_OPERATOR
[platform-api]=$BUILT_PLATFORM_API
)
# Deployable = changed AND its image was actually built this run.
deployable() { [ "${CHANGED[$1]}" = "true" ] && [ "${BUILT[$1]}" = "success" ]; }
ROLL="" ROLL=""
if [ "${{ needs.changes.outputs.infra }}" = "true" ]; then if [ "${{ needs.changes.outputs.infra }}" = "true" ]; then
# Manifest change: apply the whole kustomization, but pin every # Manifest change: apply the whole kustomization, but pin every
@@ -257,7 +272,7 @@ jobs:
# rebuilt) so the apply never resets anything to :latest. # rebuilt) so the apply never resets anything to :latest.
cd infrastructure/production/fleet/apps cd infrastructure/production/fleet/apps
for app in portal booking platform-api operator; do for app in portal booking platform-api operator; do
if [ "${CHANGED[$app]}" = "true" ]; then if deployable "$app"; then
IMG="$REG/$app:$SHA" IMG="$REG/$app:$SHA"
else else
IMG=$(kubectl -n dezky-apps get deploy "$app" -o jsonpath='{.spec.template.spec.containers[0].image}' 2>/dev/null || echo "$REG/$app:latest") IMG=$(kubectl -n dezky-apps get deploy "$app" -o jsonpath='{.spec.template.spec.containers[0].image}' 2>/dev/null || echo "$REG/$app:latest")
@@ -269,7 +284,7 @@ jobs:
else else
# App-only change: roll just the changed apps; nothing else moves. # App-only change: roll just the changed apps; nothing else moves.
for app in portal booking platform-api operator; do for app in portal booking platform-api operator; do
if [ "${CHANGED[$app]}" = "true" ]; then if deployable "$app"; then
kubectl -n dezky-apps set image "deploy/$app" "$app=$REG/$app:$SHA" kubectl -n dezky-apps set image "deploy/$app" "$app=$REG/$app:$SHA"
ROLL="$ROLL $app" ROLL="$ROLL $app"
fi fi