Adding projects
The project assistant, a buildstation.json to check in, adding missing credentials, and building two customer variants from one folder via Git branch.
In the Build Station, a project is a Flutter folder with everything you need to build it: Flutter version, store IDs, Dart defines, upload routes and the presets. If you ship the same app to several customers, create one project per customer.
The project assistant
Click + Projekt (+ Project) in the sidebar or drag a folder from the Finder onto the sidebar. The assistant has two steps.
Step 1: Choose a folder
Use Ordner wählen … (choose folder) to point to the Flutter folder. The Station then reads:
pubspec.yamland.fvmrcandroid/app/build.gradleorbuild.gradle.ktsios/Runner.xcodeproj/project.pbxproj- the entry points
lib/main*.dart - shell scripts in
tools/,scripts/andbin/
Under Erkannt (detected) you’ll see what it found: app name, version, Flutter version, applicationId, bundle ID, platforms, flavors, entry points and build scripts. From that it creates Preset-Vorschläge (preset suggestions). These are suggestions, not requirements: accept them one by one or leave them out.
If the Station can’t find a pubspec.yaml, it tells you. If the Flutter project is in a subfolder, you’re better off choosing that one. You can still create the project either way.
Step 2: Details
Everything is prefilled and can be changed:
| Field | Meaning |
|---|---|
| Anzeigename (display name) | What the project is called in the list. |
| ID | Folder name in the collection folder, e.g. kunde-a. |
| Flutter-Version (fvm) | Empty means: the version from the project’s .fvmrc. |
| Android applicationId, iOS Bundle-ID | Needed for store uploads and checks. |
| Store-Links | Play Console URL and App Store Connect URL, one click away later on. |
| Default-Dart-Defines | Compile-time constants for all presets of this project. |
| Default-Env | Process environment for the toolchain, e.g. JAVA_HOME. Doesn’t end up in the app. |
Projekt anlegen (create project) saves it. You don’t have to touch a JSON file for this.
Editing a project
In the Build tab, Projekt bearbeiten (Edit project) opens the editor; alternatively use Bearbeiten … (Edit) in the context menu of the project list. Besides the fields from the assistant, you’ll find:
- Projektordner (project folder) with Ändern … (change), in case the folder has moved
- Git-Branch to link to a branch (see below)
- Web-Build committen (commit web build) (see Custom scripts and web builds)
- Codemagic to link to a Codemagic app
- Upload with Store-Upload einrichten (set up store upload) and fastlane
- the list of Presets with edit, duplicate and delete
Under Prüfung (check) you’ll see errors and notes. As long as an error is listed, such as a missing folder, Speichern (Save) stays disabled.
Shipping settings with the project
So that a project doesn’t need to be set up again on a second Mac, you can write its settings into the project folder and check them in.
… › Einstellungen in Projektordner exportieren … (export settings to project folder) creates a buildstation.json in the project folder. It contains presets, env and Dart defines, store IDs, upload modes and the Codemagic link. It does not contain the path or any credentials from the keychain, keystores or certificates.
Values in env and Dart defines whose names look like secrets (TOKEN, PASSWORD, KEY …) are listed by the export under Sieht nach Geheimnis aus (looks like a secret). Ticked values stay empty in the file and are asked for after import.
When you create a project for this folder on the other Mac, the assistant recognizes the file and offers Exportierte Build-Einstellungen übernehmen (use exported build settings). The checkbox is ticked; you can untick it.
Later, … › Einstellungen aus Projektordner laden … (load settings from project folder) pulls a newer version into an existing project. Presets, env, Dart defines, upload and Codemagic settings are replaced; credentials in the keychain stay untouched.
A
buildstation.jsoncan contain custom scripts, and those run without a sandbox. Take a look inside a file from someone else before you use it. See Settings and security.
Adding missing credentials
After creating or importing a project, the Station checks what’s still missing on this Mac and shows a dialog Zugangsdaten für „…“ (credentials for “…”). Depending on the project, that can be:
- the Codemagic API token, if a Codemagic app is linked
- the store credentials matching the upload mode: service account,
.p8, Partner Center key or the service account JSON forfastlane supply - the Android keystore, if
build.gradlereads akey.properties - the team’s iOS distribution certificate from the
project.pbxproj - env and Dart define values that were left empty in the export
You can fill in each item right in the dialog or jump to the matching setup via Einrichten … (set up). Erneut prüfen (check again) refreshes the list, Später (later) closes it. The same check is available at any time under … › Zugangsdaten prüfen … (check credentials).
Sharing projects as JSON
… › Als JSON exportieren … (export as JSON) saves a single project as a JSON file. The import icon next to + Projekt reads such a file back in. Since the path differs from machine to machine, the Station asks for the project folder when importing.
One folder, two customers
If the same app lives in a separate branch per customer, two projects can point to the same folder and each be linked to a branch:
| Project | Folder | Branch |
|---|---|---|
| Kunde A | ~/kunden/erp-ui |
kunde-a |
| Kunde B | ~/kunden/erp-ui |
kunde-b |
In the project editor, the field is called Git-Branch. The list icon next to it lets you pick one of the local branches. Leaving it empty is the normal case and changes nothing.
If a branch is set, the Station switches to it before every build, even before the pre-steps. That way a pub get doesn’t resolve the dependencies of the wrong state. The switch shows up in the log:
Git: Branch „kunde-b" → „kunde-a" …
Auf „kunde-a" gewechselt (a1b2c3d).
Three rules apply, and they’re deliberate:
- A dirty working tree cancels the build.
git checkoutwould carry uncommitted changes over to the other branch. Commit or discard them first. - If the switch fails, the build is cancelled. Otherwise you’d get an artifact with one customer’s name and the other customer’s code.
- Only one operation runs per folder. While customer A is building, customer B waits in the queue, even though they’re two projects.
After a switch, the run points out that the dependencies may differ. A pub get pre-step in the preset takes care of that for good.
If two projects use the same folder but only one has a branch, the project editor warns you. The same applies if both have the same branch entered.
The alternative: git worktree
git worktree add ../erp-ui-kunde-b kunde-b
This creates a separate folder for the branch that shares the repository with the first one. Then you have two projects with two paths, nothing ever gets switched, and both can build in parallel. If you have the disk space, this is the calmer route. Branch linking is meant for cases where you want to stick with a single folder.
Git pull and push in the Build tab
If the project folder is a Git repository, the Build tab shows a bar for syncing with the remote below the branch line. It shows whether the branch is Synchron mit (in sync with) its upstream, how many commits it’s ahead or behind, or that there’s Kein Upstream (no upstream) yet.
- Pull runs
git pull --ff-only. It only fetches new commits if that works without a merge. The number in parentheses shows how many commits are waiting. - Commit & Push opens a dialog with the changed files, a suggested Commit-Nachricht (commit message) and the Danach pushen (push afterwards) switch. If there’s nothing to commit but there are unpushed commits, the button is called Push.
- The arrow icon Remote prüfen (git fetch) (check remote) fetches the current state of the remote.
This is handy for everything the Station itself changes in the project: the version in pubspec.yaml, a Flutter hotfix in .fvmrc or an automatic repair. While a build is running in the folder, the buttons are disabled.