Skip to content

AmoreComputer/release-action

Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 

Repository files navigation

Amore Release Action

Build, sign, notarize, and publish a macOS app release via the Amore CLI, in one GitHub Actions step.

The action installs the Amore CLI on the runner, imports your Developer ID certificate, then runs amore release: archive, code sign, DMG, notarize, Sparkle sign, and upload.

Quick start

Copy this into .github/workflows/release.yml and fill in your scheme, runner, and Xcode. Pushing a v* tag ships a stable release; use a manual run to publish to a channel like beta.

name: Release
run-name: Release ${{ github.event.repository.name }}${{ inputs.channel && format(' ({0})', inputs.channel) || '' }}

on:
  push:
    tags: ['v*']
  workflow_dispatch:
    inputs:
      channel:
        type: choice
        default: alpha
        options:
          - alpha
          - beta
          - stable
        description: Channel for manual runs (stable = no channel)
      build-number:
        type: string
        default: auto
        description: Build number ("auto", "timestamp", or an integer)
      marketing-version:
        type: string
        default: ""
        description: Override marketing version (e.g. 1.2.3)

concurrency:
  group: amore-release
  cancel-in-progress: true

jobs:
  release:
    runs-on: macos-26
    steps:
      - uses: actions/checkout@v4

      - uses: AmoreComputer/release-action@v1
        with:
          # Uncomment to pin Xcode to what your project builds with, so a runner
          # image update can't drift the default to a version that breaks your
          # build. Leave commented to use whatever the runner ships.
          # xcode-path: /Applications/Xcode_16.app
          scheme: YourScheme
          codesign-identity: ${{ secrets.CODESIGN_IDENTITY }}
          dev-id-cert-p12: ${{ secrets.DEV_ID_CERT_P12 }}
          dev-id-cert-password: ${{ secrets.DEV_ID_CERT_PASSWORD }}
          sparkle-private-key: ${{ secrets.SPARKLE_PRIVATE_KEY }}
          asc-api-key-id: ${{ secrets.ASC_API_KEY_ID }}
          asc-api-issuer: ${{ secrets.ASC_API_ISSUER }}
          asc-api-key: ${{ secrets.ASC_API_KEY }}
          amore-token: ${{ secrets.AMORE_TOKEN }}
          channel: ${{ inputs.channel }}
          build-number: ${{ inputs.build-number || 'auto' }}
          marketing-version: ${{ inputs.marketing-version }}
          # Leave false to use your account default: Amore+ ships a clean DMG,
          # free accounts always ship the "Built with amore.computer" watermark.
          # Set true only if you want to keep the watermark.
          watermark: false
          # --- Self-hosted S3 hosting only (uncomment if not using Amore hosting) ---
          # s3-bucket: ${{ vars.AMORE_S3_BUCKET }}
          # s3-region: ${{ vars.AMORE_S3_REGION }}
          # s3-public-url: ${{ vars.AMORE_S3_PUBLIC_URL }}
          # s3-endpoint: ${{ vars.AMORE_S3_ENDPOINT }}
          # s3-path-prefix: ${{ vars.AMORE_S3_PATH_PREFIX }}
          # s3-appcast-path: ${{ vars.AMORE_S3_APPCAST_PATH }}
          # aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          # aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

Multi-channel (alpha / beta / stable)

Prefer to drive the channel off the trigger instead of a manual flag? This variant publishes:

  • alpha on every push to main,
  • beta on any version tag containing beta (e.g. v1.2.3-beta),
  • stable on any other version tag (e.g. v1.2.3),
  • and lets a manual run pick alpha, beta, or stable (stable = no channel).

A small step derives the channel from the event. It's a step rather than an inline expression because a tag can't be mapped to the stable channel inline: GitHub treats the empty channel string as falsy, so startsWith(github.ref, 'refs/tags/') && '' falls through the || chain and a stable tag ends up mislabeled. Same secrets as above.

name: Release
run-name: Release ${{ github.event.repository.name }} ${{ github.ref_type == 'tag' && github.ref_name || format('({0})', github.event_name == 'workflow_dispatch' && inputs.channel || 'alpha') }}

