Skip to content

feat(deploy): P4.2b — mint GitHub App installation token for source=git clones#226

Merged
mastermanas805 merged 2 commits into
masterfrom
feat/github-app-p4-2b-2026-06-03
Jun 3, 2026
Merged

feat(deploy): P4.2b — mint GitHub App installation token for source=git clones#226
mastermanas805 merged 2 commits into
masterfrom
feat/github-app-p4-2b-2026-06-03

Conversation

@mastermanas805

Copy link
Copy Markdown
Member

A source=git deploy with no stored PAT but linked to a GitHub App installation
now clones its private repo with a freshly-minted, short-lived installation
token (contents:read, ~1h) instead of requiring a long-lived PAT — the
private-repo payoff of the App integration.

  • DeployHandler gains an installationTokenMinter (interface; github.App
    satisfies it), wired in NewDeployHandler when GITHUB_APP_ENABLED + key valid
    (nil otherwise → git clones fall back to PAT/public). SetGitHubApp setter
    mirrors SetEmailClient/SetComputeProvider.
  • runDeploy → applyInstallationAuth → installationCloneToken: looks up the
    deploy's app_github_connection → installation_id, validates the installation
    belongs to the deploy's team AND isn't suspended (anti-hijack / revocation),
    mints via the minter. Fail-soft: any miss leaves GitAuth empty (public clone).
    A stored PAT takes precedence (no mint).
  • Migration-free (reuses app_github_connections.installation_id).

Tests: sqlmock white-box covers applyInstallationAuth + installationCloneToken
100% across every branch (non-git / PAT / app-disabled / no-connection /
no-installation-id / installation-missing / suspended / team-mismatch /
mint-error / minted), plus NewDeployHandler minter-wiring (valid/bad/disabled).
The end-to-end real-DB source=git runDeploy path is covered by the existing
TestDeployNew_SourceGit_FlagOn_Accepted.

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

…it clones

A source=git deploy with no stored PAT but linked to a GitHub App installation
now clones its private repo with a freshly-minted, short-lived installation
token (contents:read, ~1h) instead of requiring a long-lived PAT — the
private-repo payoff of the App integration.

- DeployHandler gains an installationTokenMinter (interface; github.App
  satisfies it), wired in NewDeployHandler when GITHUB_APP_ENABLED + key valid
  (nil otherwise → git clones fall back to PAT/public). SetGitHubApp setter
  mirrors SetEmailClient/SetComputeProvider.
- runDeploy → applyInstallationAuth → installationCloneToken: looks up the
  deploy's app_github_connection → installation_id, validates the installation
  belongs to the deploy's team AND isn't suspended (anti-hijack / revocation),
  mints via the minter. Fail-soft: any miss leaves GitAuth empty (public clone).
  A stored PAT takes precedence (no mint).
- Migration-free (reuses app_github_connections.installation_id).

Tests: sqlmock white-box covers applyInstallationAuth + installationCloneToken
100% across every branch (non-git / PAT / app-disabled / no-connection /
no-installation-id / installation-missing / suspended / team-mismatch /
mint-error / minted), plus NewDeployHandler minter-wiring (valid/bad/disabled).
The end-to-end real-DB source=git runDeploy path is covered by the existing
TestDeployNew_SourceGit_FlagOn_Accepted.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mastermanas805 mastermanas805 enabled auto-merge (squash) June 3, 2026 17:58
deploy.go:414 (SetGitHubApp) was uncovered — the sqlmock tests set the minter
via a struct literal. Route through h.SetGitHubApp(minter) in the test helper
so the setter is exercised.
@mastermanas805 mastermanas805 merged commit 0e107ad into master Jun 3, 2026
18 checks passed
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