GitHub App deployments

This guide shows how to deploy a repository with a GitHub App. GitHub sends push and pull request events to the control node. The control node deploys the services in up.yaml.

No GitHub Actions runner is used. A deploy does not use Actions minutes while a build runs.

Before you start

You need:

  • a control node that GitHub can reach over HTTPS;
  • a node with the deploy role;
  • an up.yaml file at the root of the repository;
  • permission to create a GitHub App on your account or organization.

1. Set the public URL (optional)

The plugin must know the public URL of the control node: the address that GitHub and browsers use to reach it. Up resolves it in this order:

  1. public_url in the [plugins.github] table.
  2. The top-level public_url in the control node config.
  3. node_url, when it is not a loopback address.

A loopback node_url (127.0.0.1 or localhost) is refused, because the GitHub webhook must be reachable from GitHub. Set a public URL when the control node is behind a proxy or tunnel and its node_url is loopback. Open ~/.config/up/config.toml on the control node and add:

public_url = "https://up.example.com"

Replace the URL with the URL of your control node. Use https://. Use http://localhost:7070 only for a local test, and set it explicitly, because the loopback node_url fallback is refused.

To override the public URL for GitHub alone, use the [plugins.github] table instead:

[plugins.github]
public_url = "https://up.example.com"

The GitHub plugin is registered when the control node starts, so you can go straight to the next step when node_url is already public. Use one of the tables above otherwise.

2. Create the App

Run:

up plugin github init

The command prints a URL and opens your browser.

  1. On the GitHub page, click Create GitHub App. GitHub creates the App from a prefilled template. The template sets the permissions and the events that up needs.
  2. Wait in the terminal. The command writes the App settings to the control node config. It writes the private key to ~/.config/up/plugins/github/app.pem with mode 0600. It reloads the plugin. You do not restart the control node.
  3. Continue when the command reports that the App is configured. The command checks the control node, so it finishes by itself.

The App is public. Any account or organization can install it. GitHub cannot change a public App back to private.

3. Install the App

Run:

up plugin github install

The command opens the install page. Select the account or organization. Select the repositories. Click Install.

To see where the App is installed, run:

up plugin github installations

4. Remove the old workflows

If you copied the up CI workflow templates before, remove them. Delete .github/workflows/deploy.yml and .github/workflows/preview.yml. The App now sends the events that the workflows sent before. The CI templates and the up deploy action are no longer part of up; the GitHub App is the GitHub deployment path.

5. Check the result

Push a commit to the default branch. Up deploys the environment whose branch is the default branch. Open the repository on GitHub. GitHub shows a check run for the commit, and a deployment with the URL of the first service.

For a pull request, up deploys the environment pr-<number> only when the environment for the base branch enables previews. Up writes one comment on the pull request. When the pull request closes, up removes the environment.

What up does with each event

  • A push to a branch deploys the environment declared for that branch.
  • A push to an undeclared branch does not deploy.
  • A pull request deploys pr-<number> as a preview only when the environment for the base branch declares previews.
  • A closed pull request removes the preview environment.
  • A re-requested up deploy check run re-runs the deploy it belongs to.

Re-run a deploy

After a failed deploy, open the up deploy check run and click Re-run. Up re-runs the same deploy: the same commit, the same environment, the same check run, and the same pull request comment. No new comment is posted.

The control node must run a build that includes the check run support, or the re-request is ignored. A re-run repeats the deploy with the same commit and the same environment, so it helps when the failure was environmental (a bad credential, a flaky build) rather than a problem in the commit itself.

The environments block in up.yaml declares the branches, the environment names, and the preview policy. The top-level previews.base_domain sets the preview domain for every environment, and an environment can override it. See Environments and Preview environments.

Approvals

A deploy starts as soon as GitHub sends the event. A GitHub environment approval rule does not apply, because no workflow job runs. To approve production changes, protect the default branch. Then a change reaches production only through a reviewed pull request.

Limits

  • The installation token is valid for one hour. A build that runs longer than one hour cannot push the image. Use a registry credential that lasts longer for very long builds.
  • GitHub Container Registry does not accept a GitHub App installation token for registry authentication, and an App cannot create a personal access token. Up therefore never injects a registry credential on the App path. A config reference such as $GHCR_TOKEN resolves from the control node’s environment when you set it; otherwise it resolves to empty and the apply keeps the registry password already stored on the control node. Set the credential once with up registry add, or export the variable on the control node to let the App manage the registry too.
  • GitHub can send the same event more than once. Up ignores a repeat event, so a retry does not start a second deploy.
  • Up runs one deploy at a time for the same repository and environment. A second push waits for the first to finish.
  • A pull request from a fork does not deploy. The App cannot read the fork.
  • Up handles only push and pull_request events. It ignores other events.

Set the values by hand

You can skip the browser and set the values yourself. Open ~/.config/up/config.toml and add:

[plugins.github]
app_id = 123456
private_key_path = "/etc/up/github-app.pem"
webhook_secret = "the-webhook-secret"
public_url = "https://up.example.com"

Restart the control node after you change the file.

For GitHub Enterprise Server, also set api_base_url to the API root, for example https://ghe.example.com/api/v3. Do not set it on github.com.

The values stay on the control node. The node config API cannot change them, so the private key and the webhook secret do not leave the machine.

To read more about plugins, see Plugins.