GitHub releases
There are two ways to publish from GitHub. Both keep building and signing in your own CI.
The AppsXi GitHub App
Connect GitHub in Developer → GitHub, choose the repositories, then pick a repository for each app (your app → GitHub releases). From then on, every release you publish on GitHub becomes an AppsXi build:
- AppsXi takes the installers attached to the release (
.dmg,.pkg,.zip,.msix,.msi,.exe) and skips blockmaps, checksums, update YAML files and source archives. Optional filename globs (for example*-universal.dmg) pick one file per platform. - The tag is the version (
v2.3.1→2.3.1), the release notes become the changelog, and prereleases go to the beta channel (or are ignored, if you choose). - Turn off automatic submission to review each release and press Publish yourself.
- Drafts are ignored. Each file is checked exactly like an upload, and its signature must match your pinned identity.
The App asks for read-only access to contents and metadata, plus release events. It cannot push to your repositories. AppsXi fetches each file with a short-lived token limited to that one repository.
Your release workflow only needs to build, sign, notarize and attach the installers to the release.
With appxi init (no GitHub App)
npx appxi init --app my-app writes .github/workflows/appxi-publish.yml. It runs on release: published, builds with your stack's usual commands, then runs appxi publish --wait. Prereleases go to the beta channel.
Add a repository secret APPXI_TOKEN with a developer API token that has builds:write. Your signing certificates stay in your own secrets; AppsXi never sees them.
The publish action
on:
release:
types: [published]
permissions:
contents: read
jobs:
publish:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
# build, sign, notarize and staple here
- uses: appxi/publish-action@v1
with:
token: ${{ secrets.APPXI_TOKEN }}
app: my-app
files: dist/*.dmg| Input | Default | |
|---|---|---|
token | Developer API token. | |
app | Your app's slug. | |
files | Installer file(s); globs are expanded. | |
version | release tag without v | |
channel | beta for prereleases, else stable | |
notes | release body | |
ed-signature | Sparkle signature for a single macOS file. | |
wait | true | Fail the job when a build is denied. |
cli-version | latest |
Output: build_id.
Security
Release titles and bodies are untrusted input. The action and the generated workflow pass them through environment variables and never interpolate ${{ }} expressions into shell scripts, so a crafted release cannot run commands on your runner.