diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 54a757e..9bf5c71 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -114,17 +114,21 @@ jobs: # (Type=simple, no readiness protocol) — not that `podman compose up # --build` actually finished and Puma is answering. Polls the health # endpoint (cube-host itself, same machine the container's port is - # published on) instead of trusting that. 5 minutes covers even a - # from-scratch rebuild (Gemfile change, ~3.5 minutes measured) with - # room to spare; a cached rebuild is normally up within a minute. + # published on) instead of trusting that — checking for this + # deploy's own revision, not just any 200, so a stuck old container + # that never got torn down can't pass as a successful deploy of the + # new one. 5 minutes covers even a from-scratch rebuild (Gemfile + # change, ~3.5 minutes measured) with room to spare; a cached + # rebuild is normally up within a minute. - name: Wait for it to come up run: | + expected=$(git rev-parse --short HEAD) for i in $(seq 1 30); do - if curl -sf http://localhost:4567/api/health >/dev/null; then - echo "Healthy after $(( (i - 1) * 10 ))s" + if curl -sf http://localhost:4567/api/health | grep -q "\"revision\":\"$expected\""; then + echo "Healthy at $expected after $(( (i - 1) * 10 ))s" exit 0 fi sleep 10 done - echo "::error::maptool did not become healthy within 5 minutes" + echo "::error::maptool did not report revision $expected within 5 minutes" exit 1 diff --git a/app.rb b/app.rb index 80e3ff8..cfc551b 100644 --- a/app.rb +++ b/app.rb @@ -169,7 +169,7 @@ module Maptool end get "/api/health" do - json status: "ok" + json status: "ok", revision: REVISION end get "/api/offline-tiles" do diff --git a/docs/deployment.adoc b/docs/deployment.adoc index d84c63f..c90e722 100644 --- a/docs/deployment.adoc +++ b/docs/deployment.adoc @@ -246,8 +246,11 @@ a retagged image's old layers behind — turning every deploy into a full `apt-get`/`bundle install` from scratch (~3 minutes measured, vs. ~20s before). Fixed by adding `--build` to the unit instead (see above); don't reintroduce the `podman rmi` step. -. Polls `http://localhost:4567/api/health` (up to 5 minutes, the job - fails if it never comes up) before calling the deploy done — the - restart above only confirms `podman compose up --build` was - launched (`Type=simple` has no readiness protocol), not that the - build actually succeeded and Puma is answering. +. Polls `http://localhost:4567/api/health` for *this deploy's own* + revision (up to 5 minutes, the job fails if it never shows up) + before calling the deploy done — the restart above only confirms + `podman compose up --build` was launched (`Type=simple` has no + readiness protocol), not that the build actually succeeded and the + new code is what's answering; checking the revision specifically, + not just any 200, also catches a stuck old container that never got + torn down. diff --git a/test/test_app.rb b/test/test_app.rb index 96b99b6..c25902a 100644 --- a/test/test_app.rb +++ b/test/test_app.rb @@ -7,7 +7,7 @@ class AppTest < Minitest::Test def test_health response = request.get("/api/health") assert_equal 200, response.status - assert_equal({ "status" => "ok" }, json_body(response)) + assert_equal({ "status" => "ok", "revision" => "dev" }, json_body(response)) end def test_index_renders_with_asset_versioning_and_importmap