CI file
A.hearthforge-ci.toml
@@ -0,0 +1,95 @@
# HearthForge CI for filebrowser-ng.
# Steps run in file order, in one container, sharing /ci/build.
# The steps call the `just` recipes that already live in the repo.
image = "docker.io/rust:1.90-bookworm"
work_dir = "/ci/build"
clone_project_to = "/ci/build/project"
# The rust image ships bash. /bin/sh is dash and has no `pipefail`.
shell = ["/bin/bash", "-c"]
shell_setup = "set -euo pipefail"
timeout = 5400
memory_limit = "6g"
# Without these every run recompiles the whole dependency tree from scratch.
cache = [
"/usr/local/cargo/registry",
"/ci/build/project/target",
"/root/.bun/install/cache",
]
[on]
push = ["master"]
tag = true
[variables]
[variables.TRUNK_VERSION]
default = "0.21.14"
description = "Trunk release that builds the wasm frontend. Matches the Containerfile."
[variables.BUN_VERSION]
default = "1.4.0"
description = "Bun release that bundles web/cm6.js. Matches the Containerfile."
# ── toolchain ────────────────────────────────────────────────────────────────
# The rust image has cargo only. The build also needs the wasm target, just,
# bun and trunk. binaryen supplies wasm-opt, so trunk does not download one.
[setup]
timeout = 900
run_sh = """
apt-get update -qq
apt-get install -y --no-install-recommends binaryen unzip
rustup target add wasm32-unknown-unknown
curl -fsSL https://just.systems/install.sh | bash -s -- --to /usr/local/bin
# BUN_INSTALL controls the prefix, so the binary lands in /usr/local/bin.
curl -fsSL https://bun.sh/install | BUN_INSTALL=/usr/local bash -s "bun-v${BUN_VERSION}"
# Pinned and checksum-checked, same as the Containerfile. This is the gnu
# build, not the musl one, because the image is Debian.
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
just --version && bun --version && trunk --version
"""
# ── checks ───────────────────────────────────────────────────────────────────
# `just lint` is cargo fmt --check plus clippy with warnings denied.
[lint]
run_sh = "cd project && just lint"
# `just test` covers server and api-types. The web crate has its own tests.
[test]
run_sh = "cd project && just test && cargo test -p web"
# ── build ────────────────────────────────────────────────────────────────────
# `just build` bundles CodeMirror, builds the frontend, stages it into
# server/dist and links the single binary with the `embedded` feature.
[build]
timeout = 2400
run_sh = "cd project && just build"
publish_file = ["/ci/build/project/target/release/filebrowser-ng"]
# `just e2e` would rebuild the frontend. The build step already staged
# server/dist, so run the embedded suite against it directly.
[e2e]
run_sh = "cd project && cargo test -p server --features embedded"
# ── release ──────────────────────────────────────────────────────────────────
# Tags only. Ships the binary under a versioned name.
[release]
run_if = 'test -n "${CI_COMMIT_TAG}"'
run_sh = """
cd project
install -Dm755 target/release/filebrowser-ng \
"dist/filebrowser-ng-${CI_COMMIT_TAG}-x86_64-linux-gnu"
"""
publish_gzip = ["/ci/build/project/dist/"]