diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 02c6b2b..6023ed9 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -178,21 +178,16 @@ jobs: docker compose -f "$compose_file" up --no-build --detach container_id="$(docker compose -f "$compose_file" ps -q rendezvous)" test -n "$container_id" - compose_network="$(docker inspect "$container_id" | jq -er \ - '.[0].NetworkSettings.Networks | keys[0]')" - service_ip="$(docker inspect "$container_id" | jq -er \ - --arg network "$compose_network" \ - '.[0].NetworkSettings.Networks[$network].IPAddress')" 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" docker run --rm \ - --network "$compose_network" \ + --network "container:${container_id}" \ --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_SMOKE_HTTP_URL=http://127.0.0.1:8080/ \ + --env RENDEZVOUS_SMOKE_UDP_ENDPOINT=127.0.0.1:9050 \ --env RENDEZVOUS_PUBLISHER_CREDENTIAL \ --volume "$runner_workspace_source:/source:ro" \ --workdir /source \ diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index c93461b..93b9a21 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -140,17 +140,12 @@ jobs: docker compose -f deploy/compose/compose.yaml up --detach --no-build container_id="$(docker compose -f deploy/compose/compose.yaml ps -q rendezvous)" test -n "$container_id" - compose_network="$(docker inspect "$container_id" | jq -er \ - '.[0].NetworkSettings.Networks | keys[0]')" - service_ip="$(docker inspect "$container_id" | jq -er \ - --arg network "$compose_network" \ - '.[0].NetworkSettings.Networks[$network].IPAddress')" docker run --rm \ - --network "$compose_network" \ + --network "container:${container_id}" \ --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_SMOKE_HTTP_URL=http://127.0.0.1:8080/ \ + --env RENDEZVOUS_SMOKE_UDP_ENDPOINT=127.0.0.1:9050 \ --env RENDEZVOUS_PUBLISHER_CREDENTIAL \ --volume "$runner_workspace_source:/source:ro" \ --workdir /source \ diff --git a/docs/deployment/linux.md b/docs/deployment/linux.md index 1daca49..f20f6f4 100644 --- a/docs/deployment/linux.md +++ b/docs/deployment/linux.md @@ -49,14 +49,14 @@ 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 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. Automation probes readiness once -per second and allows up to three minutes for a cold, resource-constrained image -to become ready; the protocol smoke retains its separate, stricter scenario -timeout. +operators should normally keep the checked-in relative defaults. CI runs its +ephemeral smoke client as a sidecar in the service container's network namespace +to avoid runner-specific bridge and host-routing policy; 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. Automation probes readiness once per second and +allows up to three minutes for a cold, resource-constrained image to become +ready; the protocol smoke retains its separate, stricter scenario timeout. `deploy/compose/appsettings.Production.json` is a local/private-bridge smoke profile, not an Internet template: TCP is published only on host loopback, the diff --git a/tests/FinalFactory.Rendezvous.Tests/Release/ReleaseCompatibilityTests.cs b/tests/FinalFactory.Rendezvous.Tests/Release/ReleaseCompatibilityTests.cs index c7e182d..ae2ff79 100644 --- a/tests/FinalFactory.Rendezvous.Tests/Release/ReleaseCompatibilityTests.cs +++ b/tests/FinalFactory.Rendezvous.Tests/Release/ReleaseCompatibilityTests.cs @@ -178,15 +178,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("--network \"$compose_network\"", workflow, StringComparison.Ordinal); + Assert.Contains("--network \"container:${container_id}\"", workflow, StringComparison.Ordinal); Assert.Contains("publisher_credential", workflow, StringComparison.Ordinal); Assert.Contains("RENDEZVOUS_PUBLISHER_CREDENTIAL", workflow, StringComparison.Ordinal); Assert.Contains("for attempt in {1..180}", workflow, StringComparison.Ordinal); Assert.Contains("sleep 1", 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("http://127.0.0.1:8080/", workflow, StringComparison.Ordinal); + Assert.Contains("127.0.0.1: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);