Makefile

main
gitbay/Makefile history · blame · raw

98 lines · 4967 bytes

 1# gitbay build and deploy.
 2#
 3#   make test          run the full suite
 4#   make deploy        build the server, push it to HOST, rebuild the local CLI
 5#   make deploy-runner update the CI runner on HOST (only when cmd/gitbay-runner changed)
 6#
 7# 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
 9
10HOST     ?= gitbay.org
11PORT     ?= 2222
12CLI_DEST ?= $(HOME)/go/bin/gitbay
13
14CROSS   := CGO_ENABLED=0 GOOS=linux GOARCH=amd64
15
16# Stamp the commit into every binary so a deployed artifact can say where it
17# came from. The -dirty suffix only appears under ALLOW_DIRTY=1, since
18# preflight otherwise refuses to build an uncommitted tree.
19COMMIT  := $(shell git rev-parse --short=12 HEAD 2>/dev/null || echo unknown)$(shell [ -n "$$(git status --porcelain 2>/dev/null)" ] && echo -dirty)
20LDFLAGS := -s -w -X gitbay.org/gitbay/internal/buildinfo.Commit=$(COMMIT)
21SERVER_BIN := dist/gitbayd-linux-amd64
22RUNNER_BIN := dist/gitbay-runner-linux-amd64
23
24.PHONY: help test server cli deploy deploy-runner preflight
25
26help:
27	@sed -n 's/^#   //p' $(MAKEFILE_LIST)
28
29# -timeout 30m is a ceiling for a real hang, not a working figure: the
30# suite runs in a couple of minutes since the e2e tests went parallel.
31test:
32	go test ./... -count=1 -timeout 30m
33
34# Fail in seconds on an unreachable host or a wedged ssh-agent, rather
35# than hanging on a credential prompt mid-deploy.
36#
37# Also refuse a dirty tree. Every build target compiles the working tree, not
38# HEAD, so uncommitted work ships silently -- and migrations/ is embedded, so a
39# migration file that exists only on disk still migrates the production
40# database on restart. That happened once: 0027 reached gitbay.org inside an
41# unrelated deploy, an hour before it merged. Untracked counts; go:embed does
42# not consult the index.
43preflight:
44	@[ -n "$(ALLOW_DIRTY)" ] || [ -z "$$(git status --porcelain)" ] \
45	  || { echo "working tree is dirty; deploy builds the tree, not HEAD:" >&2; \
46	       git status --short >&2; \
47	       echo "commit first, or ALLOW_DIRTY=1 make deploy to ship it anyway." >&2; \
48	       exit 1; }
49	@echo "==> checking $(HOST):$(PORT)"
50	@ssh -p $(PORT) -o BatchMode=yes -o ConnectTimeout=10 root@$(HOST) true \
51	  || { echo "cannot reach root@$(HOST):$(PORT) without a prompt." >&2; \
52	       echo "if ssh-add -l says 'invalid format', the agent is wedged: killall ssh-agent" >&2; \
53	       exit 1; }
54
55server:
56	@echo "==> building $(SERVER_BIN)"
57	$(CROSS) go build -trimpath -ldflags='$(LDFLAGS)' -o $(SERVER_BIN) ./cmd/gitbayd
58
59cli:
60	@echo "==> installing CLI to $(CLI_DEST)"
61	go build -o $(CLI_DEST) ./cmd/gitbay
62
63deploy: preflight server
64	@echo "==> pushing to $(HOST) (~24MB, then restart)"
65	./deploy/install.sh $(HOST) $(PORT)
66	@$(MAKE) --no-print-directory cli
67	@echo "==> deployed $$(git rev-parse --short HEAD)"
68
69deploy-runner: preflight
70	@echo "==> building $(RUNNER_BIN)"
71	$(CROSS) go build -trimpath -ldflags='$(LDFLAGS)' -o $(RUNNER_BIN) ./cmd/gitbay-runner
72	@echo "==> pushing runner to $(HOST)"
73	./deploy/copy.sh $(HOST) $(PORT) $(RUNNER_BIN) /usr/local/bin/gitbay-runner.new
74	ssh -p $(PORT) root@$(HOST) 'mkdir -p /etc/systemd/system/gitbay-runner.service.d /etc/gitbay-runner'
75	./deploy/copy.sh $(HOST) $(PORT) deploy/gitbay-runner.override.conf /etc/systemd/system/gitbay-runner.service.d/override.conf
76	./deploy/copy.sh $(HOST) $(PORT) deploy/gitbay-runner-prune.service /etc/systemd/system/gitbay-runner-prune.service
77	./deploy/copy.sh $(HOST) $(PORT) deploy/gitbay-runner-prune.timer /etc/systemd/system/gitbay-runner-prune.timer
78	./deploy/copy.sh $(HOST) $(PORT) deploy/gitbay-runner-egress.nft /etc/gitbay-runner/egress.nft
79	./deploy/copy.sh $(HOST) $(PORT) deploy/gitbay-runner-egress.service /etc/systemd/system/gitbay-runner-egress.service
80	./deploy/copy.sh $(HOST) $(PORT) deploy/gitbay-runner-builds.nft /etc/gitbay-runner/builds.nft
81	@echo "==> loading the egress rule"
82	@# builds.nft names the runner's class cgroups, which may not exist yet;
83	@# its syntax is checked against system.slice, which always does.
84	ssh -p $(PORT) root@$(HOST) 'set -eu; \
85	  nft -c -f /etc/gitbay-runner/egress.nft; \
86	  sed "s|level 4 \"system.slice/gitbay-runner.service/builds/[a-z]*\"|level 1 \"system.slice\"|" /etc/gitbay-runner/builds.nft | nft -c -f /dev/stdin; \
87	  systemctl daemon-reload; \
88	  systemctl enable gitbay-runner-egress.service; \
89	  systemctl reload-or-restart gitbay-runner-egress.service'
90	ssh -p $(PORT) root@$(HOST) 'sh -s' < deploy/runner-egress-check.sh
91	ssh -p $(PORT) root@$(HOST) 'set -eu; \
92	  chmod 755 /usr/local/bin/gitbay-runner.new; \
93	  mv /usr/local/bin/gitbay-runner.new /usr/local/bin/gitbay-runner; \
94	  systemctl enable --now gitbay-runner-prune.timer; \
95	  systemctl restart gitbay-runner; \
96	  nft list table inet gitbay_builds >/dev/null; \
97	  systemctl --no-pager --lines=3 status gitbay-runner; \
98	  systemctl --no-pager list-timers gitbay-runner-prune.timer'