Skip to content

Deploy with the APCO GitHub App

The APCO GitHub App connects one project to one installed repository. It can deploy an exact Production-branch push, keep an isolated Preview for every open pull request, and report each build through a GitHub Check and one sticky APCO comment.

The App is the recommended GitHub integration. The workflow-based GitHub Actions v0 integration remains available and existing ci:deploy credentials keep working.

Set it up

Open Dashboard → Project → Settings → GitHub App.

  1. Select Set up App, then install APCO on your GitHub user or organization. Choose only the repositories APCO should be able to read.
  2. Return to the setup dialog and refresh the installation list.
  3. Select the installation, repository, and exact Production branch.
  4. For a monorepo, set the safe repository-relative Root directory and optional inclusive Watch paths (one path/glob per line).
  5. Enable Automatic Production deploys and, if wanted, Same-repository PR Previews.
  6. Save the connection.

Repository bindings use GitHub's immutable repository id, not a repository name or URL. Renaming a repository therefore does not silently point a project at a different repository.

OAuth is not a deployment credential

The GitHub account connection used for APCO sign-in and the legacy repository picker is separate. APCO never uses that broad OAuth token to download source or authorize a GitHub App deployment.

Permissions and webhook events

The APCO GitHub App requests only:

PermissionAccessWhy
MetadataReadIdentify the installed repository and account.
ContentsReadFetch the exact commit archive when a build starts.
ChecksWriteCreate and update the APCO build Check.
Pull requestsWriteMaintain one sticky APCO status comment per PR.

It does not request repository administration, Actions secrets, broad repository write access, or GitHub Deployments permission.

The App subscribes to:

  • push
  • pull_request
  • installation
  • installation_repositories

GitHub may also deliver check_run and check_suite events automatically because the App can write Checks. APCO still verifies and deduplicates those deliveries, then ignores them. Check re-run or requested-action deliveries do not approve fork code or start a deployment.

Production pushes

When automatic Production deploys are enabled, a push deploys only when its repository id and full branch ref exactly match the stored project binding. APCO records the server-attested repository, SHA, ref, and github_app trigger, applies the same account, verified-email, plan, rate, suspension, and project gates as a CLI deploy, and cancels older queued App deploys for the same project/channel.

The webhook returns after validation and queueing. Source download and builds never run inside the public webhook request.

The worker obtains a fresh, short-lived installation token only when source fetching begins and downloads the archive for the exact attested commit. The token is not stored in the database, written to a queue payload, or included in logs.

Pull-request Previews

For a pull request whose head repository is the installed repository:

  • opened, reopened, and synchronize create or update that PR's Preview;
  • later commits retire only the older Preview for the same PR;
  • different open PRs can stay live at the same time;
  • the Preview URL remains stable for that project and PR;
  • closing the PR removes its Preview route and container and marks it inactive;
  • one APCO comment is updated with the status, SHA, Preview URL, and dashboard link.

Your plan controls the maximum number of active PR Previews. If the limit is full, a new PR Preview fails clearly; APCO does not evict another PR.

Webhook deliveries can arrive late or out of order. APCO compares the stored head SHA before changing a Check, comment, or Preview, so an older event cannot overwrite the status for a newer commit.

Fork protection and maintainer approval

Fork pull requests never deploy automatically. They do not receive project environment variables or cause APCO to fetch/build their source while they are unapproved.

APCO reports Maintainer approval required and lists the pending request in the project's GitHub App card. A maintainer must approve the exact displayed SHA. At approval time APCO verifies the maintainer's repository permission and re-fetches the PR head; if the SHA changed or its identity cannot be proved, the request fails closed and no deployment is created. Review and approve the new SHA instead.

GitHub does not always allow an installed App to create a Check against a fork SHA. If GitHub returns that safe 422 case, APCO keeps the approval request in the dashboard and updates the sticky PR comment instead. It does not weaken the approval rule.

GitHub Checks and failure reporting

The APCO Check links to the deployment page and build logs. Its lifecycle is queued, in progress while APCO builds and health-checks, then completed with a success, failure, neutral, or canceled conclusion as appropriate.

GitHub reporting is asynchronous and retried independently of the deployment. A temporary GitHub API failure does not change an APCO deployment result, and a failed build still leaves a completed failing Check linked to its logs after reporting succeeds. Checks and comments contain concise status metadata only — never raw build logs, project environment values, tokens, or credentials.

Installation and repository lifecycle

  • Suspended installation: affected bindings stop accepting deploy events until GitHub marks the installation active again.
  • Repository removed from the installation: its binding is disabled and active PR Preview routes are retired.
  • Installation deleted: all of its bindings are disabled and their active PR Preview routes are retired.
  • Disconnect in APCO: future App deploys stop and active PR Preview routes are cleaned up. Production and deployment history are preserved.
  • Rebind or change Production branch: APCO cleans up obsolete PR Preview state before the new configuration becomes authoritative.

The project card shows installation, repository, permission, webhook, and reporting health. Use Manage installation to restore repository access or permissions, then refresh/reopen the APCO setup flow.

Static and server builds

GitHub App deployments feed the downloaded source into APCO's existing build, health-check, artifact, and routing pipeline; there is no second build system. For a static app, APCO builds the source and exports the configured publishDirectory. CLI and GitHub Actions v0 static uploads keep their existing prebuilt-static behavior.

For a monorepo binding, APCO keeps the whole repository as build context but resolves the app's build, start, Dockerfile, and publish paths from the selected root. <root>/apco.yml takes precedence. A repository-root apco.yml is a fallback only when its source.rootDirectory exactly matches the binding.

Optional watch paths are inclusive and repository-relative. They gate exact Production pushes and open-PR Preview updates, including shared packages such as packages/ui/**. A blank list preserves the original every-change behavior. APCO skips only when GitHub supplies a complete changed-file list with no match; errors and truncated lists fail open. PR close cleanup is never skipped.

GitHub App v1 or GitHub Actions v0?

GitHub App v1GitHub Actions v0
Source credentialShort-lived installation token minted at fetch timeOne-project ci:deploy token stored as an Actions secret
Production triggerServer-verified exact branch pushGenerated workflow trigger and job guard
PR PreviewsOne isolated Preview per project + PROne shared project Preview slot
Later PR commitsReplace only that PR's PreviewReplace the shared Preview
PR closeRoute/container cleanupNo close cleanup
Fork PRsExact-SHA maintainer approval, no secrets before approvalSkipped
StatusGitHub Check plus sticky PR commentActions job/summary plus sticky comment
Workflow or secret managementNoneYou add the workflow and APCO_TOKEN secret

Choose the App for repository-native automatic deployments and isolated PR environments. Keep Actions v0 when deployment belongs inside an existing CI graph or needs a custom pre-deploy job sequence.

Troubleshooting

StatusWhat to check
Installation suspended or deletedRestore/manage the installation on GitHub, or reconnect another installation.
Repository unavailableEnsure the repository is still selected for the installation.
Permissions out of dateAccept the App permission update on GitHub.
Push did not deployConfirm automatic deploys are enabled, the full pushed branch exactly matches the selected Production branch, and at least one changed file matches the configured watch paths.
Preview limit reachedClose an old PR/retire its Preview or change to a plan with more active PR Previews.
Fork approval became staleReview the new head commit and approve its newly displayed SHA.
Check/comment delayedThe APCO deployment remains authoritative; reporting retries independently.

APCO Cloud — ship apps with one command.