|
1 | 1 | name: deploy |
2 | 2 |
|
3 | 3 | # Fully autonomous, idempotent deploy. On every push to main (or manual |
4 | | -# dispatch) this SSHes to the bbs.profullstack.com droplet and re-runs the |
5 | | -# idempotent provisioner (setup.sh), which pulls origin, rebuilds the Go |
6 | | -# binaries, and restarts the agentbbs service that answers |
7 | | -# `ssh join@bbs.profullstack.com`. Re-running is always safe. |
| 4 | +# dispatch) this builds the Go binaries ON THE RUNNER (which has plenty of |
| 5 | +# RAM), ships them to the bbs.profullstack.com droplet, and re-runs the |
| 6 | +# idempotent provisioner (setup.sh) with SKIP_BUILD=1 so the tiny droplet |
| 7 | +# never has to compile. setup.sh still pulls origin, refreshes config/assets, |
| 8 | +# and restarts the agentbbs service that answers `ssh join@bbs.profullstack.com`. |
| 9 | +# Re-running is always safe. |
| 10 | +# |
| 11 | +# Why build on the runner: the droplet is a ~458MB box also running ergo, |
| 12 | +# forgejo, tor, podman and the live agentbbs. The Go linker's peak memory was |
| 13 | +# OOM-killing the build — and with it the sshd serving the deploy session, |
| 14 | +# surfacing as "Connection closed by remote host" (exit 255). Compiling on the |
| 15 | +# 16GB runner removes that failure mode entirely. |
8 | 16 | # |
9 | 17 | # Required repo secrets (Settings -> Secrets and variables -> Actions): |
10 | 18 | # DEPLOY_SSH_KEY private key whose public half is in the droplet admin |
|
30 | 38 | deploy: |
31 | 39 | runs-on: ubuntu-latest |
32 | 40 | steps: |
| 41 | + - uses: actions/checkout@v4 |
| 42 | + |
33 | 43 | - name: Configure SSH |
34 | 44 | env: |
35 | 45 | DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }} |
|
43 | 53 | chmod 600 ~/.ssh/id_deploy |
44 | 54 | ssh-keyscan -p "$DEPLOY_PORT" -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts 2>/dev/null |
45 | 55 |
|
46 | | - - name: Provision / redeploy (idempotent) |
| 56 | + - name: Detect droplet architecture |
| 57 | + id: arch |
| 58 | + env: |
| 59 | + DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} |
| 60 | + DEPLOY_USER: ${{ secrets.DEPLOY_USER || 'root' }} |
| 61 | + DEPLOY_PORT: ${{ secrets.DEPLOY_PORT || '2202' }} |
| 62 | + run: | |
| 63 | + uname_m="$(ssh -i ~/.ssh/id_deploy -p "$DEPLOY_PORT" \ |
| 64 | + -o BatchMode=yes -o StrictHostKeyChecking=yes \ |
| 65 | + "${DEPLOY_USER}@${DEPLOY_HOST}" 'uname -m')" |
| 66 | + case "$uname_m" in |
| 67 | + x86_64|amd64) goarch=amd64 ;; |
| 68 | + aarch64|arm64) goarch=arm64 ;; |
| 69 | + *) echo "::error::unsupported droplet arch '$uname_m'"; exit 1 ;; |
| 70 | + esac |
| 71 | + echo "goarch=$goarch" >> "$GITHUB_OUTPUT" |
| 72 | + echo "::notice::droplet arch $uname_m -> GOARCH=$goarch" |
| 73 | +
|
| 74 | + - uses: actions/setup-go@v5 |
| 75 | + with: |
| 76 | + go-version-file: go.mod |
| 77 | + cache: true |
| 78 | + |
| 79 | + - name: Build binaries (on the runner, not the droplet) |
| 80 | + env: |
| 81 | + GOOS: linux |
| 82 | + GOARCH: ${{ steps.arch.outputs.goarch }} |
| 83 | + CGO_ENABLED: '0' # pure-Go (modernc sqlite) — static, portable binary |
| 84 | + run: | |
| 85 | + mkdir -p dist |
| 86 | + go build -trimpath -o dist/agentbbs ./cmd/agentbbs |
| 87 | + go build -trimpath -o dist/ascii-live ./cmd/ascii-live |
| 88 | + file dist/* || true |
| 89 | +
|
| 90 | + - name: Ship binaries to the droplet |
| 91 | + env: |
| 92 | + DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} |
| 93 | + DEPLOY_USER: ${{ secrets.DEPLOY_USER || 'root' }} |
| 94 | + DEPLOY_PORT: ${{ secrets.DEPLOY_PORT || '2202' }} |
| 95 | + run: | |
| 96 | + # scp can only name one remote target; copy each binary explicitly. |
| 97 | + scp -i ~/.ssh/id_deploy -P "$DEPLOY_PORT" \ |
| 98 | + -o BatchMode=yes -o StrictHostKeyChecking=yes \ |
| 99 | + dist/agentbbs "${DEPLOY_USER}@${DEPLOY_HOST}:/tmp/agentbbs-deploy-agentbbs" |
| 100 | + scp -i ~/.ssh/id_deploy -P "$DEPLOY_PORT" \ |
| 101 | + -o BatchMode=yes -o StrictHostKeyChecking=yes \ |
| 102 | + dist/ascii-live "${DEPLOY_USER}@${DEPLOY_HOST}:/tmp/agentbbs-deploy-ascii-live" |
| 103 | +
|
| 104 | + - name: Provision / redeploy (idempotent, SKIP_BUILD=1) |
47 | 105 | env: |
48 | 106 | DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} |
49 | 107 | DEPLOY_USER: ${{ secrets.DEPLOY_USER || 'root' }} |
@@ -76,7 +134,11 @@ jobs: |
76 | 134 | fi |
77 | 135 | git -C "$SRC" fetch --depth 1 origin "$BRANCH" |
78 | 136 | git -C "$SRC" reset --hard "origin/$BRANCH" |
79 | | - exec env BRANCH="$BRANCH" \ |
| 137 | + # Install the runner-built binaries, then tell setup.sh not to compile. |
| 138 | + install -m 0755 /tmp/agentbbs-deploy-agentbbs /usr/local/bin/agentbbs |
| 139 | + install -m 0755 /tmp/agentbbs-deploy-ascii-live /usr/local/bin/ascii-live |
| 140 | + rm -f /tmp/agentbbs-deploy-agentbbs /tmp/agentbbs-deploy-ascii-live |
| 141 | + exec env BRANCH="$BRANCH" SKIP_BUILD=1 \ |
80 | 142 | COINPAY_API_KEY="${COINPAY_API_KEY:-}" \ |
81 | 143 | COINPAY_MERCHANT_ID="${COINPAY_MERCHANT_ID:-}" \ |
82 | 144 | AGENTBBS_QRYPT_ISSUER_KEY="${AGENTBBS_QRYPT_ISSUER_KEY:-}" \ |
|
0 commit comments