Adding gitea build scripts for Android, Linux GUI and dockerized website
This commit is contained in:
@@ -0,0 +1,86 @@
|
|||||||
|
name: Build Android Apk
|
||||||
|
|
||||||
|
# Only a release built through "Releases -> New Release" starts a build. A tag
|
||||||
|
# pushed with plain git does not publish a release and is therefore ignored.
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
|
||||||
|
env:
|
||||||
|
# Keep in sync with the other workflows and with `ac_web/Dockerfile`.
|
||||||
|
FLUTTER_VERSION: '3.44.9'
|
||||||
|
# The project produces java 17 bytecode (`android/app/build.gradle.kts`), but
|
||||||
|
# gradle 9.1 and the android gradle plugin 9 need a newer jdk to run on.
|
||||||
|
JAVA_VERSION: '21'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
android:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: catthehacker/ubuntu:act-latest
|
||||||
|
|
||||||
|
# The flutter project lives in a sub directory of the repository.
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: ac_web
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: https://github.com/actions/checkout@v4
|
||||||
|
|
||||||
|
# The flutter tool runs git inside the workspace, which the container
|
||||||
|
# user does not own after the checkout.
|
||||||
|
- name: Trust the workspace
|
||||||
|
run: git config --global --add safe.directory '*'
|
||||||
|
|
||||||
|
- name: Set up Java
|
||||||
|
uses: https://github.com/actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: ${{ env.JAVA_VERSION }}
|
||||||
|
|
||||||
|
# Installs the command line tools and accepts the sdk licenses. The
|
||||||
|
# platform, the build tools and the ndk pinned by the flutter sdk are
|
||||||
|
# then downloaded by gradle itself, which is what makes this job slow on
|
||||||
|
# a cold runner.
|
||||||
|
- name: Set up the Android sdk
|
||||||
|
uses: https://github.com/android-actions/setup-android@v3
|
||||||
|
|
||||||
|
- name: Set up Flutter
|
||||||
|
uses: https://github.com/subosito/flutter-action@v2
|
||||||
|
with:
|
||||||
|
flutter-version: ${{ env.FLUTTER_VERSION }}
|
||||||
|
channel: stable
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: flutter pub get
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: flutter test
|
||||||
|
|
||||||
|
# One apk for all abis. `--split-per-abi` would produce three smaller
|
||||||
|
# ones instead, at the cost of having to pick the right one manually.
|
||||||
|
#
|
||||||
|
# The release build is signed with a debug key, because
|
||||||
|
# `android/app/build.gradle.kts` has no release signing config yet. To
|
||||||
|
# ship the apk, add a keystore as a secret, write it into
|
||||||
|
# `android/key.properties` here and reference it from the gradle file.
|
||||||
|
- name: Build the apk
|
||||||
|
run: flutter build apk --release
|
||||||
|
|
||||||
|
# Gradle always writes the same file name, so the release the apk belongs
|
||||||
|
# to would not be visible after downloading it.
|
||||||
|
- name: Name the apk after the release
|
||||||
|
run: mv build/app/outputs/flutter-apk/app-release.apk ac_web-${{ github.ref_name }}.apk
|
||||||
|
|
||||||
|
# Artifacts of v4 need gitea 1.22 or newer, older instances need @v3.
|
||||||
|
- name: Upload the apk
|
||||||
|
uses: https://github.com/actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ac_web-android-${{ github.ref_name }}
|
||||||
|
# Artifact paths are relative to the repository, not to the
|
||||||
|
# working-directory above.
|
||||||
|
path: ac_web/ac_web-${{ github.ref_name }}.apk
|
||||||
|
if-no-files-found: error
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
name: Build Linux Application
|
||||||
|
|
||||||
|
# Only a release built through "Releases -> New Release" starts a build. A tag
|
||||||
|
# pushed with plain git does not publish a release and is therefore ignored.
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
|
||||||
|
env:
|
||||||
|
# Keep in sync with the other workflows and with `ac_web/Dockerfile`.
|
||||||
|
FLUTTER_VERSION: '3.44.9'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
linux:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
# Same base image as the docker job, it already brings the tools the
|
||||||
|
# actions below expect (git, curl, unzip, node).
|
||||||
|
container:
|
||||||
|
image: catthehacker/ubuntu:act-latest
|
||||||
|
|
||||||
|
# The flutter project lives in a sub directory of the repository.
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: ac_web
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: https://github.com/actions/checkout@v4
|
||||||
|
|
||||||
|
# The flutter tool runs git inside the workspace, which the container
|
||||||
|
# user does not own after the checkout.
|
||||||
|
- name: Trust the workspace
|
||||||
|
run: git config --global --add safe.directory '*'
|
||||||
|
|
||||||
|
# Everything `flutter build linux` needs to compile the gtk runner.
|
||||||
|
- name: Install the linux desktop toolchain
|
||||||
|
run: |
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y --no-install-recommends \
|
||||||
|
clang cmake ninja-build pkg-config \
|
||||||
|
libgtk-3-dev liblzma-dev libstdc++-12-dev \
|
||||||
|
curl unzip xz-utils
|
||||||
|
|
||||||
|
- name: Set up Flutter
|
||||||
|
uses: https://github.com/subosito/flutter-action@v2
|
||||||
|
with:
|
||||||
|
flutter-version: ${{ env.FLUTTER_VERSION }}
|
||||||
|
channel: stable
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: flutter pub get
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: flutter test
|
||||||
|
|
||||||
|
- name: Build the linux application
|
||||||
|
run: flutter build linux --release
|
||||||
|
|
||||||
|
# The build produces a directory, not a single file: the executable next
|
||||||
|
# to the flutter engine and its data. It is packed so that the artifact
|
||||||
|
# keeps the executable bit.
|
||||||
|
- name: Pack the bundle
|
||||||
|
run: tar -czf ac_web-linux-x64-${{ github.ref_name }}.tar.gz -C build/linux/x64/release bundle
|
||||||
|
|
||||||
|
# Artifacts of v4 need gitea 1.22 or newer, older instances need @v3.
|
||||||
|
- name: Upload the bundle
|
||||||
|
uses: https://github.com/actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ac_web-linux-x64-${{ github.ref_name }}
|
||||||
|
# Artifact paths are relative to the repository, not to the
|
||||||
|
# working-directory above.
|
||||||
|
path: ac_web/ac_web-linux-x64-${{ github.ref_name }}.tar.gz
|
||||||
|
if-no-files-found: error
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
name: Publish Docker Image
|
||||||
|
|
||||||
|
# Only a release built through "Releases -> New Release" starts a build. A tag
|
||||||
|
# pushed with plain git does not publish a release and is therefore ignored.
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
|
||||||
|
env:
|
||||||
|
# Gitea container registry. Set a different host in
|
||||||
|
# "Settings -> Actions -> Variables" if the instance ever moves.
|
||||||
|
REGISTRY: git.srv.kingeldarion.de
|
||||||
|
OWNER: ${{ github.repository_owner }}
|
||||||
|
IMAGE: ac-web
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
# This base image makes Docker-in-Docker with Gitea's act-runner painless.
|
||||||
|
container:
|
||||||
|
image: catthehacker/ubuntu:act-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: https://github.com/actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: https://github.com/docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Buildx
|
||||||
|
uses: https://github.com/docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Login to Gitea Container Registry
|
||||||
|
uses: https://github.com/docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
# A personal access token, created in the repo settings as BUILDTOKEN.
|
||||||
|
password: ${{ secrets.BUILDTOKEN }}
|
||||||
|
|
||||||
|
- name: Docker meta (tags & labels)
|
||||||
|
id: meta
|
||||||
|
uses: https://github.com/docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
${{ env.REGISTRY }}/${{ env.OWNER }}/${{ env.IMAGE }}
|
||||||
|
# Only releases end up here, so every build is the newest one and
|
||||||
|
# branch tags can never occur. Move `latest` behind a condition on
|
||||||
|
# `github.event.release.prerelease` if pre-releases are used.
|
||||||
|
tags: |
|
||||||
|
type=raw,value=latest
|
||||||
|
type=ref,event=tag
|
||||||
|
type=sha,format=short
|
||||||
|
|
||||||
|
# The dockerfile compiles the web bundle itself, so the context is the
|
||||||
|
# flutter project and nothing has to be built before this step.
|
||||||
|
- name: Build & Push the website image
|
||||||
|
uses: https://github.com/docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: ./ac_web
|
||||||
|
file: ./ac_web/Dockerfile
|
||||||
|
push: true
|
||||||
|
platforms: linux/amd64
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
@@ -32,6 +32,25 @@ Widget tests run against a mocked backend: build a `MockClient` that answers by
|
|||||||
|
|
||||||
`flutter analyze` reports ~40 pre-existing `file_names` / `non_constant_identifier_names` infos caused by the naming conventions below. They are expected — only care about new warnings and errors.
|
`flutter analyze` reports ~40 pre-existing `file_names` / `non_constant_identifier_names` infos caused by the naming conventions below. They are expected — only care about new warnings and errors.
|
||||||
|
|
||||||
|
## CI (Gitea Actions)
|
||||||
|
|
||||||
|
`.gitea/workflows/` holds one workflow per delivery target. All of them are triggered by `release: types: [published]`, so they run when a release is published through "Releases -> New Release" and never on an ordinary push or on a tag pushed with plain git:
|
||||||
|
|
||||||
|
| Workflow | Builds | Result |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `BuildLinux.yml` | `flutter build linux --release` | `ac_web-linux-x64-<tag>.tar.gz` (the whole bundle directory) as an artifact |
|
||||||
|
| `BuildAndroid.yml` | `flutter build apk --release` | `ac_web-<tag>.apk` as an artifact |
|
||||||
|
| `PublishDocker.yml` | `ac_web/Dockerfile` | image pushed to the Gitea registry as `<tag>`, `latest` and the short sha |
|
||||||
|
|
||||||
|
Notes that are easy to get wrong:
|
||||||
|
|
||||||
|
- The Flutter version is pinned in three places (`FLUTTER_VERSION` in both build workflows, `ARG FLUTTER_VERSION` in `ac_web/Dockerfile`) and must be kept in sync.
|
||||||
|
- Steps run with `working-directory: ac_web`, but `upload-artifact` paths are relative to the repository root.
|
||||||
|
- The workflows are read from the tag the release points at, so they have to be committed **before** the release is created.
|
||||||
|
- Artifacts and the built files carry the tag name (`github.ref_name`); the docker image is pushed as the tag, as `latest` and as the short sha.
|
||||||
|
- The apk is signed with a debug key, because `android/app/build.gradle.kts` still has no release signing config.
|
||||||
|
- The docker image is self contained: it compiles the web bundle itself, so `docker build -f ac_web/Dockerfile ac_web` gives the same result locally. It serves the static bundle with nginx (`ac_web/nginx.conf`), which falls back to `index.html` so deep links survive a reload. The backend address is compiled into the bundle, so the host in `main.dart` must be reachable from the browser of every visitor, not only from the container.
|
||||||
|
|
||||||
## Backend connection
|
## Backend connection
|
||||||
|
|
||||||
The backend host/port is configured once in `lib/main.dart` via `AcApi.configure(const ApiConfig(host: 'localhost', port: 5118))`. Plain http is intentional — the API is only reached inside a trusted network. There is no environment/config file; changing the backend address means editing `main.dart`.
|
The backend host/port is configured once in `lib/main.dart` via `AcApi.configure(const ApiConfig(host: 'localhost', port: 5118))`. Plain http is intentional — the API is only reached inside a trusted network. There is no environment/config file; changing the backend address means editing `main.dart`.
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# Build output and caches of local builds - the image builds everything itself.
|
||||||
|
build/
|
||||||
|
.dart_tool/
|
||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
|
|
||||||
|
# Platform folders that are irrelevant for the web build.
|
||||||
|
android/
|
||||||
|
ios/
|
||||||
|
linux/
|
||||||
|
macos/
|
||||||
|
windows/
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
# Serves the Flutter web build of "AC Control" as a plain static website.
|
||||||
|
#
|
||||||
|
# The image is self contained: it compiles the web bundle itself instead of
|
||||||
|
# expecting a prepared `build/web` directory, so
|
||||||
|
# `docker build -f ac_web/Dockerfile ac_web` produces exactly the same image
|
||||||
|
# locally as the gitea action does.
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- build stage
|
||||||
|
FROM debian:bookworm-slim AS build
|
||||||
|
|
||||||
|
# Keep the version in sync with `.gitea/workflows/*.yml`. The sdk is taken from
|
||||||
|
# the official archive instead of a prebuilt flutter image, because that archive
|
||||||
|
# has every released version and can therefore be pinned exactly.
|
||||||
|
ARG FLUTTER_VERSION=3.44.9
|
||||||
|
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends ca-certificates curl git unzip xz-utils \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN curl -fsSL "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${FLUTTER_VERSION}-stable.tar.xz" \
|
||||||
|
| tar -xJ -C /opt
|
||||||
|
|
||||||
|
ENV PATH="/opt/flutter/bin:${PATH}"
|
||||||
|
|
||||||
|
# The flutter tool calls git on its own sdk during every command, and git
|
||||||
|
# refuses to work in a directory it considers to belong to somebody else.
|
||||||
|
RUN git config --global --add safe.directory /opt/flutter
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# The dependencies are copied on their own so that this layer is only rebuilt
|
||||||
|
# when they actually changed, not on every source change.
|
||||||
|
COPY pubspec.yaml pubspec.lock ./
|
||||||
|
RUN flutter pub get
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# The result is a completely static bundle - the app talks to the AcAPI from
|
||||||
|
# the browser of the user, not from this container.
|
||||||
|
RUN flutter build web --release
|
||||||
|
|
||||||
|
# -------------------------------------------------------------- runtime stage
|
||||||
|
FROM nginx:alpine AS runtime
|
||||||
|
|
||||||
|
# The bundle is built with the backend address that is compiled into
|
||||||
|
# `lib/main.dart`, and the browser of the visitor resolves it - not this
|
||||||
|
# container. Serving this image to other machines therefore needs a host name
|
||||||
|
# in `main.dart` that those machines can reach as well.
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
COPY --from=build /app/build/web /usr/share/nginx/html
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Nginx configuration for the static Flutter web bundle.
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# Everything the bundle cannot resolve itself is answered with the app, so
|
||||||
|
# that reloading a deep link does not end in a 404.
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Both files decide which version of the app the browser gets. They must
|
||||||
|
# never be cached, otherwise a new deployment is not picked up.
|
||||||
|
location = /index.html {
|
||||||
|
add_header Cache-Control "no-store";
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /flutter_service_worker.js {
|
||||||
|
add_header Cache-Control "no-store";
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user