Muse Release Process: Building Android (APK/AAB) and iOS Binaries

The Muse release process triggers automated Android builds via GitHub Actions when you publish a new release, while iOS requires running a local shell script for simulator testing or manual Xcode commands to generate production IPAs.

The kkoshin/muse repository is a Kotlin Multiplatform project that packages a Compose Multiplatform app for both Android and iOS distribution. Whether you are shipping a signed APK to Google Play or testing an iOS build locally, the release pipeline relies on distinct workflows for each platform.

Android Release Workflow (APK and AAB)

The Android release process is fully automated through GitHub Actions and produces signed, production-ready artifacts.

Automated CI/CD Pipeline

The workflow defined in .github/workflows/package.yml listens for release events and executes six distinct stages:

  1. Trigger: Creating a new GitHub release automatically starts the workflow via the on: release event trigger.

  2. Build: The runner executes ./gradlew assembleRelease to compile the composeApp module. This generates an unsigned APK in release mode. For an Android App Bundle (AAB) instead, the command would be ./gradlew bundleRelease.

  3. Sign: The ilharp/sign-android-release GitHub Action signs the artifact using keystore credentials stored in repository secrets:

    • KEY_STORE_BASE64 (Base64-encoded keystore)
    • KEY_STORE_PASSWORD
    • ALIAS
    • KEY_PASSWORD
  4. Rename: The workflow strips the -signed suffix from the filename and moves the signed artifact to a signed/ subdirectory.

  5. Publish: The signed APK (or AAB) and the ProGuard mapping file are uploaded as a workflow artifact named release-artifacts, available for download from the Actions run page.

  6. Metadata: The fastlane/metadata/android directory contains Play Store screenshots, changelogs, and listing metadata that you manually update before distribution.

The release build configuration itself is defined in composeApp/build.gradle.kts, which specifies the signing configuration and release build type parameters.

Local Android Builds

For local development or manual releases, you can generate unsigned artifacts directly:


# Build APK

./gradlew assembleRelease

# Build Android App Bundle (AAB)

./gradlew bundleRelease

These commands output to composeApp/build/outputs/apk/release/ and composeApp/build/outputs/bundle/release/ respectively. You must then sign the artifact using jarsigner or Android Studio’s Generate Signed Bundle/APK wizard, ensuring you use the same keystore referenced in the CI secrets.

iOS Release Workflow

Unlike Android, the Muse repository does not include a fully automated CI workflow for iOS distribution. Instead, it provides a convenience script for development builds and requires manual Xcode commands for release archiving.

Development Builds with run_ios.sh

The run_ios.sh script automates building, installing, and launching the app on an iOS simulator:

  1. Simulator Selection: The script searches for a currently booted simulator; if none exists, it automatically boots an iPhone 15 Pro.

  2. Build: It invokes xcodebuild using the swiftApp/swiftApp.xcworkspace workspace and swiftApp scheme in Debug configuration, directing derived data to build/ios_derived_data.

  3. Installation: The script locates the compiled .app bundle in DerivedData/Build/Products/Debug-iphonesimulator, extracts the bundle identifier from swiftApp/swiftApp/Info.plist using PlistBuddy, and installs the app via xcrun simctl.

  4. Launch: Finally, it launches the installed app on the selected simulator using xcrun simctl launch.

Production IPA Generation

To create a distributable IPA for TestFlight or the App Store, you must run manual xcodebuild commands. The repository does not currently automate this step in CI, though you could adapt the following commands into a GitHub Actions workflow:


# Step 1: Create archive

xcodebuild -workspace swiftApp/swiftApp.xcworkspace \
           -scheme swiftApp \
           -configuration Release \
           -archivePath build/ios.xcarchive \
           archive

# Step 2: Export IPA (requires ExportOptions.plist)

xcodebuild -exportArchive \
           -archivePath build/ios.xcarchive \
           -exportPath build/ios_ipa \
           -exportOptionsPlist ExportOptions.plist

The resulting .ipa file in build/ios_ipa/ can then be uploaded to App Store Connect using the Transporter app or xcrun altool.

Key Configuration Files

Understanding the Muse release process requires familiarity with these specific files:

File Path Platform Purpose
.github/workflows/package.yml Android CI workflow that triggers on releases, builds, signs, and publishes artifacts
composeApp/build.gradle.kts Android Gradle configuration defining the release build type and version codes
fastlane/metadata/android/** Android Store listing assets including screenshots and changelogs
run_ios.sh iOS Local development script for simulator builds and testing
swiftApp/swiftApp.xcworkspace iOS Xcode workspace file used by xcodebuild
swiftApp/swiftApp/Info.plist iOS Contains bundle identifier used during simulator installation

Summary

  • Android releases are fully automated through GitHub Actions when you publish a new release, producing signed APKs or AABs using secrets stored in the repository.
  • iOS development builds rely on the run_ios.sh convenience script to compile and run the app on a local simulator.
  • iOS production releases currently require manual xcodebuild archiving and exporting, though the commands can be adapted for CI/CD.
  • The fastlane/metadata/android directory manages Play Store listing content separately from the binary build process.

Frequently Asked Questions

How do I trigger an Android release build in Muse?

Create a new GitHub release (or push a new tag) to automatically trigger the package.yml workflow. The workflow listens for release events and handles the entire build, sign, and publish cycle without manual intervention.

What secrets are required for Android signing?

You must configure four GitHub Secrets: KEY_STORE_BASE64 (your keystore file encoded as Base64), KEY_STORE_PASSWORD, ALIAS (the keystore alias), and KEY_PASSWORD. These are consumed by the ilharp/sign-android-release action during the CI workflow.

Can I build iOS release binaries automatically in CI?

The current repository does not include an automated iOS release workflow. While run_ios.sh handles debug simulator builds, you must manually run xcodebuild archive and xcodebuild -exportArchive commands locally to generate IPAs. You can adapt these commands into a GitHub Actions workflow using macOS runners if needed.

What is the difference between APK and AAB in Muse builds?

The Muse CI workflow generates an APK by default using ./gradlew assembleRelease. To produce an Android App Bundle (AAB) required for Google Play Store distribution, you would modify the workflow to run ./gradlew bundleRelease instead, or execute this command locally. Both artifacts are signed using the same keystore configuration.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →