A CLI-first git forge.

cli forge git self-hosted

https://gitbay.org

Commit c8bf623f41

c8bf623f41f5a83856a502f4f88fac365e4df268

parent: d4aaf96d88

Verified · cmc ci/build: success

cmc <hello@cleberg.net> · 2026-08-30T01:52:40Z

deploy: refuse to build a dirty tree

Every build target compiles the working tree, not HEAD. Uncommitted work
ships without review, and migrations/ is embedded, so a migration file
that exists only on disk migrates the production database on restart.
0027 reached gitbay.org that way, inside an unrelated deploy, an hour
before it merged.

The check is git status --porcelain, so untracked files count: go:embed
does not consult the index, and an untracked migration is the exact case
that got through. ALLOW_DIRTY=1 ships an uncommitted build on purpose.

Ref #28.
Makefile +13
@@ -5,6 +5,7 @@
55 # make deploy-runner update the CI runner on HOST (only when cmd/gitbay-runner changed)
66 #
77 # Override the target host with: make deploy HOST=example.org PORT=22
8# Deploy an uncommitted build on purpose with: ALLOW_DIRTY=1 make deploy
89
910 HOST ?= 46.232.248.67
1011 PORT ?= 2222
@@ -25,7 +26,19 @@ test:
2526
2627 # Fail in seconds on an unreachable host or a wedged ssh-agent, rather
2728 # than hanging on a credential prompt mid-deploy.
29#
30# Also refuse a dirty tree. Every build target compiles the working tree, not
31# HEAD, so uncommitted work ships silently -- and migrations/ is embedded, so a
32# migration file that exists only on disk still migrates the production
33# database on restart. That happened once: 0027 reached gitbay.org inside an
34# unrelated deploy, an hour before it merged. Untracked counts; go:embed does
35# not consult the index.
2836 preflight:
37 @[ -n "$(ALLOW_DIRTY)" ] || [ -z "$$(git status --porcelain)" ] \
38 || { echo "working tree is dirty; deploy builds the tree, not HEAD:" >&2; \
39 git status --short >&2; \
40 echo "commit first, or ALLOW_DIRTY=1 make deploy to ship it anyway." >&2; \
41 exit 1; }
2942 @echo "==> checking $(HOST):$(PORT)"
3043 @ssh -p $(PORT) -o BatchMode=yes -o ConnectTimeout=10 root@$(HOST) true \
3144 || { echo "cannot reach root@$(HOST):$(PORT) without a prompt." >&2; \