feat(parity): switch to nix2container + consume mkNix2ContainerPublish (#201)
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/push/woodpecker Pipeline failed
Replaces dockerTools.streamLayeredImage (no .copyTo) with nix2container buildImage so angie consumes the shared parity-lib mkNix2ContainerPublish (stage/publish/publish-index/push-staged/verify-digest) instead of inline skopeo/token/guard. Image content preserved (angie + conf-dir + runtime dirs, runs as root); .woodpecker.yaml thinned to nix run .#publish. Tags move from :latest-arm64 to :<ver>-arm64 + index :<ver>/:latest (no consumer pinned :latest-arm64). pipeline-doctor --strict 9/9.
This commit is contained in:
+5
-4
@@ -45,7 +45,8 @@ steps:
|
|||||||
EOF
|
EOF
|
||||||
- if [ -n "$GITEA_CLONE_TOKEN" ]; then echo "machine git.oleks.space login oleks password $GITEA_CLONE_TOKEN" >~/.netrc && chmod 600 ~/.netrc; fi
|
- if [ -n "$GITEA_CLONE_TOKEN" ]; then echo "machine git.oleks.space login oleks password $GITEA_CLONE_TOKEN" >~/.netrc && chmod 600 ~/.netrc; fi
|
||||||
|
|
||||||
# Thin front door: CI and `nix run .#publish-arm64` on emmett run the
|
# Thin front door: CI and `nix run .#publish` on emmett run the exact
|
||||||
# exact same shared app (emmett#44, archetype oci-image-skopeo). The app
|
# same shared parity-lib nix2container app (emmett#44, cluster #201).
|
||||||
# is dry-run by default; PUBLISH=1 makes it actually push.
|
# `.#publish` pushes :<ver>-arm64, assembles the index :<ver>, and mirrors
|
||||||
- PUBLISH=1 nix run .#publish-arm64
|
# :latest. Dry-run by default; PUBLISH=1 makes it actually push.
|
||||||
|
- PUBLISH=1 nix run .#publish
|
||||||
|
|||||||
Generated
+159
-1
@@ -1,5 +1,106 @@
|
|||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1731533236,
|
||||||
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fleet": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs_2",
|
||||||
|
"nixpkgs-armer": [
|
||||||
|
"parity",
|
||||||
|
"fleet",
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"nixpkgs-bim": [
|
||||||
|
"parity",
|
||||||
|
"fleet",
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"nixpkgs-ci": [
|
||||||
|
"parity",
|
||||||
|
"fleet",
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"nixpkgs-emmett": [
|
||||||
|
"parity",
|
||||||
|
"fleet",
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"nixpkgs-howard": [
|
||||||
|
"parity",
|
||||||
|
"fleet",
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"nixpkgs-mermaid": [
|
||||||
|
"parity",
|
||||||
|
"fleet",
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"nixpkgs-mermaid-gpu": [
|
||||||
|
"parity",
|
||||||
|
"fleet",
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"nixpkgs-micron": [
|
||||||
|
"parity",
|
||||||
|
"fleet",
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"nixpkgs-projects": [
|
||||||
|
"parity",
|
||||||
|
"fleet",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1779533061,
|
||||||
|
"narHash": "sha256-orWNYXtYURhEj3X4+xGMAhaEcKRvwXqTtJ8x2jV/M+Q=",
|
||||||
|
"ref": "refs/heads/main",
|
||||||
|
"rev": "b818e345ec4470e4b3e335bd2f864183c512116d",
|
||||||
|
"revCount": 13,
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.oleks.space/oleks/fleet-pins"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.oleks.space/oleks/fleet-pins"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nix2container": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1775487831,
|
||||||
|
"narHash": "sha256-2lguQpLPQaxpQCJjXhmEEAfabwsAhkP29Z7fgLzHARA=",
|
||||||
|
"owner": "nlewo",
|
||||||
|
"repo": "nix2container",
|
||||||
|
"rev": "76be9608a7f4d6c985d28b0e7be903ae2547df3e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nlewo",
|
||||||
|
"repo": "nix2container",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1777954456,
|
"lastModified": 1777954456,
|
||||||
@@ -16,9 +117,66 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"nixpkgs_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1777268161,
|
||||||
|
"narHash": "sha256-bxrdOn8SCOv8tN4JbTF/TXq7kjo9ag4M+C8yzzIRYbE=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "1c3fe55ad329cbcb28471bb30f05c9827f724c76",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "1c3fe55ad329cbcb28471bb30f05c9827f724c76",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parity": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"fleet": "fleet",
|
||||||
|
"nixpkgs": [
|
||||||
|
"parity",
|
||||||
|
"fleet",
|
||||||
|
"nixpkgs-ci"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1780597793,
|
||||||
|
"narHash": "sha256-TGFRv37oEyJY96Ax+oHK05cttGUuf9tifrRh/AQiiXs=",
|
||||||
|
"ref": "refs/heads/main",
|
||||||
|
"rev": "413f78c365d2d433f3f74cfc59c146de87097b1f",
|
||||||
|
"revCount": 12,
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.oleks.space/oleks/parity-lib"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.oleks.space/oleks/parity-lib"
|
||||||
|
}
|
||||||
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": "nixpkgs"
|
"nix2container": "nix2container",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"parity": "parity"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,13 +1,24 @@
|
|||||||
{
|
{
|
||||||
description = "Angie web server (aarch64) — OCI image for Gitea registry";
|
description = "Angie web server (aarch64) — OCI image for Gitea registry";
|
||||||
|
|
||||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
nix2container.url = "github:nlewo/nix2container";
|
||||||
|
nix2container.inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
parity.url = "git+https://git.oleks.space/oleks/parity-lib";
|
||||||
|
};
|
||||||
|
|
||||||
outputs =
|
outputs =
|
||||||
{ self, nixpkgs }:
|
{
|
||||||
|
nixpkgs,
|
||||||
|
nix2container,
|
||||||
|
parity,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
system = "aarch64-linux";
|
system = "aarch64-linux";
|
||||||
pkgs = import nixpkgs { inherit system; };
|
pkgs = import nixpkgs { inherit system; };
|
||||||
|
n2c = nix2container.packages.${system}.nix2container;
|
||||||
|
|
||||||
# nixpkgs ships angie compiled against `--prefix=/etc/angie` and
|
# nixpkgs ships angie compiled against `--prefix=/etc/angie` and
|
||||||
# `--http-log-path=/var/log/angie/access.log`; the package's `bin/angie`
|
# `--http-log-path=/var/log/angie/access.log`; the package's `bin/angie`
|
||||||
@@ -41,29 +52,43 @@
|
|||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
image = pkgs.dockerTools.streamLayeredImage {
|
# The image root extra: /etc/angie (the bundled conf-dir + our main config)
|
||||||
name = "angie";
|
# plus the runtime dirs angie expects to exist. angie runs as root and the
|
||||||
|
# container gets a writable upper layer, so the dirs only need to EXIST —
|
||||||
|
# no sticky/1777 perms needed (this replaces streamLayeredImage's
|
||||||
|
# extraCommands, which did the same mkdir + cp of the angie conf-dir).
|
||||||
|
rootExtra = pkgs.runCommand "angie-root" { } ''
|
||||||
|
mkdir -p $out/var/log/nginx $out/var/cache/angie $out/var/lib/angie \
|
||||||
|
$out/run $out/tmp $out/etc/angie/http.d
|
||||||
|
cp ${angie}/conf/* $out/etc/angie/
|
||||||
|
chmod -R u+w $out/etc/angie
|
||||||
|
cp -f ${mainConf} $out/etc/angie/angie.conf
|
||||||
|
'';
|
||||||
|
|
||||||
|
# OCI image via nix2container (cluster #201): yields `.copyTo` (skopeo) so
|
||||||
|
# it consumes the shared parity-lib mkNix2ContainerPublish — no buildkit,
|
||||||
|
# no inline skopeo/token/guard. Replaces dockerTools.streamLayeredImage.
|
||||||
|
image = n2c.buildImage {
|
||||||
|
name = "git.oleks.space/oleks/angie";
|
||||||
tag = angie.version;
|
tag = angie.version;
|
||||||
contents = with pkgs; [
|
arch = "arm64";
|
||||||
angie
|
layers = [
|
||||||
cacert
|
(n2c.buildLayer {
|
||||||
dockerTools.fakeNss
|
copyToRoot = [
|
||||||
coreutils
|
rootExtra
|
||||||
bash
|
angie
|
||||||
|
pkgs.cacert
|
||||||
|
pkgs.dockerTools.fakeNss
|
||||||
|
pkgs.coreutils
|
||||||
|
pkgs.bash
|
||||||
|
];
|
||||||
|
maxLayers = 25;
|
||||||
|
# reproducible = false materializes the layer tar so the image streams
|
||||||
|
# verbatim from any host (remote-builder + binary-cache safe); parity
|
||||||
|
# is asserted at the OCI manifest DIGEST (nix run .#verify-digest, #195).
|
||||||
|
reproducible = false;
|
||||||
|
})
|
||||||
];
|
];
|
||||||
# Writable runtime dirs. /var/log/nginx is the compiled-in path for
|
|
||||||
# angie (matches nixpkgs' nginx build flags); the chart's main config
|
|
||||||
# also writes pid to /run.
|
|
||||||
extraCommands = ''
|
|
||||||
mkdir -p var/log/nginx var/cache/angie var/lib/angie run tmp etc/angie/http.d
|
|
||||||
chmod 1777 tmp run
|
|
||||||
# Ship the conf-dir bundled with angie (mime.types, fastcgi_params,
|
|
||||||
# scgi_params, uwsgi_params, koi-utf, koi-win, etc.) — chart configs
|
|
||||||
# `include fastcgi_params;` and similar resolve relative to /etc/angie.
|
|
||||||
cp ${angie}/conf/* etc/angie/
|
|
||||||
chmod -R u+w etc/angie
|
|
||||||
cp -f ${mainConf} etc/angie/angie.conf
|
|
||||||
'';
|
|
||||||
config = {
|
config = {
|
||||||
Entrypoint = [ "${angie}/bin/angie" ];
|
Entrypoint = [ "${angie}/bin/angie" ];
|
||||||
Cmd = [
|
Cmd = [
|
||||||
@@ -78,112 +103,19 @@
|
|||||||
WorkingDir = "/etc/angie";
|
WorkingDir = "/etc/angie";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
# Shared build+publish logic for the arm64 OCI leg. This script IS the
|
|
||||||
# parity code (emmett#44, archetype: oci-image-skopeo): both
|
|
||||||
# `.woodpecker.yaml` and a local `nix run .#publish-arm64` invoke the
|
|
||||||
# exact same entrypoint, so CI and local cannot drift.
|
|
||||||
#
|
|
||||||
# Safety: DRY-RUN by default. It builds the image stream and prints the
|
|
||||||
# refs it WOULD push, but performs no registry contact unless PUBLISH=1
|
|
||||||
# is set. The token is never printed and this script never runs under
|
|
||||||
# `set -x` (which would leak the auth header).
|
|
||||||
publish-arm64 = pkgs.writeShellApplication {
|
|
||||||
name = "publish-arm64";
|
|
||||||
runtimeInputs = with pkgs; [
|
|
||||||
skopeo
|
|
||||||
coreutils
|
|
||||||
gnused
|
|
||||||
gitMinimal
|
|
||||||
];
|
|
||||||
# `pass` is optional (only the local fallback path needs it) and may
|
|
||||||
# live outside this closure, so it is resolved from PATH at runtime.
|
|
||||||
text = ''
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# --- usage -------------------------------------------------------
|
# Publish apps: shared parity-lib nix2container builder (cluster #201).
|
||||||
if [ "''${1:-}" = "--help" ] || [ "''${1:-}" = "-h" ]; then
|
# Single-arch (arm64): yields stage-arm64 / publish-arm64 / publish-index /
|
||||||
printf '%s\n' \
|
# publish / push-staged / verify-digest. copy-to (skopeo) pushes the arch
|
||||||
"publish-arm64 — build the angie arm64 OCI image and (optionally) push it." \
|
# tag, regctl assembles the index; dry-run by default (--publish to push);
|
||||||
"" \
|
# token $REGISTRY_TOKEN -> pass fallback, never echoed.
|
||||||
"Builds the arm64 docker-archive via Nix and uses skopeo to copy it to" \
|
builders = parity.lib.mkParityBuilders pkgs;
|
||||||
"the Gitea OCI registry as :<ver>-arm64, then mirrors that digest to" \
|
publishApps = builders.mkNix2ContainerPublish {
|
||||||
":latest-arm64." \
|
imageName = "git.oleks.space/oleks/angie";
|
||||||
"" \
|
inherit (angie) version;
|
||||||
"DRY-RUN by default: prints the refs it would push and exits without" \
|
images = {
|
||||||
"contacting the registry. Set PUBLISH=1 to actually push." \
|
arm64.copyTo = image.copyTo;
|
||||||
"" \
|
};
|
||||||
"Env:" \
|
|
||||||
" PUBLISH=1 actually push (default: dry-run)" \
|
|
||||||
" VERSION=<ver> override the tag (default: angie.version)" \
|
|
||||||
" REGISTRY_TOKEN=<tok> registry RW token; if empty, falls back to" \
|
|
||||||
" pass infra/gitea/personal_access_token_packages_rw" \
|
|
||||||
"" \
|
|
||||||
"Flags:" \
|
|
||||||
" --help, -h this help" \
|
|
||||||
" --dry-run force dry-run even if PUBLISH=1"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
DRY_RUN=0
|
|
||||||
if [ "''${PUBLISH:-0}" != "1" ]; then DRY_RUN=1; fi
|
|
||||||
if [ "''${1:-}" = "--dry-run" ]; then DRY_RUN=1; fi
|
|
||||||
|
|
||||||
REGISTRY="git.oleks.space"
|
|
||||||
IMAGE="oleks/angie"
|
|
||||||
|
|
||||||
# --- version / tag (identical for CI + local) --------------------
|
|
||||||
VERSION="''${VERSION:-$(nix eval --raw .#angieVersion)}"
|
|
||||||
echo "angie version: $VERSION"
|
|
||||||
echo "target refs: docker://$REGISTRY/$IMAGE:$VERSION-arm64"
|
|
||||||
echo " docker://$REGISTRY/$IMAGE:latest-arm64"
|
|
||||||
|
|
||||||
# --- build (cluster-independent) ---------------------------------
|
|
||||||
echo "building arm64 image stream..."
|
|
||||||
STREAM="$(nix build .#default --print-out-paths --no-link)"
|
|
||||||
|
|
||||||
if [ "$DRY_RUN" = "1" ]; then
|
|
||||||
echo "DRY-RUN: built $STREAM"
|
|
||||||
echo "DRY-RUN: would skopeo-copy docker-archive -> docker://$REGISTRY/$IMAGE:$VERSION-arm64"
|
|
||||||
echo "DRY-RUN: would mirror :$VERSION-arm64 -> :latest-arm64"
|
|
||||||
echo "DRY-RUN: set PUBLISH=1 to actually push."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# --- token resolution (never printed) ----------------------------
|
|
||||||
TOKEN="''${REGISTRY_TOKEN:-}"
|
|
||||||
if [ -z "$TOKEN" ]; then
|
|
||||||
if command -v pass >/dev/null 2>&1; then
|
|
||||||
TOKEN="$(pass infra/gitea/personal_access_token_packages_rw)"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if [ -z "$TOKEN" ]; then
|
|
||||||
echo "ERROR: no registry token. Set REGISTRY_TOKEN or store it at" >&2
|
|
||||||
echo " pass infra/gitea/personal_access_token_packages_rw" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# skopeo's containers/image library stages under /var/tmp (not TMPDIR).
|
|
||||||
mkdir -p /var/tmp && chmod 1777 /var/tmp || true
|
|
||||||
|
|
||||||
AUTHFILE="$(mktemp -d)/auth.json"
|
|
||||||
# shellcheck disable=SC2064
|
|
||||||
trap "rm -rf '$(dirname "$AUTHFILE")'" EXIT
|
|
||||||
printf '{"auths":{"%s":{"auth":"%s"}}}\n' \
|
|
||||||
"$REGISTRY" "$(printf 'oleks:%s' "$TOKEN" | base64 -w0)" \
|
|
||||||
> "$AUTHFILE"
|
|
||||||
|
|
||||||
echo "pushing :$VERSION-arm64 ..."
|
|
||||||
skopeo copy --insecure-policy --authfile "$AUTHFILE" \
|
|
||||||
docker-archive:<("$STREAM") \
|
|
||||||
"docker://$REGISTRY/$IMAGE:$VERSION-arm64"
|
|
||||||
|
|
||||||
echo "mirroring :$VERSION-arm64 -> :latest-arm64 ..."
|
|
||||||
skopeo copy --insecure-policy --authfile "$AUTHFILE" \
|
|
||||||
"docker://$REGISTRY/$IMAGE:$VERSION-arm64" \
|
|
||||||
"docker://$REGISTRY/$IMAGE:latest-arm64"
|
|
||||||
|
|
||||||
echo "done."
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
@@ -191,13 +123,9 @@
|
|||||||
default = image;
|
default = image;
|
||||||
};
|
};
|
||||||
|
|
||||||
apps.${system} = {
|
# stage-arm64 / publish-arm64 / publish-index / publish / push-staged /
|
||||||
publish-arm64 = {
|
# verify-digest come from parity-lib.
|
||||||
type = "app";
|
apps.${system} = publishApps;
|
||||||
program = "${publish-arm64}/bin/publish-arm64";
|
|
||||||
meta.description = "Build and publish the angie arm64 OCI image to git.oleks.space (dry-run by default; PUBLISH=1 to push).";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# Plain string — read by CI via `nix eval --raw .#angieVersion`.
|
# Plain string — read by CI via `nix eval --raw .#angieVersion`.
|
||||||
angieVersion = angie.version;
|
angieVersion = angie.version;
|
||||||
|
|||||||
Reference in New Issue
Block a user