Files
alertmanager-gotify-bridge/flake.nix
T
2026-06-04 23:29:06 +03:00

135 lines
5.5 KiB
Nix

{
description = "alertmanager-gotify-bridge pure-stdlib Python forwarder, containerized with Nix (nix2container), multi-arch via the shared parity-lib OCI builder.";
# ──────────────────────────────────────────────────────────────────────────
# LOCAL-PIPELINE PARITY (cluster #192, emmett#44). Archetype: nix2container OCI
# image (NOT a buildkit/escape-hatch repo — the whole payload is Nix-
# expressible). The payload is pure-stdlib `bridge.py` next to a stock CPython
# closure, so BOTH arches build on emmett with no buildkit / qemu / docker:
# amd64 = native, arm64 = pkgsCross of stock python3 from the binary cache.
# The per-arch image derivations are kept verbatim; the stage/publish/
# publish-index/publish/push-staged apps come from parity-lib's
# mkNix2ContainerPublish so CI and local invoke the SAME code and cannot drift.
# ci/MIGRATION.md is the design history.
# ──────────────────────────────────────────────────────────────────────────
inputs = {
fleet.url = "git+https://git.oleks.space/oleks/fleet-pins";
nixpkgs.follows = "fleet/nixpkgs-projects";
nix2container.url = "github:nlewo/nix2container";
nix2container.inputs.nixpkgs.follows = "nixpkgs";
parity.url = "git+https://git.oleks.space/oleks/parity-lib";
flake-utils.url = "github:numtide/flake-utils";
};
outputs =
{
nixpkgs,
nix2container,
parity,
flake-utils,
...
}:
flake-utils.lib.eachDefaultSystem (
system:
let
pkgs = import nixpkgs { inherit system; };
n2c = nix2container.packages.${system}.nix2container;
registry = "git.oleks.space/oleks/alertmanager-gotify-bridge";
# TAG is derived in shared code: CI exports CI_COMMIT_TAG (parity-lib
# strips the leading v / trailing -N), local dev may override $VERSION.
# No version.nix side-channel — the app is a static asset with no
# version-baked source build, so the tag lives purely in $VERSION/tag.
version = "0.0.0-dev";
# The whole payload: bridge.py + a python3 interpreter symlink under /app.
# The symlink keeps the (arch-correct) python3 Nix closure tracked while
# contributing no extra files. Parameterised over a pkg set so the SAME
# expression builds natively (amd64) and cross (arm64).
appRoot =
targetPkgs: arch:
pkgs.runCommand "app-root-${arch}" { } ''
mkdir -p $out/app
cp ${./bridge.py} $out/app/bridge.py
ln -s ${targetPkgs.python3}/bin/python3 $out/app/python3
'';
mkImage =
targetPkgs: arch:
n2c.buildImage {
name = registry;
tag = "${version}-${arch}";
inherit arch;
# reproducible = false materializes the layer tar so the image streams
# verbatim from any host (remote-builder + binary-cache safe). For a
# pure-stdlib interpreter closure the determinism risk is low, but the
# standard's caveat still applies: emmett+CI must resolve the identical
# python3 store path from the shared cache (fleet pin + flake.lock).
layers = [
(n2c.buildLayer {
copyToRoot = [
(appRoot targetPkgs arch)
pkgs.cacert
];
maxLayers = 25;
reproducible = false;
})
];
config = {
Cmd = [
"/app/python3"
"/app/bridge.py"
];
WorkingDir = "/app";
ExposedPorts = {
"8080/tcp" = { };
};
Env = [
"PORT=8080"
# urllib → Gotify over HTTPS needs an explicit CA bundle (the old
# Alpine base provided one via the distro; the Nix image ships it).
"SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt"
];
};
};
# amd64 = native; arm64 = cross-compiled (stock python3 closure from the
# binary cache, no qemu). Both are buildable on emmett (amd64).
imageAmd64 = mkImage pkgs "amd64";
imageArm64 = mkImage pkgs.pkgsCross.aarch64-multiplatform "arm64";
# ── Publish apps: shared parity-lib nix2container builder (cluster #192).
# Yields stage-<arch> / publish-<arch> / publish-index / publish /
# push-staged. copy-to (skopeo) pushes per-arch, regctl assembles the
# index; no buildkit / docker daemon. Dry-run by default (--publish to
# push); token from $REGISTRY_TOKEN (CI from_secret) → pass fallback,
# never echoed.
builders = parity.lib.mkParityBuilders pkgs;
publishApps = builders.mkNix2ContainerPublish {
imageName = registry;
inherit version;
images = {
amd64.copyTo = imageAmd64.copyTo;
arm64.copyTo = imageArm64.copyTo;
};
};
in
{
packages = {
image-amd64 = imageAmd64;
image-arm64 = imageArm64;
default = imageAmd64;
};
apps = publishApps;
formatter = pkgs.nixfmt-rfc-style;
}
);
}