Skip to content

ci: add a manual deploy workflow (Actions → Deploy) - #34

Merged
EOEboh merged 1 commit into
mainfrom
chore/ci-and-currency-guard
Jul 28, 2026
Merged

ci: add a manual deploy workflow (Actions → Deploy)#34
EOEboh merged 1 commit into
mainfrom
chore/ci-and-currency-guard

Conversation

@EOEboh

@EOEboh EOEboh commented Jul 28, 2026

Copy link
Copy Markdown
Owner

Answers "is there a new way to deploy?" — there is now, for the backend. The frontend already auto-deployed from main via Cloudflare Pages and still does.

Why

Deploying meant a laptop with Docker, the SSH key and a good connection. Nothing tied a deploy to a reviewed commit, and nothing surfaced drift: production ran a 12-day-old build against a current frontend with no signal at all. That is what produced the live checkout 500.

How it works

Actions → Deploy → Run workflow. Manual by design: merging should not ship to customers by itself, but a deploy should not depend on one machine either. Takes a ref, defaults to main.

The release is ordered so a failed deploy cannot take the site down:

  1. Re-runs go vet and the tests at the commit being deployed — workflow_dispatch is not gated on the CI workflow, and "it passed on the PR" is not the same as "it passes here"
  2. Builds linux/amd64, pushes ghcr.io/eoeboh/hookdrop:<sha> and :latest
  3. Pulls the exact tag on the server first, so compose is only repointed at an image the host already holds
  4. Backs up docker-compose.yml and snapshots the DB after a clean shutdown (WAL checkpointed)
  5. Restarts, then polls /health for 60s
  6. Rolls back to the previous image and fails the run if it never comes healthy
  7. Verifies https://api.hookdrop.app/health from outside and checks uptime is fresh — localhost being healthy says nothing about what customers reach

Rollback is re-running the workflow against the previous commit; images are tagged per commit so nothing needs rebuilding.

Setup already done

  • Dedicated ed25519 deploy key generated, installed in the server's authorized_keys (previous file backed up), and verified. Your personal key is untouched.
  • DEPLOY_SSH_KEY, DEPLOY_HOST, DEPLOY_USER set as repo secrets. The private key was written to GitHub and deleted locally.

One manual step remains: the first run publishes the GHCR package as private. Either make ghcr.io/eoeboh/hookdrop public (the image holds only the compiled binary — all secrets come from compose env on the server) or docker login ghcr.io once on the box. Without one of those the server cannot pull.

scripts/deploy.sh

Kept as break-glass, and fixed: it now repoints compose back at the local image, since the workflow leaves it on a ghcr.io tag and the old script would otherwise conflict. It also confirms before shipping and warns when the tree is dirty.

Testing

workflow_dispatch only appears once the workflow is on the default branch, so this cannot be exercised until it merges. Happy to run it and verify the whole path — including a deliberate rollback — once it is in.

Deploys were a laptop with Docker, the SSH key and a good connection.
Nothing tied a deploy to a reviewed commit, and nothing surfaced drift —
production ran a 12-day-old build against a current frontend without any
signal, which is how the live checkout 500 happened.

Actions tab → Deploy → Run workflow. Manual on purpose: merging should
not ship to customers on its own, but a deploy should not depend on one
machine either.

It re-runs vet and the tests before building, because workflow_dispatch
is not gated on the CI workflow and "it passed on the PR" is not the same
as "it passes at the commit being deployed".

The release is ordered so a failure cannot take the site down: the exact
tag is pulled first, compose is only then repointed at an image the host
already holds, and the container is restarted. If /health does not answer
within 60s it restores the previous image and fails the run. The public
endpoint is checked afterwards as well, since localhost being healthy
says nothing about what customers reach.

Images are tagged by commit as well as latest, so a rollback is re-running
this against the previous commit rather than rebuilding it.

scripts/deploy.sh stays as the break-glass path and now repoints compose
back at the local image, since the workflow leaves it on a ghcr.io tag.
It also asks before shipping and warns on a dirty tree.
@cloudflare-workers-and-pages

Copy link
Copy Markdown
Contributor

Deploying hookdrop with  Cloudflare Pages  Cloudflare Pages

Latest commit: 7c8f2b1
Status: ✅  Deploy successful!
Preview URL: https://3f2673c4.hookdrop.pages.dev
Branch Preview URL: https://chore-ci-and-currency-guard.hookdrop.pages.dev

View logs

@cloudflare-workers-and-pages

Copy link
Copy Markdown
Contributor

Deploying hookdrop-frontend with  Cloudflare Pages  Cloudflare Pages

Latest commit: 7c8f2b1
Status: ✅  Deploy successful!
Preview URL: https://80c4f7dd.hookdrop-frontend.pages.dev
Branch Preview URL: https://chore-ci-and-currency-guard.hookdrop-frontend.pages.dev

View logs

@EOEboh
EOEboh merged commit 026f727 into main Jul 28, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant