Pre-merge QA workflow

Use a branch install link to let QA test a change before it merges into develop or main. When a fix is uploaded, testers can reopen the same link.

This guide covers branch uploads, environment checkpoints and private tester access, with a CI example you can adapt to your repository.

The problem

A mobile change often needs testing on a device before merge. A typical review looks like this:

  1. Developer opens a PR for feature/payments.
  2. They trigger a custom GitHub Action that builds and uploads the artifact somewhere.
  3. The action posts a Slack message with a link.
  4. The developer moves the Linear / Jira ticket to "QA".
  5. A tester picks it up, installs the build, tests it.
  6. If it passes, the ticket goes to "Ready to merge". The PR is approved and merged.
  7. If it fails, the developer fixes the bug, re-triggers the action, and step 4 repeats.

When each upload has a new URL, the link in the ticket can fall behind. A stable branch link gives testers one place to find the latest build, including fixes made during review.

How buildtree fits

buildtree organises every build by (env, branch). The CLI accepts both as flags:

buildtree upload ./app.apk --env dev --branch feature/payments

The CI invocation never changes. It uploads under the same (env, branch) pair every time. The dashboard groups uploads by branch and serves a stable URL per branch:

/install/folder/<project>/dev/feature/payments

That URL points at the latest build for the environment and branch. Add it to the QA ticket once; subsequent uploads update the build served at that address.

The flow, end to end

1. Developer opens PR for feature/payments.

2. CI runs (or developer runs locally) and uploads:

   buildtree upload ./app.apk --env dev --branch feature/payments
   buildtree upload ./app.ipa --env dev --branch feature/payments

3. Developer pastes one URL into the ticket:

   https://buildtree.sh/install/folder/<project>/dev/feature/payments

   (or scans the QR for testers in person)

4. QA installs from that URL, tests, marks the ticket as approved
   or "needs fixes" in Linear / Jira.

5. If fixes are needed: developer pushes a commit, CI re-uploads to
   the same (env, branch) pair, QA refreshes the same URL.

6. Once approved, PR merges to develop. CI uploads the merged build
   as the develop checkpoint:

   buildtree upload ./app.apk --env dev

   (no --branch flag; this is the env's checkpoint, see below)

7. /install/folder/<project>/dev now serves the latest release-ready
   build. That URL is what you give to internal stakeholders, demo
   reviewers, anyone who wants "the latest from develop".

Steps 1–6 cover feature review. After the merge, the environment link gives the team access to the latest checkpoint build.

Checkpoint vs branch uploads

The model has two upload modes, distinguished by whether you pass --branch:

  • Branched upload (--env dev --branch feature/payments): a pre-merge preview build for that branch. Lives in the Branches section of the dashboard. Never affects the env's "latest".
  • Checkpoint upload (--env dev, no --branch): the env's latest release-ready build. Most-recent branchless iOS + most-recent branchless Android together form the "Latest dev" pair surfaced at the top of the env tab.

This maps directly onto trunk-based development: feature branches are branched uploads, every merge to develop produces a new checkpoint upload. The branch URL gets QA in the feature loop; the checkpoint URL gets internal stakeholders the latest passing build.

Add distribution to CI

Keep your existing build job and add buildtree upload after it succeeds. Pass the branch name so uploads appear under the right branch. Share the resulting folder URL in your ticket or pull request.

Build retention follows your plan. Deleting a Git branch does not replace build cleanup; manage builds in the dashboard.

CI snippet

GitHub Actions example that uploads under the current branch:

- name: Distribute to buildtree
  env:
    BUILDTREE_TOKEN: ${{ secrets.BUILDTREE_TOKEN }}
  run: |
    npm install -g @buildtree/cli
    BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME}}"
    if [ "$BRANCH" = "develop" ] || [ "$BRANCH" = "main" ]; then
      buildtree upload ./build/app.apk --env dev
    else
      buildtree upload ./build/app.apk --env dev --branch "$BRANCH"
    fi

Pull requests upload as branched; merges to develop or main upload as the env checkpoint. Full example workflows: see GitHub Actions.

Collect feedback and record approval

Testers can send bugs, suggestions and screenshots from the install page. Feedback is attached to the build and appears in the project dashboard. See Tester feedback.

Record the final QA approval in your ticket or pull request; buildtree does not currently provide a separate build approval status.

See also

  • Concepts: the env + branch + checkpoint model in detail.
  • Install URLs: pinned, folder, and release URL flavours.
  • Install access: scoping branch URLs to internal testers when the project is private.
  • GitHub Actions: full CI workflow examples.

Last updated

Pre-merge QA workflow | buildtree docs