.hearthforge-ci.toml
⎇
Raw
1# Steps run in file order, in one container, sharing /ci/build.
2# Same image as the Containerfile's build stage, so the binary links against
3# the glibc of the trixie runtime image.
4
5image = "docker.io/library/rust:1-trixie"
6work_dir = "/ci/build"
7clone_project_to = "/ci/build/project"
8shell_setup = """
9set -euo pipefail
10export CARGO_TARGET_DIR=/ci/cache/target
11export ANDROID_HOME=/ci/cache/android-sdk
12"""
13
14timeout = 3600
15memory_limit = "6g"
16
17# CARGO_TARGET_DIR must stay outside clone_project_to: the checkout is
18# extracted over that directory.
19cache = [
20 { path = "/ci/cache/target", max_size = "16g" },
21 { path = "/usr/local/cargo/registry", max_size = "4g" },
22 # trunk downloads wasm-opt here.
23 { path = "/root/.cache/trunk", max_size = "1g" },
24 { path = "/ci/cache/android-sdk", max_size = "3g" },
25 { path = "/root/.gradle", max_size = "4g" },
26]
27
28[on]
29push = ["master"]
30tag = true
31
32[variables]
33
34 [variables.TRUNK_VERSION]
35 default = "0.21.14"
36 description = "Trunk release that builds the wasm frontend. Matches the Containerfile."
37
38[[steps]]
39name = "setup"
40timeout = 900
41run_sh = """
42apt-get update -qq && apt-get install -y -qq --no-install-recommends \
43 openjdk-21-jdk-headless > /dev/null
44
45rustup component add rustfmt clippy
46rustup target add wasm32-unknown-unknown
47
48url="https://github.com/trunk-rs/trunk/releases/download/v${TRUNK_VERSION}/trunk-x86_64-unknown-linux-gnu.tar.gz"
49curl -fsSL -o /tmp/trunk.tar.gz "$url"
50curl -fsSL "$url.sha256" | awk '{print $1 " /tmp/trunk.tar.gz"}' | sha256sum -c -
51tar xzf /tmp/trunk.tar.gz -C /usr/local/bin
52rm -f /tmp/trunk.tar.gz
53
54# Only for the license files. Gradle installs the platform and build-tools
55# that the app needs on its own.
56if [ ! -x "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" ]; then
57 curl -fsSL -o /tmp/clt.zip \
58 "https://dl.google.com/android/repository/commandlinetools-linux-15859902_latest.zip"
59 echo "040d3996a65543d22ec4bf73e4c37aa37a8d4af4 /tmp/clt.zip" | sha1sum -c -
60 unzip -q /tmp/clt.zip -d /tmp/clt
61 mkdir -p "$ANDROID_HOME/cmdline-tools"
62 mv /tmp/clt/cmdline-tools "$ANDROID_HOME/cmdline-tools/latest"
63 rm -r /tmp/clt /tmp/clt.zip
64fi
65(yes || true) | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --licenses > /dev/null
66
67trunk --version && cargo fmt --version && cargo clippy --version && java -version
68"""
69
70# Reported, not gated: clippy findings change between toolchain versions.
71[[steps]]
72name = "lint"
73warn_on_fail = true
74run_sh = """
75cd project
76cargo fmt --check
77cargo clippy --workspace --all-targets -- -D warnings
78"""
79
80[[steps]]
81name = "test"
82run_sh = "cd project && cargo test --workspace"
83
84[[steps]]
85name = "build"
86timeout = 2400
87run_sh = """
88cd project
89(cd web && trunk build --release)
90cargo build --locked --release -p server
91"""
92
93[[steps]]
94name = "android"
95timeout = 1800
96run_sh = """
97cd project/android
98./gradlew --no-daemon testDebugUnitTest assembleDebug
99cp app/build/outputs/apk/debug/app-debug.apk /ci/build/opentracker-debug.apk
100"""
101publish_file = ["/ci/build/opentracker-debug.apk"]
102
103# Needs the CI secrets ANDROID_KEYSTORE_BASE64 (base64 of a PKCS12 keystore)
104# and ANDROID_KEYSTORE_PASSWORD. Releases must keep the same key: Android
105# refuses an update signed with another key.
106[[steps]]
107name = "android-release"
108run_if = 'test -n "${CI_COMMIT_TAG}"'
109warn_on_fail = true
110timeout = 1800
111run_sh = """
112if [ -z "${ANDROID_KEYSTORE_BASE64:-}" ] || [ -z "${ANDROID_KEYSTORE_PASSWORD:-}" ]; then
113 echo "WARNING: CI secrets ANDROID_KEYSTORE_BASE64 or ANDROID_KEYSTORE_PASSWORD missing. No signed release APK."
114 exit 1
115fi
116export ANDROID_KEYSTORE=/tmp/release.p12 ANDROID_KEY_ALIAS=opentracker
117printf '%s' "$ANDROID_KEYSTORE_BASE64" | base64 -d > "$ANDROID_KEYSTORE"
118cd project/android
119./gradlew --no-daemon assembleRelease
120cp app/build/outputs/apk/release/app-release.apk /ci/build/opentracker-release.apk
121"""
122publish_file = ["/ci/build/opentracker-release.apk"]
123
124[[steps]]
125name = "android-lint"
126warn_on_fail = true
127run_sh = "cd project/android && ./gradlew --no-daemon lintDebug"
128
129# Packages what the build step made via the Containerfile's prebuilt stage.
130# build_image builds it in a VM on the server and pushes it to this repo's
131# registry. A branch run pushes the short sha and "edge". A tag run pushes
132# the short sha, the tag and "latest". Tags cannot depend on the trigger, so
133# run_if picks one of two image steps.
134[[steps]]
135name = "image-files"
136run_sh = """
137cd project
138mkdir -p ci-bin
139cp "${CARGO_TARGET_DIR}/release/otserver" ci-bin/otserver
140cp -r web/dist ci-bin/web
141"""
142
143[[steps]]
144name = "image"
145run_if = 'test -z "${CI_COMMIT_TAG}"'
146timeout = 900
147[steps.build_image]
148args = { BIN_STAGE = "prebuilt" }
149tags = ["$CI_COMMIT_SHORT_SHA", "edge"]
150
151[[steps]]
152name = "image-release"
153run_if = 'test -n "${CI_COMMIT_TAG}"'
154timeout = 900
155[steps.build_image]
156args = { BIN_STAGE = "prebuilt" }
157tags = ["$CI_COMMIT_SHORT_SHA", "$CI_COMMIT_TAG", "latest"]
158