# Steps run in file order, in one container, sharing /ci/build. # Same image as the Containerfile's build stage, so the binary links against # the glibc of the trixie runtime image. image = "docker.io/library/rust:1-trixie" work_dir = "/ci/build" clone_project_to = "/ci/build/project" shell_setup = """ set -euo pipefail export CARGO_TARGET_DIR=/ci/cache/target export ANDROID_HOME=/ci/cache/android-sdk """ timeout = 3600 memory_limit = "6g" # CARGO_TARGET_DIR must stay outside clone_project_to: the checkout is # extracted over that directory. cache = [ { path = "/ci/cache/target", max_size = "16g" }, { path = "/usr/local/cargo/registry", max_size = "4g" }, # trunk downloads wasm-opt here. { path = "/root/.cache/trunk", max_size = "1g" }, { path = "/ci/cache/android-sdk", max_size = "3g" }, { path = "/root/.gradle", max_size = "4g" }, ] [on] push = ["master"] tag = true [variables] [variables.TRUNK_VERSION] default = "0.21.14" description = "Trunk release that builds the wasm frontend. Matches the Containerfile." [[steps]] name = "setup" timeout = 900 run_sh = """ apt-get update -qq && apt-get install -y -qq --no-install-recommends \ openjdk-21-jdk-headless > /dev/null rustup component add rustfmt clippy rustup target add wasm32-unknown-unknown url="https://github.com/trunk-rs/trunk/releases/download/v${TRUNK_VERSION}/trunk-x86_64-unknown-linux-gnu.tar.gz" curl -fsSL -o /tmp/trunk.tar.gz "$url" curl -fsSL "$url.sha256" | awk '{print $1 " /tmp/trunk.tar.gz"}' | sha256sum -c - tar xzf /tmp/trunk.tar.gz -C /usr/local/bin rm -f /tmp/trunk.tar.gz # Only for the license files. Gradle installs the platform and build-tools # that the app needs on its own. if [ ! -x "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" ]; then curl -fsSL -o /tmp/clt.zip \ "https://dl.google.com/android/repository/commandlinetools-linux-15859902_latest.zip" echo "040d3996a65543d22ec4bf73e4c37aa37a8d4af4 /tmp/clt.zip" | sha1sum -c - unzip -q /tmp/clt.zip -d /tmp/clt mkdir -p "$ANDROID_HOME/cmdline-tools" mv /tmp/clt/cmdline-tools "$ANDROID_HOME/cmdline-tools/latest" rm -r /tmp/clt /tmp/clt.zip fi (yes || true) | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --licenses > /dev/null trunk --version && cargo fmt --version && cargo clippy --version && java -version """ # Reported, not gated: clippy findings change between toolchain versions. [[steps]] name = "lint" warn_on_fail = true run_sh = """ cd project cargo fmt --check cargo clippy --workspace --all-targets -- -D warnings """ [[steps]] name = "test" run_sh = "cd project && cargo test --workspace" [[steps]] name = "build" timeout = 2400 run_sh = """ cd project (cd web && trunk build --release) cargo build --locked --release -p server """ [[steps]] name = "android" timeout = 1800 run_sh = """ cd project/android ./gradlew --no-daemon testDebugUnitTest assembleDebug cp app/build/outputs/apk/debug/app-debug.apk /ci/build/opentracker-debug.apk """ publish_file = ["/ci/build/opentracker-debug.apk"] # Needs the CI secrets ANDROID_KEYSTORE_BASE64 (base64 of a PKCS12 keystore) # and ANDROID_KEYSTORE_PASSWORD. Releases must keep the same key: Android # refuses an update signed with another key. [[steps]] name = "android-release" warn_on_fail = true timeout = 1800 run_sh = """ if [ -z "${ANDROID_KEYSTORE_BASE64:-}" ] || [ -z "${ANDROID_KEYSTORE_PASSWORD:-}" ]; then echo "WARNING: CI secrets ANDROID_KEYSTORE_BASE64 or ANDROID_KEYSTORE_PASSWORD missing. No signed release APK." exit 1 fi export ANDROID_KEYSTORE=/tmp/release.p12 ANDROID_KEY_ALIAS=opentracker printf '%s' "$ANDROID_KEYSTORE_BASE64" | base64 -d > "$ANDROID_KEYSTORE" cd project/android ./gradlew --no-daemon assembleRelease cp app/build/outputs/apk/release/app-release.apk /ci/build/opentracker-release.apk """ publish_file = ["/ci/build/opentracker-release.apk"] [[steps]] name = "android-lint" warn_on_fail = true run_sh = "cd project/android && ./gradlew --no-daemon lintDebug" # Packages what the build step made via the Containerfile's prebuilt stage. # build_image builds it in a VM on the server and pushes it to this repo's # registry. A branch run pushes the short sha and "edge". A tag run pushes # the short sha, the tag and "latest". Tags cannot depend on the trigger, so # run_if picks one of two image steps. [[steps]] name = "image-files" run_sh = """ cd project mkdir -p ci-bin cp "${CARGO_TARGET_DIR}/release/otserver" ci-bin/otserver cp -r web/dist ci-bin/web """ [[steps]] name = "image" run_if = 'test -z "${CI_COMMIT_TAG}"' timeout = 900 [steps.build_image] args = { BIN_STAGE = "prebuilt" } tags = ["$CI_COMMIT_SHORT_SHA", "edge"] [[steps]] name = "image-release" run_if = 'test -n "${CI_COMMIT_TAG}"' timeout = 900 [steps.build_image] args = { BIN_STAGE = "prebuilt" } tags = ["$CI_COMMIT_SHORT_SHA", "$CI_COMMIT_TAG", "latest"]