Skip to content

GitHub Action reference

betadrop-app/upload-action publishes a build from a workflow and returns its install link. It is a composite action: it installs @betadrop/cli and runs betadrop publish --ci, so CI behaves exactly like a laptop and there is one upload client to keep true. For complete Gradle and Xcode workflows, read the GitHub Actions guide instead. This page is the input table.

The minimum step

Add after your build step
- name: Publish to BetaDrop
  id: betadrop
  uses: betadrop-app/upload-action@v1
  with:
    file: app/build/outputs/apk/release/*.apk
    token: ${{ secrets.BETADROP_TOKEN }}

Two required inputs and nothing else. Create the token under Settings → Developer → API tokens in the BetaDrop dashboard, then store it as a repository or organisation secret. Never inline in the workflow file, where it is readable by anyone who can read the repo and is captured in every fork.

Pin the tag. @v1 tracks backwards-compatible releases of the major version; pin a full version such as @v1.2.0 to freeze it entirely. A branch reference is not a supported way to consume this Action.

Inputs

Inputs accepted by betadrop-app/upload-action
InputRequiredDescription
fileYesPath to the build artifact (.ipa or .apk). A glob such as app/build/outputs/apk/release/*.apk is allowed, but it must match exactly one file.
tokenYesA BetaDrop API token (bd_live_…), passed from a secret: ${{ secrets.BETADROP_TOKEN }}.
nameNoOverride the build name shown on the install page. Defaults to the app's own name, read out of the archive.
notesNoRelease notes for this build. The commit message is the usual choice. Default: empty.
standing-linkNoA standing link slug to point at this build once it is live, so that fixed URL keeps serving whatever CI published last. Claim the standing link first: a free account holds one, Pro and Studio up to 50. A standing link that cannot be used fails the step before anything is uploaded. Needs @betadrop/cli 0.3.0 or newer, which the step checks and names. The older name for this input, channel, stays accepted indefinitely.
expires-in-daysNoStop the install link working after this many days, clamped to the plan's maximum. Needs @betadrop/cli 0.4.0 or newer; the step names the installed version if it is older.
max-downloadsNoStop the link after this many downloads. CLI 0.4.0+.
max-devicesNoStop the link after this many different devices. With more than one limit set, the link stops at whichever comes first. CLI 0.4.0+.
inspectNoCheck the build will install from a link before uploading it — profile type and expiry, bundle ID, signing, testOnly — and fail the step with nothing uploaded if it will not. Default: false. CLI 0.4.0+.
comment-on-prNoPost the install link as a comment on the pull request, editing that same comment on every later push instead of adding another. Requires pull-requests: write on the job. Skipped with a notice on events that have no pull request, so a workflow that runs on both push and pull_request needs no condition. Default: false.
github-tokenNoThe token used for that comment. Defaults to the workflow's own ${{ github.token }}; override it only if the comment should come from a different account.
cli-versionNoVersion of @betadrop/cli the Action installs. Defaults to latest; pin it for reproducible pipelines.

That is the complete list. There is no input for platform or visibility: platform is inferred from the file. Expiry can be set here, with the three limits above, or changed on the build in the dashboard afterwards.

Outputs

Outputs produced by betadrop-app/upload-action
OutputDescription
install-urlThe OTA install link for the uploaded build. Read it as ${{ steps.<id>.outputs.install-url }}, which requires giving the step an id.
standing-link-urlThe standing link's URL, when standing-link was set. Empty otherwise. This is the one to hand out, or to put behind a download button in a README: it still points at the newest build next week, which the per-build link above will not. channel-url is the older name for the same value and still works, so a workflow already reading it needs no edit.

A link nobody sees is a wasted upload. The Action already writes it to the run summary on every green build, and comment-on-pr puts it on the pull request without a second step. Use the output when you want it somewhere else — chat, a release note, a downstream job. The integrations guide has those as copy-ready steps.

A complete job

.github/workflows/beta.yml
name: Beta
on:
  push:
    branches: [main]

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # …your existing build steps produce the .apk or .ipa here…

      - name: Publish to BetaDrop
        id: betadrop
        uses: betadrop-app/upload-action@v1
        with:
          file: app/build/outputs/apk/release/*.apk
          token: ${{ secrets.BETADROP_TOKEN }}
          name: MyApp ${{ github.ref_name }}
          notes: ${{ github.event.head_commit.message }}

      - name: Publish the link to the run summary
        run: echo "${{ steps.betadrop.outputs.install-url }}" >> "$GITHUB_STEP_SUMMARY"

The build steps are deliberately elided: whatever already produces your .apk or .ipa stays exactly as it is, and this Action is appended to it. If you do not have those steps yet, the guide carries full Gradle and Xcode jobs, including the export-options detail that trips up iOS runs.

When it fails

Failure modes of betadrop-app/upload-action
SymptomCause and fix
"No file matches …"The path or glob matched nothing on the runner. Check that the build step runs before this one and writes where you think — a step that lists the output directory is the fastest way to find out.
"… matches N files"The glob matched more than one build. This is a deliberate failure rather than an arbitrary pick: silently uploading whichever file sorted first is worse than stopping. Narrow the pattern so exactly one build matches.
"Publish produced no output"The upload did not complete. The CLI's own error is above this line in the log. An invalid or revoked token and a file over the size limit are the two common causes.
"… has no --channel flag"standing-link (or its channel alias) was set, but the @betadrop/cli the step installed predates 0.3.0, where that flag landed. The message names the version it got and the version it needs. Set cli-version to 0.3.0 or newer, or 0.4.0 or newer if the step also uses the expiry limits or inspect.
The pull-request comment never appearsDeliberately a warning rather than a failure — the build published, and losing it to a missing permission would be the worse trade. The usual cause is the job lacking pull-requests: write; the other is an event with no pull request, reported as a notice. Runs from forked pull requests get a read-only token and cannot comment at all.
Fails only on pull requests from forksNot the Action. GitHub does not expose repository secrets to workflows triggered by a pull_request event from a fork, so the token arrives empty. Publish on push to your own branches, or use an event that runs in the base repository's context.

Notes on how it behaves

  • Node is assumed, not installed. Every GitHub-hosted runner image ships Node, so the Action needs no setup step. On a self-hosted runner without Node 18 or newer, add one — the Action installs the CLI with npm install -g.
  • Inputs are passed through the environment. They are not interpolated into the shell script, so a filename or a commit message containing shell metacharacters cannot inject a command. This is the standard composite-action footgun and it is worth knowing it has been avoided.
  • Permissions, only if you comment. Publishing needs no permissions block at all — the upload authenticates with your BetaDrop token and never touches GITHUB_TOKEN. Setting comment-on-pr is the one exception: that step writes to the pull request, so the job needs pull-requests: write. If it is missing the step warns and the run stays green, because a published build should not be lost to a permission.
  • It is the CLI. Anything documented on the CLI page about extensions, the ZIP magic-byte check, size limits or error behaviour applies here unchanged, because it is literally the same program running.
  • The repository. Source and releases live at github.com/betadrop-app/upload-action. Note the namespace: betadrop-app, not betadrop, which is an unrelated account. Issues and pull requests are read there; a star is how the next team looking for this finds it rather than writing the step themselves.