Skip to content

feat: per-PR ephemeral preview envs with PAT browser auth#95

Merged
posix4e merged 2 commits intomainfrom
feat/per-pr-envs
Apr 15, 2026
Merged

feat: per-PR ephemeral preview envs with PAT browser auth#95
posix4e merged 2 commits intomainfrom
feat/per-pr-envs

Conversation

@posix4e
Copy link
Copy Markdown
Contributor

@posix4e posix4e commented Apr 15, 2026

Summary

  • Each PR deploys its own control-plane to pr-{N}.devopsdefender.com, isolated by hostname and DD_ENV=pr-{N} (no more single shared app-staging)
  • Browser login: /auth/pat form accepts a GitHub PAT (gh auth token), validated against DD_OWNER via api.github.com/user. Reuses the existing session-cookie machinery.
  • OAuth (DD_GITHUB_CLIENT_ID) is now optional in dd-web. When unset, /auth/github/* returns 404 and browsers are redirected to /auth/pat instead.
  • release.yml's deploy-staging job is renamed to deploy-preview, computes DD_ENV + DD_HOSTNAME from github.event_name and github.event.number, and posts a comment on the PR with the preview URL.
  • New pr-teardown.yml on pull_request: closed deletes the VM, CF tunnel(s), and DNS CNAME.
  • cleanup.yml gains a reap-pr-previews job for TERMINATED dd-pr-* VMs that accumulate between pushes.

Machine auth is unchanged: /cp/attest still takes GitHub Actions OIDC, /register still takes Noise XX.

What this PR does NOT do

  • Retire the shared app-staging env (workflow_dispatch still targets it)
  • Local-agent install script (lives on the closed feat/installer branch)
  • GPU passthrough for a local agent

Those are follow-ups once the per-PR flow is proven.

Test plan

This PR exercises itself — on open, CI will:

  • Build + publish pre-release pr-{sha12}
  • Deploy a VM to pr-{this-PR}.devopsdefender.com
  • /health returns 200 via the new CF tunnel
  • /cp/attest returns a non-zero MRTD (OIDC-gated)
  • STONITH leaves exactly one dd_env=pr-{this-PR} VM RUNNING
  • Bot comments preview URL on this PR
  • curl -H "Authorization: Bearer \$(gh auth token)" https://pr-{N}.devopsdefender.com/ returns 200
  • Browser hit to / redirects to /auth/pat; form accepts PAT, sets cookie, redirects to dashboard
  • On close, pr-teardown.yml deletes VM + tunnel + DNS

🤖 Generated with Claude Code

posix4e and others added 2 commits April 15, 2026 23:14
Each PR now deploys its own CP to pr-{N}.devopsdefender.com, isolated
by hostname and DD_ENV=pr-{N}. Browser access uses /auth/pat (paste a
GitHub PAT, validated against DD_OWNER); OIDC and Noise XX still gate
machine endpoints unchanged.

On PR close, pr-teardown.yml deletes the VM, CF tunnel, and DNS
CNAME. Between pushes, cleanup.yml's new reap-pr-previews job reaps
STONITH-terminated VMs so they don't accumulate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
`env.DD_DOMAIN` isn't available when job-level `env:` is evaluated
— only vars/secrets/inputs/github/runner/needs/matrix are. Reference
`vars.DD_CF_DOMAIN` directly instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

DD preview ready

URL: https://pr-95.devopsdefender.com

Browser login: paste gh auth token output at https://pr-95.devopsdefender.com/auth/pat

CLI / curl: curl -H "Authorization: Bearer $(gh auth token)" https://pr-95.devopsdefender.com/

Register endpoint for a local agent: wss://pr-95.devopsdefender.com/register

@posix4e posix4e merged commit f61b453 into main Apr 15, 2026
3 checks passed
@posix4e posix4e deleted the feat/per-pr-envs branch April 15, 2026 23:48
@posix4e posix4e mentioned this pull request Apr 15, 2026
4 tasks
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