From 99480ce4f3735c84ead4b3ff1bb64e34bdac1d24 Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Sun, 12 Apr 2026 08:22:57 -0700 Subject: [PATCH 1/4] Miniflux 2.2.19 upgrade, container.py migration, ty typechecker, mise version tracking - Upgrade miniflux from 2.2.17 to 2.2.19 (SSRF hardening, performance) - Migrate miniflux from Dockerfile to native Dagger container.py build - Refactor alpine_runtime() with create_user param for existing users - Add ty Python typechecker to prek hooks with Dagger SDK config - Pin all mise.toml tool versions (no more "latest") - Add type: mise to service-versions.yaml for development tool tracking - Add mise-specific review guidance to service-review script and docs Co-Authored-By: Claude Opus 4.6 (1M context) --- containers/miniflux/Dockerfile | 35 ----------- containers/miniflux/container.py | 61 +++++++++++++++++++ .../miniflux-upgrade-and-ty.infra.md | 1 + docs/how-to/knowledgebase/review-services.md | 14 ++++- mise-tasks/service-review | 9 ++- mise.toml | 7 ++- prek.toml | 12 ++++ pyproject.toml | 7 +++ service-versions.yaml | 43 ++++++++++++- src/blumeops/containers.py | 22 ++++--- 10 files changed, 159 insertions(+), 52 deletions(-) delete mode 100644 containers/miniflux/Dockerfile create mode 100644 containers/miniflux/container.py create mode 100644 docs/changelog.d/miniflux-upgrade-and-ty.infra.md diff --git a/containers/miniflux/Dockerfile b/containers/miniflux/Dockerfile deleted file mode 100644 index 4e987cc..0000000 --- a/containers/miniflux/Dockerfile +++ /dev/null @@ -1,35 +0,0 @@ -# Miniflux RSS feed reader -# Based on upstream packaging/docker/alpine/Dockerfile - -ARG CONTAINER_APP_VERSION=2.2.17 -ARG MINIFLUX_VERSION=${CONTAINER_APP_VERSION} - -FROM golang:alpine3.22 AS build - -ARG MINIFLUX_VERSION -RUN apk add --no-cache build-base git make - -# Clone specific version -RUN git clone --depth 1 --branch ${MINIFLUX_VERSION} \ - https://forge.ops.eblu.me/mirrors/miniflux.git /go/src/app - -WORKDIR /go/src/app -RUN make miniflux - -FROM alpine:3.22 - -ARG CONTAINER_APP_VERSION -LABEL org.opencontainers.image.title="Miniflux" -LABEL org.opencontainers.image.description="Miniflux is a minimalist and opinionated feed reader" -LABEL org.opencontainers.image.version="${CONTAINER_APP_VERSION}" -LABEL org.opencontainers.image.source="https://forge.eblu.me/eblume/blumeops" -LABEL org.opencontainers.image.vendor="blumeops" - -EXPOSE 8080 -ENV LISTEN_ADDR=0.0.0.0:8080 - -RUN apk --no-cache add ca-certificates tzdata -COPY --from=build /go/src/app/miniflux /usr/bin/miniflux - -USER 65534 -CMD ["/usr/bin/miniflux"] diff --git a/containers/miniflux/container.py b/containers/miniflux/container.py new file mode 100644 index 0000000..ef2050a --- /dev/null +++ b/containers/miniflux/container.py @@ -0,0 +1,61 @@ +"""Miniflux RSS feed reader — native Dagger build. + +Two-stage build: Go (backend with PIE), Alpine (runtime). +Source cloned from forge mirror. +""" + +import dagger +from dagger import dag + +from blumeops.containers import ( + alpine_runtime, + clone_from_forge, + oci_labels, +) + +VERSION = "2.2.19" + + +async def build(src: dagger.Directory) -> dagger.Container: + source = clone_from_forge("miniflux", VERSION) + + # Stage 1: Build Go backend (PIE mode, matching upstream Makefile) + ldflags = f"-s -w -X 'miniflux.app/v2/internal/version.Version={VERSION}'" + backend = ( + dag.container() + .from_("golang:alpine3.22") + .with_exec(["apk", "add", "--no-cache", "build-base", "git"]) + .with_directory("/app", source) + .with_workdir("/app") + .with_env_variable("CGO_ENABLED", "1") + .with_exec( + [ + "go", + "build", + "-buildmode=pie", + f"-ldflags={ldflags}", + "-o", + "/miniflux", + ".", + ] + ) + ) + + # Stage 2: Runtime (uses Alpine's built-in nobody:65534) + runtime = alpine_runtime( + extra_apk=["ca-certificates", "tzdata"], + create_user=False, + ) + runtime = oci_labels( + runtime, + title="Miniflux", + description="Miniflux is a minimalist and opinionated feed reader", + version=VERSION, + ) + return ( + runtime.with_file("/usr/bin/miniflux", backend.file("/miniflux")) + .with_exposed_port(8080) + .with_env_variable("LISTEN_ADDR", "0.0.0.0:8080") + .with_user("65534") + .with_default_args(args=["/usr/bin/miniflux"]) + ) diff --git a/docs/changelog.d/miniflux-upgrade-and-ty.infra.md b/docs/changelog.d/miniflux-upgrade-and-ty.infra.md new file mode 100644 index 0000000..4e53c28 --- /dev/null +++ b/docs/changelog.d/miniflux-upgrade-and-ty.infra.md @@ -0,0 +1 @@ +Upgrade miniflux to 2.2.19 with native Dagger container.py build (second container migrated from Dockerfile). Add `ty` Python typechecker to prek hooks. Pin all mise.toml tool versions and track them as `type: mise` in service-versions.yaml. Refactor `alpine_runtime()` to support existing users via `create_user=False`. diff --git a/docs/how-to/knowledgebase/review-services.md b/docs/how-to/knowledgebase/review-services.md index 43615fb..f995d1a 100644 --- a/docs/how-to/knowledgebase/review-services.md +++ b/docs/how-to/knowledgebase/review-services.md @@ -1,7 +1,7 @@ --- title: Review Services -modified: 2026-03-24 -last-reviewed: 2026-03-07 +modified: 2026-04-12 +last-reviewed: 2026-04-12 tags: - how-to - maintenance @@ -66,6 +66,16 @@ Versioned NixOS services (forgejo-runner, snowflake, k3s) are pinned via a `nixp 4. Deploy via `mise run provision-ringtail` 5. Update `service-versions.yaml` with the new version +### Mise Tools (`type: mise`) + +Development tools managed via `mise.toml` with pinned versions. These are local CLI tools (dagger, pulumi, prek, ty, ansible-core) rather than deployed services. + +1. Check the upstream releases page for new versions +2. Review the changelog for breaking changes +3. Update the pinned version in `mise.toml` +4. Run `mise install` to verify the new version installs correctly +5. Update `service-versions.yaml` with the new version + ### Private Forge Repos (`upstream-source` under `forge.eblu.me/eblume/`) Some services are built from private repos on the forge rather than tracking an external upstream project. When `upstream-source` points to a `forge.eblu.me/eblume/` repo: diff --git a/mise-tasks/service-review b/mise-tasks/service-review index 92bac53..01c4ce0 100755 --- a/mise-tasks/service-review +++ b/mise-tasks/service-review @@ -5,7 +5,7 @@ # /// #MISE description="Review the most stale service for version freshness" #USAGE flag "--limit " default="15" help="Number of services to show in the table" -#USAGE flag "--type " help="Filter by service type (argocd, ansible, nixos)" +#USAGE flag "--type " help="Filter by service type (argocd, ansible, nixos, fly, mise)" """Review the most stale service for version freshness. Reads ``docs/reference/services/service-versions.yaml`` and sorts services @@ -197,6 +197,13 @@ def main( "• Update: dagger call flake-update --src=. export --path=nixos/ringtail/flake.lock\n", "• Deploy: mise run provision-ringtail\n", ] + elif svc_type == "mise": + checklist_parts += [ + "\n[bold]Mise Tool Update:[/bold]\n", + "• Update pinned version in mise.toml\n", + "• Run: mise install to verify\n", + "• Check for breaking changes in release notes\n", + ] checklist_parts += [ "\n[bold]Health Check:[/bold]\n", diff --git a/mise.toml b/mise.toml index 5bb2829..a5bad84 100644 --- a/mise.toml +++ b/mise.toml @@ -1,5 +1,6 @@ [tools] -"pipx:ansible-core" = { version = "latest", uvx = "true", uvx_args = "--with botocore --with boto3" } -prek = "latest" -pulumi = "latest" +"pipx:ansible-core" = { version = "2.20.1", uvx = "true", uvx_args = "--with botocore --with boto3" } +prek = "0.3.4" +pulumi = "3.215.0" dagger = "0.20.1" +ty = "0.0.29" diff --git a/prek.toml b/prek.toml index 7f0f9ab..191629a 100644 --- a/prek.toml +++ b/prek.toml @@ -77,6 +77,18 @@ repo = "https://github.com/astral-sh/ruff-pre-commit" rev = "v0.15.7" hooks = [{ id = "ruff", args = ["--fix"] }, { id = "ruff-format" }] +# Python - ty type checker +[[repos]] +repo = "local" + +[[repos.hooks]] +id = "ty-check" +name = "ty type check" +entry = "mise x ty -- ty check" +language = "system" +types = ["python"] +pass_filenames = false + # Shell scripts - shellcheck and shfmt [[repos]] repo = "https://github.com/shellcheck-py/shellcheck-py" diff --git a/pyproject.toml b/pyproject.toml index 8b6cf8e..f612759 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,3 +10,10 @@ build-backend = "uv_build" [tool.uv.sources] dagger-io = { path = "sdk", editable = true } + +[tool.ty.environment] +python-version = "3.13" +extra-paths = ["sdk/src"] + +[tool.ty.src] +exclude = ["pulumi/", "containers/transmission-exporter/"] diff --git a/service-versions.yaml b/service-versions.yaml index 1250698..50f167d 100644 --- a/service-versions.yaml +++ b/service-versions.yaml @@ -5,7 +5,7 @@ # # Fields: # name - kebab-case service identifier -# type - argocd | ansible | nixos | fly +# type - argocd | ansible | nixos | fly | mise # last-reviewed - date (YYYY-MM-DD) or null # current-version - deployed version string or null # upstream-source - URL to upstream releases/changelog @@ -184,8 +184,8 @@ services: - name: miniflux type: argocd - last-reviewed: 2026-03-02 - current-version: "2.2.17" + last-reviewed: 2026-04-12 + current-version: "2.2.19" upstream-source: https://github.com/miniflux/v2/releases - name: teslamate @@ -393,3 +393,40 @@ services: current-version: "v1.14.1" upstream-source: https://github.com/grafana/alloy/releases notes: COPY --from in fly/Dockerfile for log shipping and metrics + + # --- Mise-managed development tools --- + + - name: dagger + type: mise + last-reviewed: 2026-04-12 + current-version: "0.20.1" + upstream-source: https://github.com/dagger/dagger/releases + notes: Dagger CI/CD engine; pinned in mise.toml + + - name: ansible-core + type: mise + last-reviewed: 2026-04-12 + current-version: "2.20.1" + upstream-source: https://github.com/ansible/ansible/releases + notes: Installed via pipx/uvx with botocore and boto3 + + - name: prek + type: mise + last-reviewed: 2026-04-12 + current-version: "0.3.4" + upstream-source: https://github.com/j178/prek/releases + notes: Pre-commit hook runner (Rust reimplementation) + + - name: pulumi-cli + type: mise + last-reviewed: 2026-04-12 + current-version: "3.215.0" + upstream-source: https://github.com/pulumi/pulumi/releases + notes: IaC CLI for tailscale and gandi stacks + + - name: ty + type: mise + last-reviewed: 2026-04-12 + current-version: "0.0.29" + upstream-source: https://github.com/astral-sh/ty/releases + notes: Astral Python typechecker (beta); prek hook diff --git a/src/blumeops/containers.py b/src/blumeops/containers.py index 728129f..4805c5c 100644 --- a/src/blumeops/containers.py +++ b/src/blumeops/containers.py @@ -131,20 +131,26 @@ def alpine_runtime( uid: int = 65534, gid: int = 65534, username: str = "app", + create_user: bool = True, ) -> dagger.Container: - """Standard Alpine 3.22 runtime base with non-root user.""" + """Standard Alpine 3.22 runtime base. + + When create_user is True (default), creates a non-root user with the given + uid/gid/username. Set create_user=False to use an existing user (e.g. + Alpine's built-in nobody:65534). + """ packages = extra_apk or [] setup_cmds = [] if packages: setup_cmds.append(f"apk add --no-cache {' '.join(packages)}") - setup_cmds.append(f"addgroup -g {gid} {username}") - setup_cmds.append(f"adduser -u {uid} -G {username} -D {username}") + if create_user: + setup_cmds.append(f"addgroup -g {gid} {username}") + setup_cmds.append(f"adduser -u {uid} -G {username} -D {username}") - return ( - dag.container() - .from_("alpine:3.22") - .with_exec(["sh", "-c", " && ".join(setup_cmds)]) - ) + ctr = dag.container().from_("alpine:3.22") + if setup_cmds: + ctr = ctr.with_exec(["sh", "-c", " && ".join(setup_cmds)]) + return ctr def oci_labels( From e08c95c5fb4202a3e71afdd7896a3408c11de539 Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Sun, 12 Apr 2026 08:23:13 -0700 Subject: [PATCH 2/4] Revert prek ty hook to bare 'ty check' (mise shims handle PATH in normal shells) Co-Authored-By: Claude Opus 4.6 (1M context) --- prek.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prek.toml b/prek.toml index 191629a..28776c5 100644 --- a/prek.toml +++ b/prek.toml @@ -84,7 +84,7 @@ repo = "local" [[repos.hooks]] id = "ty-check" name = "ty type check" -entry = "mise x ty -- ty check" +entry = "ty check" language = "system" types = ["python"] pass_filenames = false From 2b72ef7b74270225cc19c158405792fedb9a449f Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Sun, 12 Apr 2026 08:43:14 -0700 Subject: [PATCH 3/4] Deploy miniflux 2.2.19 from branch build (v2.2.19-e08c95c) Co-Authored-By: Claude Opus 4.6 (1M context) --- argocd/manifests/miniflux/kustomization.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/argocd/manifests/miniflux/kustomization.yaml b/argocd/manifests/miniflux/kustomization.yaml index 8207d55..9105d42 100644 --- a/argocd/manifests/miniflux/kustomization.yaml +++ b/argocd/manifests/miniflux/kustomization.yaml @@ -10,4 +10,4 @@ resources: images: - name: registry.ops.eblu.me/blumeops/miniflux - newTag: v2.2.17-613f05d + newTag: v2.2.19-e08c95c From 2787aacf456092037f2c21db156bfd9a14e2a256 Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Sun, 12 Apr 2026 08:54:06 -0700 Subject: [PATCH 4/4] Split changelog into infra and feature fragments Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/changelog.d/miniflux-upgrade-and-ty.feature.md | 1 + docs/changelog.d/miniflux-upgrade-and-ty.infra.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 docs/changelog.d/miniflux-upgrade-and-ty.feature.md diff --git a/docs/changelog.d/miniflux-upgrade-and-ty.feature.md b/docs/changelog.d/miniflux-upgrade-and-ty.feature.md new file mode 100644 index 0000000..fa88736 --- /dev/null +++ b/docs/changelog.d/miniflux-upgrade-and-ty.feature.md @@ -0,0 +1 @@ +Add `ty` (Astral) Python typechecker to prek hooks, configured for Dagger SDK and container.py modules. Add `type: mise` to service-versions.yaml for tracking development tool versions (dagger, ansible-core, prek, pulumi, ty) through the standard service review process. diff --git a/docs/changelog.d/miniflux-upgrade-and-ty.infra.md b/docs/changelog.d/miniflux-upgrade-and-ty.infra.md index 4e53c28..1c124f5 100644 --- a/docs/changelog.d/miniflux-upgrade-and-ty.infra.md +++ b/docs/changelog.d/miniflux-upgrade-and-ty.infra.md @@ -1 +1 @@ -Upgrade miniflux to 2.2.19 with native Dagger container.py build (second container migrated from Dockerfile). Add `ty` Python typechecker to prek hooks. Pin all mise.toml tool versions and track them as `type: mise` in service-versions.yaml. Refactor `alpine_runtime()` to support existing users via `create_user=False`. +Upgrade miniflux from 2.2.17 to 2.2.19 and migrate from Dockerfile to native Dagger container.py build (second container after navidrome). Refactor `alpine_runtime()` with `create_user` parameter to support Alpine's built-in nobody user. Pin all mise.toml tool versions to explicit versions instead of "latest".