Install from a repository
Build any GitHub repository with a wrangler config in your own account, public or private with a read-only token, review what it declares, and install it. Also, build a catalog app from source at another commit. Needs Workers Paid and sandbox builds.
The catalog lists apps that someone packaged and checked. You can also install a Workers project that is not in the catalog, straight from its GitHub repository (public, or private with a GitHub access token), the way the "Deploy to Cloudflare" button would: your sandbox Worker builds it in a container in your own account, you review what the build declares, and then Appflare installs it like any other app, with resources it creates and records, updates with a snapshot and a rollback, and an uninstall that cleans up.
Such an install is marked Not from the catalog, not checked wherever it appears, and
is named owner/repo so two repositories of the same name stay apart.
Nobody reviewed its code for you, and Appflare never updates it on its own.
What you need
- Sandbox builds turned on in Settings > Building apps > Build in your account, which also means Workers Paid and R2 on the account. See Sandbox builds. If the card offers Update sandbox, update first: older sandbox Workers cannot build from a repository.
- A repository on github.com with a
wrangler.json,wrangler.jsoncorwrangler.tomlat its root (or only a template of one, such aswrangler.toml.example, which the build copies to its real name), and a lockfile (pnpm-lock.yaml,package-lock.json,yarn.lockorbun.lock) when it has apackage.json. A private one also needs a GitHub access token that can read it.
Start a build
On the Catalog page, admins see From a repository. Enter:
- Repository: a GitHub URL such as
https://github.com/owner/repoor justowner/repo. A URL that points at a branch or commit (.../tree/<branch>,.../commit/<sha>) fills in the next field. - Branch, tag or commit (optional): the repository's default branch when empty. A branch or tag can be checked for changes later; a commit never moves. A commit is accepted whenever GitHub serves it for that repository, which includes commits that exist only in its forks, so pin commits from a branch you trust.
- Build command: Work it out runs the project's
package.jsonbuildscript with the package manager its lockfile names, if it has one. Run this command takes one plain command (no pipes, quotes or variables), and None runs nothing besides the wrangler config's ownbuild.command, aswrangler deploywould.
Confirm the cost and choose Build for review. Before a container starts, Appflare reads the repository's branches and tags from GitHub, so a misspelled branch, or a private repository none of your GitHub access tokens can read, is refused at once, and the build is pinned to the commit the branch points at right then.
The build runs as a job, and its log opens. In the container, the sandbox Worker:
- Clones the repository at that commit.
- Reads the root of the checkout: the lockfile for the package manager, the wrangler
config, the build command, and the secrets
.dev.vars.example(or.env.example) lists, one perNAME=line, with the comment above each as its help. A secret whose comment says it is optional is optional in the install form. The wrangler config is read with wrangler's own reader, whatever its format: each of its plain vars becomes a setting you can change, each secret it lists insecrets.requiredis asked for too (never as optional), and the sections Appflare cannot deploy are noted. - Installs the dependencies with install scripts disabled, then runs the build command
and
wrangler deploy --dry-runthrough the same packer the catalog uses, in an environment that holds no credentials. - Stores the result, an unsigned artifact, in the sandbox Worker's bucket, and checks every file of it.
Nothing is deployed yet. A build of a small project takes a minute or two; the cost is the container time, as for any sandbox build.
Review the build
When the build finishes, its log offers Review. The review page shows:
- Source: the repository, the branch or tag, the commit, the version Appflare gave
it (the tag without its
v, or0.0.0-<date>.<commit>), the build command and where it came from, and the container image that built it. - What it declares: the resources the install would create (KV namespaces, D1 databases, R2 buckets, queues, Vectorize indexes, Durable Object classes, Workflows), every binding of the Worker, its cron triggers, and the secrets and settings the install form will ask for.
- Runs on: the Cloudflare services it uses, and whether this account offers each, as on a catalog app's page.
- Why it cannot be installed, when that is the case, in the words the install would use. Appflare installs self-contained Workers only, so it refuses a build with a Hyperdrive binding (a repository has no catalog manifest to declare its database), an mTLS certificate binding, a service binding or Durable Object binding to another Worker, or a wrangler config that uses Containers, dispatch namespaces, Tail Workers, Pipelines or Secrets Store secrets.
Below the review is the usual install form. Installing starts the ordinary install job with this build as its artifact: it is read back from the bucket and checked against what the review showed before anything is created. A build installs once. Throw away deletes a build you do not want, and its files. A build nobody installs, updates from or throws away is thrown away by Appflare 7 days after it was built (a failed one, 7 days after it failed), so the sandbox Worker's bucket does not keep it forever. A build an app or one of its snapshots uses is never thrown away.
If the install fails
Install again on the app's page (also on Home and on the failed job's log) opens the review of the build it was installed from, with the install form filled in from last time. Installing removes what the failed install left in your account, then installs the same build again: nothing is built twice, and the build's files stay in the bucket for the new install. See Installing apps for what is filled in and what you enter again.
If that build is gone (turning sandbox builds off deletes every build), the review says so and offers Build again: the same repository at the same branch, tag or commit, with the same build command. If a branch has moved on, that is its newest commit. Once it is built, its review opens with the form filled in from the failed install.
Build a catalog app from source
A catalog app's page has Advanced: build from source at a commit below its install form, for admins with sandbox builds on. It builds the app's own repository at the branch, tag or commit you choose, with the catalog's secrets, settings and build command. The review also says which bindings differ from the catalog's release.
The install is marked Built from source, not checked: the catalog checked its own release, not your commit. It is not updated automatically. When the catalog has a newer version, updating from the catalog puts its checked release back; you can also rebuild from source as below.
Check for changes
The Overview tab of an app installed from a repository (or built from source) has a Source card. Check for changes reads the newest commit of the branch or tag it was built from and says whether it moved. Rebuild and update builds that commit for review, with the same build command as before. The review lists any secrets the new build introduces and asks for them, and says when the new version cannot be checked on a preview first. Update then runs the ordinary update: a snapshot of the Worker and of each D1 database, the preview check, promotion, and a rollback to the previous build if you need it.
Appflare never checks for changes or rebuilds on its own, and automatic updates do not apply to these installs.
Private repositories
A private repository needs a GitHub access token that can read it. Tokens are listed and managed in Settings > Building apps > GitHub access, which only admins see; members get nothing about them. With sandbox builds on, an admin adds one:
- Choose Add token, then Create it on GitHub. It opens GitHub's page for a new fine-grained personal access token with the permissions filled in: Contents: Read-only, plus Metadata: Read-only, which GitHub adds to every token. Pick the owner and Only select repositories, choose the repositories to install, and an expiry. Give it no other permission.
- Back in Appflare, enter a Label and paste the token.
- Under Use it for, keep Builds of private repositories ticked. Repositories
is optional: leave it empty to use the token for any private repository, or name
repositories (
owner/repo, orowner/*for all of an owner's) to use it only for those.
You can add several tokens, for example one per organisation. When a repository is not
public, Appflare tries only the tokens for builds of it, the most specific first: those
naming the repository, then those naming its owner, then *, then those that name no
repositories. A token that names other repositories only is never sent for it. The token
that reads it is the one the build clones with, and Check for changes and Rebuild
and update find it the same way. The list shows what each token is used
for (for example Builds of acme/* or Appflare release downloads) and when it was
last used.
Appflare stores each token as a secret on the sandbox Worker, the same way it keeps a self-deploying app's token, and records only its label, what it is used for and its last use. It never shows a token again. In a build, only the commands that fetch the repository get the token, as the password of the https clone; the dependency install and the build command, which run the repository's own code, never see it, and the job log never shows it. The token is sent to github.com and api.github.com only.
Delete removes the token from the sandbox Worker. Apps already installed keep running, but a private repository no remaining token covers cannot be rebuilt. Revoke the token on GitHub as well. Disabling sandbox builds deletes the sandbox Worker, and every token with it.
Appflare release downloads
Appflare's own repository on GitHub is public, so updating Appflare needs no token. Without one, Appflare finds new versions on github.com and asks GitHub's API only for release notes, because GitHub allows 60 API requests an hour to each address without a token and Cloudflare Workers share their addresses. If release notes are slow to appear, tick Appflare release downloads under Use it for on a token: the update check then uses the API with the token's own, much higher limit. A token for release downloads alone needs no repositories, and untick Builds of private repositories so builds never try it.
Appflare then reads its own releases, and nothing else, with that token (for update
checks, self-updates and updating the sandbox Worker) instead of the GITHUB_TOKEN
secret, which stays the fallback. Only one token is used for release downloads: ticking
it on a new token moves it from the old one. If the old token was for nothing else, the
list shows it as Not used, and you can delete it. Turning sandbox builds on for the first
time cannot use it, since the token is kept on the sandbox Worker being created.
If the build fails
The job log and the review page name the step that failed and quote the end of its output:
- checkout: the repository, branch or commit does not exist, or the repository is private and the GitHub access token cannot read it (it expired, was revoked, or does not cover the repository).
- detect: there is no wrangler config at the root, or no lockfile next to
package.json. A monorepo whose Worker sits in a subdirectory cannot be built this way yet. - install: the locked dependencies did not install. The lockfile may be out of date
with
package.json. - build: the build command failed. Choose another one, or None.
- pack: wrangler could not bundle the Worker, or the project binds a Vectorize index, whose size wrangler's config does not say. Such a project needs a catalog entry.
A build whose container could not start or went away runs once more by itself. Nothing is deployed by a build, so a failed one leaves nothing to clean up but its log; Throw away deletes that too.
What is sent
The anonymous report records that a build, install or update of this kind ran and how it ended, never the repository, its name, or its version.