This guide walks through setting up automated build, test, and release pipelines for all Artifact Keeper clients.
| Platform | Runner | Cost | Trigger |
|---|---|---|---|
| Backend | ubuntu-latest |
Free (public repo) | Every push to main |
| Web | ubuntu-latest |
Free (public repo) | Every push to main |
| iOS/macOS | macos-15 |
Free (public repo) | Every push to main |
| Android | ubuntu-latest |
Free (public repo) | Every push to main |
Releases (archive + signing) trigger on v* tags or manual workflow_dispatch.
Repo: artifact-keeper/artifact-keeper-ios
Workflow: .github/workflows/ci.yml
| Job | Trigger | What it does |
|---|---|---|
build |
Every push/PR | swift build |
test |
Every push/PR | swift test |
build-ios |
Push to main | Build for iOS Simulator (validates Xcode project) |
archive-release |
v* tag or manual |
Archive iOS IPA + macOS app, sign, upload to App Store |
Set these in GitHub: Settings > Secrets and variables > Actions > New repository secret
The build, test, and build-ios jobs run without any secrets.
| Secret | Description | How to get it |
|---|---|---|
APPLE_CERTIFICATE_BASE64 |
Distribution certificate (.p12), base64-encoded | See steps below |
APPLE_CERTIFICATE_PASSWORD |
Password you set when exporting the .p12 | You chose this during export |
APPLE_PROVISIONING_PROFILE_BASE64 |
Provisioning profile (.mobileprovision), base64-encoded | See steps below |
APPLE_TEAM_ID |
Your Apple Developer Team ID | developer.apple.com > Membership |
| Secret | Description | How to get it |
|---|---|---|
APPSTORE_API_KEY_ID |
App Store Connect API Key ID | See steps below |
APPSTORE_API_ISSUER_ID |
App Store Connect API Issuer ID | See steps below |
APPSTORE_API_PRIVATE_KEY |
Contents of the .p8 private key file | See steps below |
- Open Keychain Access on your Mac
- Find your Apple Distribution certificate (or create one at developer.apple.com > Certificates)
- Right-click > Export > save as
.p12format - Set a password when prompted (you'll use this as
APPLE_CERTIFICATE_PASSWORD) - Base64-encode it:
base64 -i ~/Desktop/Certificates.p12 | pbcopy
- Paste into GitHub secret
APPLE_CERTIFICATE_BASE64
- Go to developer.apple.com > Certificates, IDs & Profiles > Profiles
- Click + to create a new profile
- Select App Store Connect (for distribution)
- Select the App ID for Artifact Keeper (create one if needed, bundle ID should match your project)
- Select your distribution certificate
- Download the
.mobileprovisionfile - Base64-encode it:
base64 -i ~/Desktop/ArtifactKeeper.mobileprovision | pbcopy
- Paste into GitHub secret
APPLE_PROVISIONING_PROFILE_BASE64
- Go to appstoreconnect.apple.com > Users and Access > Integrations > App Store Connect API
- Click + to generate a new key
- Give it a name (e.g., "CI/CD"), select App Manager role
- Download the
.p8file (you can only download it once!) - Note the Key ID and Issuer ID shown on the page
- Set secrets:
# Key ID (shown on the page, e.g., "ABC123DEF4") gh secret set APPSTORE_API_KEY_ID --repo artifact-keeper/artifact-keeper-ios # Issuer ID (shown at top of page, e.g., "69a6de78-...") gh secret set APPSTORE_API_ISSUER_ID --repo artifact-keeper/artifact-keeper-ios # Private key (contents of the .p8 file) gh secret set APPSTORE_API_PRIVATE_KEY --repo artifact-keeper/artifact-keeper-ios < ~/Desktop/AuthKey_ABC123DEF4.p8
Once you have the files ready:
# Signing certificate
base64 -i Certificates.p12 | gh secret set APPLE_CERTIFICATE_BASE64 --repo artifact-keeper/artifact-keeper-ios
gh secret set APPLE_CERTIFICATE_PASSWORD --repo artifact-keeper/artifact-keeper-ios
# Provisioning profile
base64 -i ArtifactKeeper.mobileprovision | gh secret set APPLE_PROVISIONING_PROFILE_BASE64 --repo artifact-keeper/artifact-keeper-ios
# Team ID
gh secret set APPLE_TEAM_ID --repo artifact-keeper/artifact-keeper-ios
# App Store Connect API (optional, for automated uploads)
gh secret set APPSTORE_API_KEY_ID --repo artifact-keeper/artifact-keeper-ios
gh secret set APPSTORE_API_ISSUER_ID --repo artifact-keeper/artifact-keeper-ios
gh secret set APPSTORE_API_PRIVATE_KEY --repo artifact-keeper/artifact-keeper-ios < AuthKey_XXXXXXXXXX.p8# Tag a release (triggers archive + App Store upload)
git tag v1.0.0
git push origin v1.0.0
# Or trigger manually without a tag
gh workflow run ci.yml --repo artifact-keeper/artifact-keeper-ios -f upload_to_appstore=trueRepo: artifact-keeper/artifact-keeper-android
Workflow: .github/workflows/ci.yml
| Job | Trigger | What it does |
|---|---|---|
lint |
Every push/PR | ./gradlew lint |
build |
Every push/PR | ./gradlew assembleDebug, uploads debug APK |
test |
Every push/PR | ./gradlew test |
release |
v* tag or manual |
Build signed release APK + AAB, upload to Play Store |
The lint, build, and test jobs run without any secrets.
| Secret | Description | How to get it |
|---|---|---|
ANDROID_KEYSTORE_BASE64 |
Release keystore (.jks), base64-encoded | See steps below |
ANDROID_KEYSTORE_PASSWORD |
Keystore password | You chose this during creation |
ANDROID_KEY_ALIAS |
Key alias in the keystore | You chose this during creation |
ANDROID_KEY_PASSWORD |
Key password | You chose this during creation |
| Secret | Description | How to get it |
|---|---|---|
GOOGLE_PLAY_SERVICE_ACCOUNT_JSON |
Google Play API service account JSON | See steps below |
keytool -genkey -v \
-keystore artifact-keeper-release.jks \
-keyalg RSA \
-keysize 2048 \
-validity 10000 \
-alias artifact-keeper
# Answer the prompts (name, org, etc.)
# Remember the passwords you set!IMPORTANT: Back up this keystore file securely. If you lose it, you cannot update the app on Google Play.
- Go to Google Cloud Console (console.cloud.google.com)
- Create a project (or use existing)
- Enable the Google Play Developer API
- Create a Service Account (IAM & Admin > Service Accounts)
- Download the JSON key file
- Go to Google Play Console (play.google.com/console)
- Go to Settings > API access
- Link the Google Cloud project
- Grant the service account Release Manager access
- Wait 24 hours for the permission to propagate (yes, really)
# Release keystore
base64 -i artifact-keeper-release.jks | gh secret set ANDROID_KEYSTORE_BASE64 --repo artifact-keeper/artifact-keeper-android
gh secret set ANDROID_KEYSTORE_PASSWORD --repo artifact-keeper/artifact-keeper-android
gh secret set ANDROID_KEY_ALIAS --repo artifact-keeper/artifact-keeper-android
gh secret set ANDROID_KEY_PASSWORD --repo artifact-keeper/artifact-keeper-android
# Google Play (optional, for automated uploads)
gh secret set GOOGLE_PLAY_SERVICE_ACCOUNT_JSON --repo artifact-keeper/artifact-keeper-android < service-account.json# Tag a release
git tag v1.0.0
git push origin v1.0.0
# Or manually
gh workflow run ci.yml --repo artifact-keeper/artifact-keeper-androidRepo: artifact-keeper/artifact-keeper-web
Workflow: .github/workflows/ci.yml
Already configured. Builds Docker image and pushes to ghcr.io/artifact-keeper/artifact-keeper-web:latest on every push to main.
No secrets needed (uses GITHUB_TOKEN automatically).
Repo: artifact-keeper/artifact-keeper
Workflow: Check existing workflows.
| Item | Cost | Frequency |
|---|---|---|
| Apple Developer Program | $99 | per year |
| Google Play Console | $25 | one-time |
| GitHub Actions (all platforms) | $0 | free for public repos |
| Docker images (ghcr.io) | $0 | free for public repos |
| Total first year | $124 | |
| Subsequent years | $99/year |
All repos are public, which gives you:
- Unlimited GitHub Actions minutes (Linux, macOS, Windows)
- Free GitHub Packages (Docker images via ghcr.io)
- Free GitHub Pages (landing site)
To get larger/faster macOS runners (M1 silicon), apply at:
- https://github.com/enterprise/startups (for startups)
- Or email [email protected] with your org link
APPLE_CERTIFICATE_BASE64 # .p12 cert, base64
APPLE_CERTIFICATE_PASSWORD # .p12 password
APPLE_PROVISIONING_PROFILE_BASE64 # .mobileprovision, base64
APPLE_TEAM_ID # e.g., "A1B2C3D4E5"
APPSTORE_API_KEY_ID # e.g., "ABC123DEF4"
APPSTORE_API_ISSUER_ID # e.g., "69a6de78-..."
APPSTORE_API_PRIVATE_KEY # .p8 file contents
ANDROID_KEYSTORE_BASE64 # .jks keystore, base64
ANDROID_KEYSTORE_PASSWORD # keystore password
ANDROID_KEY_ALIAS # e.g., "artifact-keeper"
ANDROID_KEY_PASSWORD # key password
GOOGLE_PLAY_SERVICE_ACCOUNT_JSON # service account JSON