---
id: w2/m9/t005
title: Live acceptance — private repo → live URL; push → auto-redeploy; autoDeploy:false suppresses
worker: worker2
status: done
estimate: 40m
depends_on: [w2/m9/t004]
---

## Objective

Prove the whole loop on a real cluster with a real private GitHub repo: connect (m8) → create the service → in-cluster build clones with the installation token → live URL; `git push` to the tracked branch → signed GitHub App delivery → auto-redeploy visible in deploy history; flipping `autoDeploy: false` suppresses the next push.

## Context

- Cluster: prod Hetzner or the local mock (`scripts/mock-cluster.sh`; build-from-git quirks in memory — Zot NodePort, bex-builds PSA, containerd certs.d).
- Test repo: a private copy of `examples/hello-go` under the connected account.
- Deploy history (w2/m5) is the observable for "new revision"; `kubectl get apps.app.bex.co` for phase/url.
- Precedent: m2/t004 and m5/t005 live-acceptance write-ups — record the evidence the same way.

## Steps

1. Configure the GitHub App env on the target bex-api; install the app on the test account with the private repo granted.
2. Create via MCP `deploy` or REST; verify build clones (no auth error) and URL serves.
3. Push a visible change → confirm auto-redeploy (new deploy in history, new content at the URL) with no webhook configured on the repo.
4. Set `autoDeploy: false`, push again → no redeploy. Tamper a delivery signature → 401.
5. Record pass/fail evidence in the milestone README.

## Files

- `.pm/w2/m9/README.md` (evidence note)

## Acceptance criteria

- [ ] All four checks pass and are evidenced (URLs, deploy ids, timestamps)

## Out of scope

- Load/perf; multi-repo scale testing

## Handoff runbook (code-complete 2026-07-11; live run pending)

All code + unit/envtest coverage for m8+m9 is merged (backend `go test ./...`, operator `make test`, `make lint` all green). What remains is the hands-on live loop, which needs a real GitHub App + private repo + cluster — do it as follows:

1. **Create a GitHub App** (manifest flow, docs/ADR026-github-integration.md §2): permissions `contents:read` + `metadata:read`, subscribe to the `push` event, set the webhook URL to `https://<api-host>/v1/webhooks/git` and the Setup URL to `https://<api-host>/v1/git/callback`. Note the app id, slug, private key (PEM), and webhook secret.
2. **Configure bex-api env** on the target cluster: `BEX_GITHUB_APP_ID`, `BEX_GITHUB_APP_PRIVATE_KEY`, `BEX_GITHUB_APP_SLUG`, `BEX_GITHUB_WEBHOOK_SECRET`, plus `BEX_CP_DB_URI` (connections need the control-plane store) and `BEX_DASHBOARD_URL`. Any `BEX_GITHUB_APP_*` unset ⇒ git-connect verbs 503 (verify that too).
3. **Connect**: dashboard Settings → Connect GitHub → install on a test account with a **private** copy of `examples/hello-go` granted → callback lands back on /settings connected. Confirm `GET /v1/repos`, GraphQL `repos`, MCP `list_repos` all return the private repo.
4. **Private deploy**: create the service from that repo (MCP `deploy` or REST) → confirm the in-cluster build clones with the installation token (no auth error in the build Job logs) → live URL serves.
5. **Hands-free push**: push a visible change to the tracked branch → confirm auto-redeploy (new revision in deploy history, new content at the URL) with **no webhook configured on the repo**.
6. **autoDeploy gate**: `setAutoDeploy(false)` (dashboard toggle or GraphQL) → push again → no redeploy.
7. **Signature**: send a tampered `X-Hub-Signature-256` → 401; a `ping` event → 200 no-op.
8. Record pass/fail evidence (URLs, deploy ids, timestamps) here, then run the t009 closeout.

## Also pending (dashboard verification)

The dashboard code (Connect-GitHub card, Auto-Deploy toggle) is written and prettier-clean but its generated GraphQL hooks need `yarn codegen` against the updated live bex-api (it introspects the schema to emit `GitConnectionDocument`/`ConnectGitDocument`/`DisconnectGitDocument`/`SetAutoDeployDocument` + the `autoDeploy` field types). Run `CODEGEN_SESSION_TOKEN=<ory-session> yarn codegen && yarn typecheck && yarn test`, then the Playwright pass (m8/t006 + this task).
