New projects on the Tville build server

How to add a repository that this server will build and publish. Pushing main or beta on a repository owned by agthatch starts a build. app.yaml at the repository root tells the server which targets to run.

Create the repository

Add a GitHub webhook on the repository:

The server answers HTTP 200 when it accepts the push and starts the build. That response does not mean the APK or the web site is ready.

What the server builds

The project is a Flutter app with pubspec.yaml at the repository root. The server runs flutter pub get in the image flutter-builder:latest, then one or both of these commands:

flutter build apk --release
flutter build web --release --target <web.target>

The image's Flutter version is the one every app gets. .fvmrc is not read. The build does not pass --dart-define. A value the app needs at compile time has to already be available to that command, because app.yaml has no field for it.

The checkout on the server is reset to origin/<branch> on every build. Commit the files you want built. Do not commit secrets.

app.yaml

Put app.yaml in the repository root. The server reads a small subset of YAML. It is not a general YAML parser.

No app.yaml

A repository with no app.yaml builds only the Android APK.

Android

android:
  kind: flutter
  target: lib/main.dart

kind must be flutter. Any other kind stops the build before Android or web runs. When target is set, it must be a relative file path such as lib/main.dart: no leading slash, no .., and no leading dash. The APK command does not receive --target. Flutter builds its default Android target.

The APK is published at:

https://apk.brotherlybins.com/<repository-name>-<branch>.apk

For agthatch/demo-app on main, that is https://apk.brotherlybins.com/demo-app-main.apk.

Web

web:
  kind: flutter
  target: lib/main.dart
  hostname: app.example.com

kind must be flutter. Any other kind stops the build before Android or web runs. target is required and follows the same path rules as the Android target. The web command is flutter build web --release --target <target>.

hostname is the public DNS name for this site. The app repository sets it. app.example.com above is a placeholder; replace it with the name you will serve. The name must contain a dot. An IP address is refused. A name this server already serves is refused, including tv.brotherlybins.com, apk.brotherlybins.com, build.brotherlybins.com, rules.brotherlybins.com, and any hostname already used by another app.

Create the DNS record for that hostname so it reaches this server before the first web deploy. The server does not create DNS records.

If hostname is missing or empty, the web deploy stops before the Flutter web build and before it changes Caddy. The current web release stays in place. When the same file also has an Android target, the APK build still runs, and the web step then fails.

A successful web deploy is served at https://<hostname>/. The server keeps the current release and the previous one. A failed build leaves the current release where it was. Caddy is reloaded only when that app's site file changes. Other sites are not rewritten.

Android and web together

android:
  kind: flutter
  target: lib/main.dart

web:
  kind: flutter
  target: lib/main.dart
  hostname: app.example.com

Android runs first, then web.

Backend

backend:
  kind: dart

A backend section is recognized and not deployed. The server does not build an image, publish a port, or start a container from it. The section can stay in the file.

Field reference

FieldRequiredMeaning
android.kindWhen the section existsflutter
android.targetNoRelative Dart path. Checked when present. Not passed to the APK build.
web.kindWhen the section existsflutter
web.targetFor webRelative Dart path passed to flutter build web --target.
web.hostnameFor webPublic DNS name. You create the DNS record. Omit it and the web deploy publishes nothing.
backend.*NoRecorded and not deployed.

Checklist

  1. The repository is agthatch/<name>, and the name is not reserved.
  2. The webhook uses https://build.brotherlybins.com/, the server secret, and push events.
  3. The server's SSH key can clone the repository.
  4. You push main or beta.
  5. pubspec.yaml is at the root, and the Flutter release command succeeds in flutter-builder:latest.
  6. app.yaml matches the shape on this page.
  7. For a web target, web.hostname is a DNS name you control, and that name reaches this server.