From 66f47a94d2144f61a777fcc7072815e6d2ea240f Mon Sep 17 00:00:00 2001 From: S'Bussiso Dube <80188685+Sbussiso@users.noreply.github.com> Date: Wed, 9 Sep 2026 14:19:38 -0700 Subject: [PATCH] =?UTF-8?q?Deploy=20from=20CI=20=E2=80=94=20fly.toml=20was?= =?UTF-8?q?=20a=20file=20that=20did=20nothing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deploy automation was deferred so a human could watch the first-ever deploy of new infrastructure, including this family's first Postgres instance. That rationale expired once the service went live, and leaving it deferred turned out worse than what it avoided: fly.toml only took effect if someone remembered to run `fly deploy` by hand. That failed silently on 2026-09-09. A scale-to-zero change merged with CI fully green and never reached Fly — the app kept running always-on, and the config looked applied because the commit was on master. It was only caught by checking the machine state directly. Config that silently doesn't apply is more dangerous than no config, because it reads as done. Deploy runs on push to master only, after the tests pass. --ha=false because Fly provisions TWO machines by default. It did exactly that on this service's manual deploy and the extra machine had to be scaled away by hand. No --strategy override: this app has no volume, so the default rolling strategy is fine. The sibling License service needs `immediate` because it mounts one. Needed a repo secret that did not exist — this repo had NO secrets at all, so a deploy job would have failed on its first run. FLY_API_TOKEN is now set, scoped to sentinel-sync only. Co-Authored-By: Claude Opus 5 --- .github/workflows/test.yml | 44 ++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1c78a6d..075a21b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,10 +1,15 @@ -name: Test +name: Test & Deploy -# Deploy automation is deferred deliberately, same rationale as -# Sentinel-License-Service's workflow of the same name: a human should -# be watching the first-ever deploy of new infrastructure (including, -# for this service, the first-ever Postgres instance in this family). -# This workflow only covers lint + dependency audit + tests. +# Tests on every push and PR; deploys to Fly on pushes to master. +# +# Deploy automation used to be deferred here so a human could watch the +# first-ever deploy of new infrastructure. That rationale expired once +# the service was live, and leaving it deferred created a worse problem: +# fly.toml became a file that did nothing. A scale-to-zero change was +# merged with CI green on 2026-09-09 and simply never reached Fly — +# the app kept running always-on until someone noticed and deployed by +# hand. Config that silently doesn't apply is more dangerous than no +# config, so this now ships. # # Unlike License-Service's version, this one needs a real Postgres # service container — JSONB isn't SQLite-portable, and this service is @@ -63,3 +68,30 @@ jobs: - name: Run tests run: uv run pytest -v + + deploy: + name: Deploy to Fly.io + runs-on: ubuntu-latest + needs: test + # Push-only: a PR runs the tests above but never ships. + if: github.event_name == 'push' + # Serialize so two quick pushes don't race on the machine update. + concurrency: + group: deploy-sentinel-sync + cancel-in-progress: true + steps: + - uses: actions/checkout@v7 + + - uses: superfly/flyctl-actions/setup-flyctl@master + + # --ha=false: Fly provisions TWO machines by default and this + # service needs one. It did exactly that on the 2026-09-09 manual + # deploy and the extra machine had to be scaled away by hand. + # + # No --strategy override: this app has no volume, so the default + # rolling strategy works. (Command Center needs `immediate` + # because its web machine mounts a single-attachment volume.) + - name: flyctl deploy + run: flyctl deploy --remote-only --ha=false --yes + env: + FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}