fix(ci): isolate deployment smoke client (#1)
quality-gate / quality (push) Successful in 2m29s
quality-gate / container (push) Failing after 2m23s

This commit is contained in:
KyuubiYoru
2026-07-17 01:53:50 +02:00
parent 769336e424
commit a77d4b801c
4 changed files with 61 additions and 36 deletions
+27 -16
View File
@@ -144,18 +144,19 @@ jobs:
set -euo pipefail
compose_file="deploy/compose/compose.yaml"
secret="deploy/compose/secrets/signing-key"
compose_network=""
cleanup() {
if [[ -n "$compose_network" ]]; then
docker network disconnect "$compose_network" "$HOSTNAME" >/dev/null 2>&1 || true
fi
RENDEZVOUS_UID=1654 RENDEZVOUS_GID=1654 \
docker compose -f "$compose_file" down --volumes >/dev/null 2>&1 || true
rm -f "$secret"
}
trap cleanup EXIT
umask 077
install -d -m 0700 deploy/compose/secrets
openssl rand -out "$secret" 32
chmod 0600 "$secret"
publisher_credential="$(RENDEZVOUS_SMOKE_LOCAL_KEY="$secret" \
./scripts/mint-local-publisher-credential.sh)"
export RENDEZVOUS_PUBLISHER_CREDENTIAL="$publisher_credential"
chmod 0444 "$secret"
export RENDEZVOUS_UID=1654
export RENDEZVOUS_GID=1654
@@ -168,6 +169,10 @@ jobs:
export RENDEZVOUS_CONFIG_SOURCE="$runner_workspace_source/deploy/compose/appsettings.Production.json"
export RENDEZVOUS_SECRET_SOURCE="$runner_workspace_source/deploy/compose/secrets/signing-key"
export SOURCE_REVISION_ID="$GITHUB_SHA"
smoke_client_image="rendezvous-smoke-client:${GITHUB_SHA}"
docker build --file eng/release-builder.Dockerfile \
--target release-builder \
--tag "$smoke_client_image" .
docker compose -f "$compose_file" build \
--build-arg SOURCE_REVISION_ID="$SOURCE_REVISION_ID"
docker compose -f "$compose_file" up --no-build --detach
@@ -175,27 +180,33 @@ jobs:
test -n "$container_id"
compose_network="$(docker inspect "$container_id" | jq -er \
'.[0].NetworkSettings.Networks | keys[0]')"
docker network connect "$compose_network" "$HOSTNAME"
service_ip="$(docker inspect "$container_id" | jq -er \
--arg network "$compose_network" \
'.[0].NetworkSettings.Networks[$network].IPAddress')"
export RENDEZVOUS_SMOKE_HTTP_URL="http://${service_ip}:8080/"
export RENDEZVOUS_SMOKE_UDP_ENDPOINT="${service_ip}:9050"
test "$(docker inspect --format '{{.Config.User}}' "$container_id")" = "1654:1654"
test "$(docker inspect --format '{{.HostConfig.ReadonlyRootfs}}' "$container_id")" = "true"
test "$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/app/appsettings.Production.json"}}{{.RW}}{{end}}{{end}}' "$container_id")" = "false"
test "$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/run/secrets/rendezvous-signing-key"}}{{.RW}}{{end}}{{end}}' "$container_id")" = "false"
for attempt in {1..100}; do
if curl --fail --silent "${RENDEZVOUS_SMOKE_HTTP_URL%/}/health/ready" >/dev/null 2>&1; then
break
fi
if (( attempt == 100 )); then
docker run --rm \
--network "$compose_network" \
--user "$(id -u):$(id -g)" \
--env HOME=/tmp \
--env RENDEZVOUS_SMOKE_HTTP_URL="http://${service_ip}:8080/" \
--env RENDEZVOUS_SMOKE_UDP_ENDPOINT="${service_ip}:9050" \
--env RENDEZVOUS_PUBLISHER_CREDENTIAL \
--volume "$runner_workspace_source:/source:ro" \
--workdir /source \
"$smoke_client_image" \
bash -lc '
for attempt in {1..300}; do
curl --fail --silent "${RENDEZVOUS_SMOKE_HTTP_URL%/}/health/ready" >/dev/null 2>&1 && exec ./scripts/smoke-deployment.sh
sleep 0.1
done
exit 1
' || {
docker compose -f "$compose_file" logs rendezvous
exit 1
fi
sleep 0.1
done
./scripts/smoke-deployment.sh
}
docker compose -f "$compose_file" stop --timeout 40 rendezvous
test "$(docker inspect --format '{{.State.Running}}' "$container_id")" = "false"
test "$(docker inspect --format '{{.State.ExitCode}}' "$container_id")" = "0"
+23 -14
View File
@@ -112,18 +112,19 @@ jobs:
run: |
set -euo pipefail
secret="deploy/compose/secrets/signing-key"
compose_network=""
cleanup() {
if [[ -n "$compose_network" ]]; then
docker network disconnect "$compose_network" "$HOSTNAME" >/dev/null 2>&1 || true
fi
RENDEZVOUS_UID=1654 RENDEZVOUS_GID=1654 RENDEZVOUS_IMAGE="git.finalfactory.de/heikyu/rendezvous:${RENDEZVOUS_VERSION}" \
docker compose -f deploy/compose/compose.yaml down --volumes >/dev/null 2>&1 || true
rm -f "$secret"
}
trap cleanup EXIT
umask 077
install -d -m 0700 deploy/compose/secrets
openssl rand -out "$secret" 32
chmod 0600 "$secret"
publisher_credential="$(RENDEZVOUS_SMOKE_LOCAL_KEY="$secret" \
./scripts/mint-local-publisher-credential.sh)"
export RENDEZVOUS_PUBLISHER_CREDENTIAL="$publisher_credential"
chmod 0444 "$secret"
export RENDEZVOUS_UID=1654
export RENDEZVOUS_GID=1654
@@ -141,21 +142,29 @@ jobs:
test -n "$container_id"
compose_network="$(docker inspect "$container_id" | jq -er \
'.[0].NetworkSettings.Networks | keys[0]')"
docker network connect "$compose_network" "$HOSTNAME"
service_ip="$(docker inspect "$container_id" | jq -er \
--arg network "$compose_network" \
'.[0].NetworkSettings.Networks[$network].IPAddress')"
export RENDEZVOUS_SMOKE_HTTP_URL="http://${service_ip}:8080/"
export RENDEZVOUS_SMOKE_UDP_ENDPOINT="${service_ip}:9050"
for attempt in {1..100}; do
curl --fail --silent "${RENDEZVOUS_SMOKE_HTTP_URL%/}/health/ready" >/dev/null 2>&1 && break
if (( attempt == 100 )); then
docker run --rm \
--network "$compose_network" \
--user "$(id -u):$(id -g)" \
--env HOME=/tmp \
--env RENDEZVOUS_SMOKE_HTTP_URL="http://${service_ip}:8080/" \
--env RENDEZVOUS_SMOKE_UDP_ENDPOINT="${service_ip}:9050" \
--env RENDEZVOUS_PUBLISHER_CREDENTIAL \
--volume "$runner_workspace_source:/source:ro" \
--workdir /source \
"$RENDEZVOUS_RELEASE_BUILDER" \
bash -lc '
for attempt in {1..300}; do
curl --fail --silent "${RENDEZVOUS_SMOKE_HTTP_URL%/}/health/ready" >/dev/null 2>&1 && exec ./scripts/smoke-deployment.sh
sleep 0.1
done
exit 1
' || {
docker compose -f deploy/compose/compose.yaml logs rendezvous
exit 1
fi
sleep 0.1
done
./scripts/smoke-deployment.sh
}
- name: Scan candidate for high and critical vulnerabilities
uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0, post-incident safe SHA
+5 -3
View File
@@ -49,9 +49,11 @@ Compose, then point `RENDEZVOUS_SMOKE_HTTP_URL` and
and production-advertised service ports remain 8080/9050. Sibling-container CI
runners may also set `RENDEZVOUS_CONFIG_SOURCE` and
`RENDEZVOUS_SECRET_SOURCE` to host-visible absolute bind-source paths; local
operators should normally keep the checked-in relative defaults. CI attaches
its ephemeral job container to the isolated Compose network for smoke traffic;
it does not widen the default loopback HTTP publication.
operators should normally keep the checked-in relative defaults. CI starts its
ephemeral smoke client directly on the isolated Compose network; it does not
widen the default loopback HTTP publication. It mints the disposable publisher
credential while the generated key is still owner-private, then makes the key
read-only for the non-root service container.
`deploy/compose/appsettings.Production.json` is a local/private-bridge smoke
profile, not an Internet template: TCP is published only on host loopback, the
@@ -179,10 +179,13 @@ public sealed class ReleaseCompatibilityTests
string workflow = File.ReadAllText(Path.Combine(root, ".gitea/workflows", workflowName));
Assert.Contains("GITHUB_RUN_ID", workflow, StringComparison.Ordinal);
Assert.Contains("compose_network", workflow, StringComparison.Ordinal);
Assert.Contains("docker network connect", workflow, StringComparison.Ordinal);
Assert.Contains("docker network disconnect", workflow, StringComparison.Ordinal);
Assert.Contains("\"$compose_network\" \"$HOSTNAME\"", workflow, StringComparison.Ordinal);
Assert.Contains("--network \"$compose_network\"", workflow, StringComparison.Ordinal);
Assert.Contains("publisher_credential", workflow, StringComparison.Ordinal);
Assert.Contains("RENDEZVOUS_PUBLISHER_CREDENTIAL", workflow, StringComparison.Ordinal);
Assert.Contains("for attempt in {1..300}", workflow, StringComparison.Ordinal);
Assert.Contains("service_ip", workflow, StringComparison.Ordinal);
Assert.Contains("http://${service_ip}:8080/", workflow, StringComparison.Ordinal);
Assert.Contains("${service_ip}:9050", workflow, StringComparison.Ordinal);
Assert.Contains("RENDEZVOUS_HTTP_HOST_PORT", workflow, StringComparison.Ordinal);
Assert.Contains("RENDEZVOUS_UDP_HOST_PORT", workflow, StringComparison.Ordinal);
Assert.Contains("RENDEZVOUS_SMOKE_HTTP_URL", workflow, StringComparison.Ordinal);