Skip to content

Install every pull request on a real phone

Add one input to the job that already builds your app and every pull request gets an install link in its own comment. The comment is edited in place on every later push, so a branch with forty commits still has exactly one BetaDrop comment, showing the build as it stands now.

A reviewer taps it and installs the branch they are reviewing. Screenshots in a pull request show what the author saw; a build shows what the reviewer can try.

The whole change

Two lines you do not already have: the permission, and comment-on-pr. The build steps are deliberately elided — keep whatever you build with today.

name: Build
on: [pull_request]

jobs:
  android:
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write        # required for the comment
    steps:
      # ... checkout, JDK, ./gradlew assembleRelease ...

      - uses: betadrop-app/upload-action@v1
        with:
          file: app/build/outputs/apk/release/*.apk
          token: ${{ secrets.BETADROP_TOKEN }}
          notes: ${{ github.event.pull_request.title }}
          comment-on-pr: true

The install URL is also written to the workflow run summary on every green build, with no extra step and no permission needed — so even a job that cannot comment still surfaces the link. The full input reference is in the Action docs.

This does not work on pull requests from forks

GitHub gives a workflow triggered by a pull_request event from a fork a read-only token and withholds repository secrets. The Action therefore cannot read your API token to upload, and could not post a comment even if it could.

This is GitHub's security model rather than a BetaDrop limitation, and it applies to every CI tool that needs a secret. If your repository takes outside contributions, the usual answers are pull_request_target or a maintainer-triggered workflow — both carry trade-offs worth understanding before you adopt them. On a private repository, or for branches pushed to the repository itself, none of this applies.

What changes when reviewers can install

  • Design review stops being a screenshot argument. A designer opens the branch on their own device, at their own text size, on their own OS version.
  • QA starts before merge. The build under test is the branch, not last night's main, so a regression is found while the change is still one reviewable diff.
  • Nobody asks for a build. The most common request in a mobile team — “can you send me a build of this?” — is answered before it is asked, by the pipeline that was already running.
  • The link dies on its own. A link lives 3 days by default, which is about the right lifetime for a branch. Nobody needs the build from a pull request that merged three weeks ago, and expiry means the file is deleted rather than archived.

When you want the opposite

Pull-request builds give every branch its own link, which is right for review and wrong for a QA channel. If what you need is one URL that always serves the current build — for a README button, a QA group, or a client who should never be sent a new link — that is a standing link, and the same Action sets one with the standing-link input. The two are complementary: a distinct link per pull request, and one standing link for whatever has merged.

Frequently Asked Questions

How do I get an install link on every pull request?

Add the BetaDrop Action to the job that builds your app, set comment-on-pr: true, and grant the job permissions: pull-requests: write. On every push to the branch the Action uploads the build and posts the install link as a comment on the pull request. It also writes the link to the run summary automatically, with no extra step and no permission needed.

Does it add a new comment on every push?

No. It edits the same comment in place on every later push, so a pull request with forty commits still has exactly one BetaDrop comment showing the current build. That behaviour is the default and is not configurable — comment spam on a long-running pull request is the fastest way to get a bot muted.

Does this work on pull requests from forks?

No, and the reason is GitHub's, not BetaDrop's. A workflow triggered by a pull_request event from a fork gets a read-only token and is not given repository secrets — so the Action cannot read your API token to upload, and could not post a comment even if it could. This affects every CI tool that needs a secret, not just this one. Public repositories taking outside contributions usually run build-and-comment on pull_request_target or on a maintainer-triggered workflow instead, both of which carry security trade-offs worth reading about before you adopt them.

What happens on a push that is not a pull request?

The upload runs normally and the comment step is skipped with a notice, not an error. A workflow that runs on both push and pull_request therefore stays green on the push half. The other documented failure is a job missing permissions: pull-requests: write, which is also reported as a notice rather than failing the build — the reasoning being that a build which uploaded successfully should not be marked red because a comment could not be posted.

Do reviewers need a BetaDrop account to install the build?

No. The comment carries an ordinary install link. A reviewer opens it on their phone and installs — no account, no companion app. On iOS the device still has to be covered by the provisioning profile the build was signed with, which is a property of your build rather than of the reviewer.

Will a pull request build fill up my storage?

Not for long. A link lives 3 days by default on the free tier and can be set up to 7 days; when it expires the file is deleted from storage rather than archived. Pull-request builds are exactly the case that default suits — nobody needs the build from a branch that merged three weeks ago. Free builds can be up to 500 MB.

Can the same link always point at the latest build?

Yes, but that is a different feature and a different use case. A standing link is one URL that you re-point at each new build, which is what you want for a QA channel or a README button that should always serve the current build. Pull-request builds want the opposite: a distinct link per pull request, so a reviewer installs the branch they are reviewing rather than whatever landed last. Standing links are on the Pro and Studio plans.

Does this work outside GitHub?

The comment behaviour is specific to the GitHub Action, because it posts through the GitHub API. The upload half works anywhere: the CLI publishes from any pipeline, and there are documented recipes for GitLab CI, Bitrise, Codemagic and fastlane. Posting the resulting link back into a merge request or a chat channel is then a step you write, using the install URL the CLI prints.

Put a build on your next pull request

Create an API token, add the two lines, open a pull request.

Part of: CI/CD Beta App Distribution