Build and release
Use this page to build installable apps on your machine and to publish a release. Local commands are package.json scripts. See Development setup for prerequisites and flavors.
Build release APKs
bun run build:apk:dev # flutter build apk --flavor dev --release
bun run build:apk:prod # flutter build apk --flavor prod --releaseThe prod scripts set BACKEND_BASE_URL=https://app.schuly.dev. All build scripts pass the Firebase values listed in Development setup.
Release builds use the signing key from android/key.properties. Without that file, they use the debug key.
Point a dev build at a custom backend
BACKEND_BASE_URL=https://example.test bun run build:apk:dev:urlbuild:apk:dev:url passes $BACKEND_BASE_URL through --dart-define=BACKEND_BASE_URL.
Build for iOS
bun run build:ios # flutter build ios --flavor prod --no-codesignThis builds the prod flavor without code signing. Sign it separately, in Xcode or your signing pipeline.
Install over adb
These scripts build a release APK and install it on the connected adb target:
bun run install:dev # build the dev APK, then flutter install --flavor dev
bun run install:prod # build the prod APK, then flutter install --flavor prodTo use a backend on your machine over USB, reverse the port so the device can reach localhost:5033:
bun run adb:reverse # adb reverse tcp:5033 tcp:5033
bun run install:dev:usb # adb:reverse, then install:devTo install a dev build with a custom backend URL:
BACKEND_BASE_URL=https://example.test bun run install:dev:urlRegenerate app icons
flutter_launcher_icons generates the Android and iOS launcher icons from assets/app_icon.png. The settings are in pubspec.yaml. After you change the image, run:
bun run icons # dart run flutter_launcher_iconsThe release workflow regenerates the icons on every build.
Publish a release
Release Drafter keeps a draft release up to date from merged pull requests. To release, publish the draft. Publishing starts two workflows:
build-and-release.ymlbuilds the apps and attaches them to the release.sync-version-on-release.ymlcompares the tag, without itsv, toapplication.properties. If they differ, it updatesapplication.propertiesand the version inpubspec.yaml, keeping the build number, then squash-merges arelease-sync/<version>pull request intomain.
version-bump.yml is a manual alternative. You choose patch, minor, major, or a custom version. It commits the new version to pubspec.yaml, pushes a v<version> tag, and creates the release.
What the build workflow produces
| Asset | Built from |
|---|---|
schuly-<tag>.apk | flutter build apk --release --flavor prod |
schuly-<tag>.aab | flutter build appbundle --release --flavor prod |
schuly-<tag>.apk.sha256 | sha256sum of the APK. The in-app updater checks the download against it. |
schuly-<tag>.ipa | flutter build ios --release --no-codesign, then an unsigned xcodebuild archive |
The workflow sets the build name to the tag and the build number to the run number. You can also start it by hand with workflow_dispatch, but it then only keeps the files as workflow artifacts. It attaches them to a release only when a published release starts it.
Workflow configuration
| Name | Kind | Purpose |
|---|---|---|
KEYSTORE_BASE64 | Secret | The Android release keystore. Without it, the workflow generates a new keystore for that run. |
KEYSTORE_PASSWORD, KEY_PASSWORD | Secret | Passwords for the keystore and key. |
BACKEND_BASE_URL | Variable | Backend URL compiled into the app. Defaults to https://app.schuly.dev. |
FIREBASE_API_KEY, FIREBASE_APP_ID, FIREBASE_SENDER_ID, FIREBASE_PROJECT_ID | Variable | Firebase project for push notifications. |
