## Summary
- Move Dagger module from `.dagger/` to repo root (`src/blumeops/`), rename `blumeops-ci` → `blumeops`
- Replace opaque `docker_build()` with native Dagger pipelines that surface full build errors per step
- Migrate navidrome as the first container (`containers/navidrome/container.py`)
- Upgrade navidrome from v0.60.3 to v0.61.1 (major artwork overhaul, SQLite FTS5 search, server-managed transcoding)
- Add `dagger call container-version` for CI version extraction without Dockerfile parsing
- All mise tasks (`container-list`, `container-version-check`, `container-build-and-release`) updated for hybrid mode
- Legacy `docker_build()` fallback preserved for all other containers
## Motivation
When navidrome v0.61.0 added a new Go build tag (`sqlite_fts5`), `docker_build()` showed only "exit code: 1". We had to run `docker build --progress=plain` manually to find `undefined: buildtags.SQLITE_FTS5`. Native Dagger pipelines show the full error inline.
## Container build dispatch needed
After merge, dispatch container build for navidrome:
```
mise run container-build-and-release navidrome --ref 470b4bd
```
## Deploy steps
1. Wait for container build to complete
2. Back up navidrome-data PVC (non-reversible DB migrations)
3. `argocd app set navidrome --revision main && argocd app sync navidrome`
4. Verify at https://dj.ops.eblu.me
## Future
Remaining containers migrate incrementally in follow-up PRs using the same pattern.
Reviewed-on: #330
54 lines
1.4 KiB
Python
54 lines
1.4 KiB
Python
"""Navidrome music server — native Dagger build.
|
|
|
|
Three-stage build: Node (UI), Go (backend with taglib + FTS5), Alpine (runtime).
|
|
Source cloned from forge mirror.
|
|
"""
|
|
|
|
import dagger
|
|
|
|
from blumeops.containers import (
|
|
alpine_runtime,
|
|
clone_from_forge,
|
|
go_build,
|
|
node_build,
|
|
oci_labels,
|
|
)
|
|
|
|
VERSION = "v0.61.1"
|
|
|
|
|
|
async def build(src: dagger.Directory) -> dagger.Container:
|
|
source = clone_from_forge("navidrome", VERSION)
|
|
|
|
# Stage 1: Build UI assets
|
|
ui = node_build(source, "ui")
|
|
|
|
# Stage 2: Build Go backend with CGO (taglib) and FTS5
|
|
backend = go_build(
|
|
source.with_directory("ui/build", ui.directory("/app/ui/build")),
|
|
"/navidrome",
|
|
tags="netgo,sqlite_fts5",
|
|
ldflags=f"-w -s -X github.com/navidrome/navidrome/consts.gitTag={VERSION}",
|
|
cgo_enabled=True,
|
|
extra_apk=["taglib-dev", "zlib-dev"],
|
|
)
|
|
|
|
# Stage 3: Runtime
|
|
runtime = alpine_runtime(
|
|
extra_apk=["ca-certificates", "tzdata", "taglib", "ffmpeg"],
|
|
uid=1000,
|
|
gid=1000,
|
|
username="navidrome",
|
|
)
|
|
runtime = oci_labels(
|
|
runtime,
|
|
title="Navidrome",
|
|
description="Navidrome is a self-hosted music server and streamer",
|
|
version=VERSION,
|
|
)
|
|
return (
|
|
runtime.with_file("/usr/bin/navidrome", backend.file("/navidrome"))
|
|
.with_exposed_port(4533)
|
|
.with_user("1000")
|
|
.with_default_args(args=["/usr/bin/navidrome"])
|
|
)
|