diff --git a/.forgejo/workflows/dev-release.yml b/.forgejo/workflows/dev-release.yml new file mode 100644 index 0000000..41e4512 --- /dev/null +++ b/.forgejo/workflows/dev-release.yml @@ -0,0 +1,99 @@ +name: dev release + +# Publishes a dev-track build on every push to `main` (the trunk branch — +# there is no separate `dev` branch). See bread-ecosystem's +# docs/release-channels.md for the release-track policy this is part of. +on: + push: + branches: ['main'] + +jobs: + build: + runs-on: [self-hosted, hestia] + steps: + - name: checkout + run: | + set -euo pipefail + rm -rf src && mkdir src + git clone --branch main --depth 1 \ + "https://git.breadway.dev/${GITHUB_REPOSITORY}.git" src + + - name: build + run: cd src && cargo build --release --locked + + - name: compute dev version + run: | + set -euo pipefail + cd src + # Base the dev version off the latest published stable tag, not + # Cargo.toml — Cargo.toml can go stale relative to the last real + # release, which would make a dev build sort as OLDER than what's + # already installed and bakery would correctly refuse it. + LATEST_TAG="$(git ls-remote --tags --refs \ + "https://git.breadway.dev/${GITHUB_REPOSITORY}.git" 'v*' \ + | awk -F/ '{print $NF}' | sed 's/^v//' | (grep -v -- '-' || true) | sort -V | tail -1)" + if [ -n "${LATEST_TAG}" ]; then + CUR="${LATEST_TAG}" + else + # breadarr's own Cargo.toml is a virtual workspace manifest with + # no [workspace.package] version — breadarrd/Cargo.toml is the + # daemon crate's own version, used as the fallback instead. + CUR="$(grep -m1 '^version' breadarrd/Cargo.toml | sed -E 's/.*"(.*)".*/\1/')" + fi + IFS='.' read -r MA MI PA <<< "${CUR}" + SHA="$(git rev-parse --short HEAD)" + TS="$(date -u +%Y%m%d%H%M%S)" + echo "VERSION=${MA}.${MI}.$((PA + 1))-dev.${TS}+${SHA}" >> "$GITHUB_ENV" + + - name: prepare artifacts + run: | + set -euo pipefail + PKG_DIR="/srv/breadway-dl/dev/breadarr/${VERSION}" + mkdir -p "${PKG_DIR}" + for bin in breadarrd breadarr-tui; do + cp "src/target/release/${bin}" "${PKG_DIR}/${bin}-x86_64" + strip "${PKG_DIR}/${bin}-x86_64" + sha256sum "${PKG_DIR}/${bin}-x86_64" | awk '{print $1}' \ + > "${PKG_DIR}/${bin}-x86_64.sha256" + done + cp src/packaging/systemd/breadarrd.service "${PKG_DIR}/" + cp src/bakery.toml "${PKG_DIR}/bakery.toml" + ln -sfn "${VERSION}" "/srv/breadway-dl/dev/breadarr/latest" + + - name: sign dev binaries + env: + MINISIGN_SEC_KEY: ${{ secrets.BAKERY_MINISIGN_SEC_KEY_PATH }} + run: | + set -euo pipefail + PKG_DIR="/srv/breadway-dl/dev/breadarr/${VERSION}" + if [ -n "${MINISIGN_SEC_KEY:-}" ]; then + for bin in breadarrd breadarr-tui; do + minisign -W -S -s "${MINISIGN_SEC_KEY}" -m "${PKG_DIR}/${bin}-x86_64" \ + -x "${PKG_DIR}/${bin}-x86_64.minisig" /dev/null || true + # mktemp: a fixed clone path races when multiple repos' dev/rc + # workflows run close together on the same self-hosted runner. + ECOSYSTEM_CI_DIR="$(mktemp -d /tmp/bread-ecosystem-ci-XXXXXX)" + git clone --branch main https://git.breadway.dev/Breadway/bread-ecosystem.git "${ECOSYSTEM_CI_DIR}" + TRACK=dev bash "${ECOSYSTEM_CI_DIR}/scripts/gen-index.sh" + rm -rf "${ECOSYSTEM_CI_DIR}" diff --git a/.forgejo/workflows/rc-release.yml b/.forgejo/workflows/rc-release.yml new file mode 100644 index 0000000..05386b2 --- /dev/null +++ b/.forgejo/workflows/rc-release.yml @@ -0,0 +1,79 @@ +name: beta (rc) release + +# Publishes a beta-track build for any `vX.Y.Z-rc.N` prerelease tag pushed +# to `main` — there is no separate `beta` branch; "freezing" is just +# pausing pushes to main while an RC gets tested. See bread-ecosystem's +# docs/release-channels.md for the release-track policy. +on: + push: + tags: ['v*'] + +jobs: + build: + if: ${{ contains(github.ref_name, '-rc.') }} + runs-on: [self-hosted, hestia] + steps: + - name: checkout + run: | + set -euo pipefail + rm -rf src && mkdir src + git clone --branch "${GITHUB_REF_NAME}" --depth 1 \ + "https://git.breadway.dev/${GITHUB_REPOSITORY}.git" src + + - name: build + run: cd src && cargo build --release --locked + + - name: prepare artifacts + run: | + set -euo pipefail + VERSION="${GITHUB_REF_NAME#v}" + PKG_DIR="/srv/breadway-dl/beta/breadarr/${VERSION}" + mkdir -p "${PKG_DIR}" + for bin in breadarrd breadarr-tui; do + cp "src/target/release/${bin}" "${PKG_DIR}/${bin}-x86_64" + strip "${PKG_DIR}/${bin}-x86_64" + sha256sum "${PKG_DIR}/${bin}-x86_64" | awk '{print $1}' \ + > "${PKG_DIR}/${bin}-x86_64.sha256" + done + cp src/packaging/systemd/breadarrd.service "${PKG_DIR}/" + cp src/bakery.toml "${PKG_DIR}/bakery.toml" + ln -sfn "${VERSION}" "/srv/breadway-dl/beta/breadarr/latest" + + - name: sign beta binaries + env: + MINISIGN_SEC_KEY: ${{ secrets.BAKERY_MINISIGN_SEC_KEY_PATH }} + run: | + set -euo pipefail + VERSION="${GITHUB_REF_NAME#v}" + PKG_DIR="/srv/breadway-dl/beta/breadarr/${VERSION}" + if [ -n "${MINISIGN_SEC_KEY:-}" ]; then + for bin in breadarrd breadarr-tui; do + minisign -W -S -s "${MINISIGN_SEC_KEY}" -m "${PKG_DIR}/${bin}-x86_64" \ + -x "${PKG_DIR}/${bin}-x86_64.minisig" /dev/null || true + # mktemp: a fixed clone path races when multiple repos' dev/rc + # workflows run close together on the same self-hosted runner. + ECOSYSTEM_CI_DIR="$(mktemp -d /tmp/bread-ecosystem-ci-XXXXXX)" + git clone https://git.breadway.dev/Breadway/bread-ecosystem.git "${ECOSYSTEM_CI_DIR}" + TRACK=beta bash "${ECOSYSTEM_CI_DIR}/scripts/gen-index.sh" + rm -rf "${ECOSYSTEM_CI_DIR}" diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml new file mode 100644 index 0000000..692002c --- /dev/null +++ b/.forgejo/workflows/release.yml @@ -0,0 +1,79 @@ +name: release + +on: + push: + tags: ['v*'] + +jobs: + build: + if: ${{ !contains(github.ref_name, '-rc.') }} + runs-on: [self-hosted, hestia] + steps: + - name: checkout + run: | + set -euo pipefail + rm -rf src && mkdir src + git clone --branch "${GITHUB_REF_NAME}" --depth 1 \ + "https://git.breadway.dev/${GITHUB_REPOSITORY}.git" src + + - name: build + run: cd src && cargo build --release --locked + + - name: prepare artifacts + run: | + set -euo pipefail + VERSION="${GITHUB_REF_NAME#v}" + PKG_DIR="/srv/breadway-dl/breadarr/${VERSION}" + mkdir -p "${PKG_DIR}" + for bin in breadarrd breadarr-tui; do + cp "src/target/release/${bin}" "${PKG_DIR}/${bin}-x86_64" + strip "${PKG_DIR}/${bin}-x86_64" + sha256sum "${PKG_DIR}/${bin}-x86_64" | awk '{print $1}' \ + > "${PKG_DIR}/${bin}-x86_64.sha256" + done + cp src/packaging/systemd/breadarrd.service "${PKG_DIR}/" + cp src/bakery.toml "${PKG_DIR}/bakery.toml" + ln -sfn "${VERSION}" "/srv/breadway-dl/breadarr/latest" + + # Signs with the shared bakery ecosystem signing key (same key that + # signs index.json). BAKERY_MINISIGN_SEC_KEY_PATH is a *path on this + # runner's disk* (hestia has persistent storage), not the key + # contents. Dormant (binaries ship unsigned) until that secret is + # provisioned for this repo. + - name: sign release binaries + env: + MINISIGN_SEC_KEY: ${{ secrets.BAKERY_MINISIGN_SEC_KEY_PATH }} + run: | + set -euo pipefail + VERSION="${GITHUB_REF_NAME#v}" + PKG_DIR="/srv/breadway-dl/breadarr/${VERSION}" + if [ -n "${MINISIGN_SEC_KEY:-}" ]; then + for bin in breadarrd breadarr-tui; do + minisign -W -S -s "${MINISIGN_SEC_KEY}" -m "${PKG_DIR}/${bin}-x86_64" \ + -x "${PKG_DIR}/${bin}-x86_64.minisig" /dev/null || true + # mktemp: a fixed clone path races when multiple repos' release + # workflows run close together on the same self-hosted runner. + ECOSYSTEM_CI_DIR="$(mktemp -d /tmp/bread-ecosystem-ci-XXXXXX)" + git clone https://git.breadway.dev/Breadway/bread-ecosystem.git "${ECOSYSTEM_CI_DIR}" + bash "${ECOSYSTEM_CI_DIR}/scripts/gen-index.sh" + rm -rf "${ECOSYSTEM_CI_DIR}" + + # No GitHub Release upload step — breadarr has no GitHub mirror, + # unlike most sibling bread-ecosystem repos. dl.breadway.dev is the + # only distribution point for this repo. diff --git a/bakery.toml b/bakery.toml new file mode 100644 index 0000000..e976440 --- /dev/null +++ b/bakery.toml @@ -0,0 +1,44 @@ +name = "breadarr" +description = "Single-daemon Sonarr+Radarr+Prowlarr replacement — release watching, matching, grabbing, importing, and a terminal UI, no web UI" +binaries = ["breadarrd", "breadarr-tui"] +# mkvtoolnix-cli / ffmpeg: `mkvmerge` and `ffprobe`/`ffmpeg` are shelled out +# to directly via Command::new() (breadarrd/src/importer/mkv.rs for the +# audio-track remux fix; breadarrd/src/importer/ffprobe.rs and +# breadarrd/src/transcode/mod.rs for media probing/corruption verification/ +# transcode-backlog work) rather than linked, so neither shows up in +# `ldd target/release/breadarrd` -- confirmed by grepping breadarrd/src for +# Command::new("mkvmerge"|"ffprobe"|"ffmpeg") and cross-checking against the +# README's own host-requirements instructions. The ONNX embedding model (the +# `ort` crate, used for fuzzy title matching) needs no system_deps entry: +# `ldd target/release/breadarrd` lists no libonnxruntime.so, and `strings` +# on the built binary is full of onnxruntime's own C++ symbol names -- +# confirming the `ort` crate's default strategy statically bundled its own +# onnxruntime build directly into breadarrd rather than dynamically linking +# the system onnxruntime-cpu package. openssl: libssl.so.3/libcrypto.so.3 +# (reqwest's TLS backend) show up directly in `ldd` for both breadarrd and +# breadarr-tui. libstdc++/libgcc/glibc/zlib/zstd/brotli also appear in +# `ldd` but are omitted here the same way breadcast's bakery.toml omits +# them: glibc/gcc-libs are unavoidable base-system dependencies, and +# zlib/zstd/brotli are themselves transitive deps of openssl/curl/pacman +# already guaranteed present on any real Arch install. +system_deps = [ + "mkvtoolnix-cli", + "ffmpeg", + "openssl", +] +optional_system_deps = [] +bread_deps = [] +license_file = "LICENSE" + +[[service]] +unit = "breadarrd.service" +enable = true + +[config] +dir = "~/.config/breadarr" +example = "config.example.toml" + +[install] +post_install = [ + "systemctl --user is-active --quiet breadarrd || systemctl --user start breadarrd", +]