on:
  push:
    branches: [main]      # push to main    -> alpha
    tags: ['v*']          # tag v1.2.3-beta -> beta
                          # tag v1.2.3      -> stable
  workflow_dispatch:
    inputs:
      channel:
        type: choice
        default: alpha
        options:
          - alpha
          - beta
          - stable
        description: Channel for manual runs (stable = no channel)
      build-number:
        type: string
        default: auto
        description: Build number ("auto", "timestamp", or an integer)
      marketing-version:
        type: string
        default: ""
        description: Override marketing version (e.g. 1.2.3)

concurrency:
  group: amore-release
  cancel-in-progress: true

jobs:
  release:
    runs-on: macos-26
    steps:
      - uses: actions/checkout@v4

      # push to main -> alpha; tag containing "beta" -> beta; any other v* tag -> stable.
      - name: Resolve channel
        id: ctx
        env:
          EVENT: ${{ github.event_name }}
          REF_TYPE: ${{ github.ref_type }}
          REF_NAME: ${{ github.ref_name }}
          INPUT_CHANNEL: ${{ inputs.channel }}
        run: |
          set -euo pipefail
          channel=""
          if [ "$EVENT" = "workflow_dispatch" ]; then
            if [ "$INPUT_CHANNEL" != "stable" ]; then channel="$INPUT_CHANNEL"; fi
          elif [ "$REF_TYPE" = "branch" ]; then
            channel="alpha"
          elif [ "$REF_TYPE" = "tag" ]; then
            case "$REF_NAME" in *beta*) channel="beta" ;; esac
          fi
          echo "channel=$channel" >> "$GITHUB_OUTPUT"
          echo "Resolved channel='${channel:-stable}'"

      - uses: AmoreComputer/release-action@v1
        with:
          # xcode-path: /Applications/Xcode_16.app   # pin to avoid runner drift
          scheme: YourScheme
          codesign-identity: ${{ secrets.CODESIGN_IDENTITY }}
          dev-id-cert-p12: ${{ secrets.DEV_ID_CERT_P12 }}
          dev-id-cert-password: ${{ secrets.DEV_ID_CERT_PASSWORD }}
          sparkle-private-key: ${{ secrets.SPARKLE_PRIVATE_KEY }}
          asc-api-key-id: ${{ secrets.ASC_API_KEY_ID }}
          asc-api-issuer: ${{ secrets.ASC_API_ISSUER }}
          asc-api-key: ${{ secrets.ASC_API_KEY }}
          amore-token: ${{ secrets.AMORE_TOKEN }}
          # false = account default (Amore+ clean, free watermarked); true keeps the watermark.
          watermark: false
          channel: ${{ steps.ctx.outputs.channel }}

Secrets

Set these in your repo under Settings → Secrets and variables → Actions.

Amore-managed hosting (the common case) needs:

Secret What it is
AMORE_TOKEN Scoped Amore API token.
CODESIGN_IDENTITY Developer ID Application identity string.
DEV_ID_CERT_P12 base64 of your Developer ID Application .p12.
DEV_ID_CERT_PASSWORD Password for that .p12.
SPARKLE_PRIVATE_KEY base64 Ed25519 Sparkle signing key.
ASC_API_KEY_ID App Store Connect API key ID (for notarization).
ASC_API_ISSUER App Store Connect API issuer ID.
ASC_API_KEY base64 of the ASC .p8 key.

Self-hosting on S3 / R2 / MinIO instead of Amore hosting? Also set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY, and uncomment the s3-* inputs.

Inputs

scheme is the Xcode scheme to build. channel picks the release channel (e.g. alpha, beta); empty ships stable. Everything else has a sensible default; see action.yml for the full list, including path, release-notes, critical, draft, phased-rollout, watermark, no-dmg, provisioning-profile, and the s3-* hosting inputs.

build-number defaults to auto: one past the highest build number the destination already has published. Use timestamp if you'd rather not depend on the destination being reachable, or pass an explicit integer.

provisioning-profile (base64 of a .provisionprofile) is only needed if your app's entitlements require one, e.g. Associated Domains.

Outputs

version, build-number, bundle-id, download-url, latest-url.

Versioning

Pin the major tag @v1 to get non-breaking fixes automatically. Breaking changes ship under @v2, which you opt into by editing the ref.

About

No description, website, or topics provided.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors