ci: convert OCI pipeline to parity-lib nix2container builder
The payload (pure-stdlib bridge.py + a stock CPython closure) is fully Nix-expressible, so this is NOT an escape-hatch/buildkit repo: both arches build on emmett (amd64 native + arm64 pkgsCross of stock python3 from the binary cache) with no buildkit, qemu, docker daemon, or howard pin. Replace the partial amd64-only scaffold with parity-lib's mkNix2ContainerPublish, completing the arm64 leg + multi-arch index. The per-arch nix2container image derivations are kept verbatim; stage/publish/ publish-index/publish/push-staged now come from the shared builder so CI and local invoke identical code. Thin .woodpecker.yaml to a single nix run .#publish; retire the buildx/remote-builder steps. The Dockerfile is now unused (the cutover drops it) but kept in-tree so the server-side hadolint pre-receive hook does not crash on a file deletion. Refs cluster #192, emmett#44.
This commit is contained in:
+12
-18
@@ -5,33 +5,27 @@ when:
|
|||||||
- event: tag
|
- event: tag
|
||||||
ref: "refs/tags/v*"
|
ref: "refs/tags/v*"
|
||||||
|
|
||||||
skip_clone: true
|
# Local-pipeline parity (cluster #192, emmett#44). The flake apps ARE the shared
|
||||||
|
# code: this same `nix run .#publish` is what a developer runs on emmett. The
|
||||||
|
# pure-stdlib bridge.py + a stock CPython closure are fully Nix-expressible, so
|
||||||
|
# both arches build from this single amd64 runner (amd64 native + arm64
|
||||||
|
# pkgsCross) — no Dockerfile, no buildkit, no remote builder, no howard pin.
|
||||||
|
# nix2container copy-to (skopeo) pushes each arch; regctl assembles the index.
|
||||||
|
# The app DRY-RUNS by default; CI opts in with PUBLISH=1. :latest is a digest
|
||||||
|
# copy of :TAG made last and guarded off for dev tags.
|
||||||
steps:
|
steps:
|
||||||
- name: clone
|
- name: publish
|
||||||
image: alpine/git
|
|
||||||
environment:
|
|
||||||
CLONE_TOKEN:
|
|
||||||
from_secret: registry_token
|
|
||||||
commands:
|
|
||||||
- git clone --depth 1 --branch $CI_COMMIT_TAG https://oleks:$CLONE_TOKEN@git.oleks.space/oleks/alertmanager-gotify-bridge.git .
|
|
||||||
|
|
||||||
- name: build-and-push
|
|
||||||
image: git.oleks.space/oleks/nix-ci:latest
|
image: git.oleks.space/oleks/nix-ci:latest
|
||||||
environment:
|
environment:
|
||||||
|
# One token env var everywhere; the app reads it (never interpolated).
|
||||||
REGISTRY_TOKEN:
|
REGISTRY_TOKEN:
|
||||||
from_secret: registry_token
|
from_secret: registry_token
|
||||||
commands:
|
commands:
|
||||||
- echo "$REGISTRY_TOKEN" | docker login git.oleks.space -u oleks --password-stdin
|
- nixos-ci-entrypoint bash -c "set -e; PUBLISH=1 nix run .#publish"
|
||||||
- docker buildx create --name arm64 --driver remote "tcp://buildkit-rootless-arm64.infra.svc.cluster.local:1234"
|
|
||||||
- TAG=$(echo "$CI_COMMIT_TAG" | sed 's/^v//')
|
|
||||||
- IMAGE="git.oleks.space/oleks/alertmanager-gotify-bridge"
|
|
||||||
- echo "Building $IMAGE:$TAG"
|
|
||||||
- docker buildx build --builder arm64 --platform linux/amd64,linux/arm64 --tag "$IMAGE:$TAG" --tag "$IMAGE:latest" --push .
|
|
||||||
backend_options:
|
backend_options:
|
||||||
kubernetes:
|
kubernetes:
|
||||||
nodeSelector:
|
nodeSelector:
|
||||||
kubernetes.io/hostname: howard2404
|
kubernetes.io/arch: amd64
|
||||||
labels:
|
labels:
|
||||||
commit-tag: "${CI_COMMIT_TAG}"
|
commit-tag: "${CI_COMMIT_TAG}"
|
||||||
commit-branch: "${CI_COMMIT_BRANCH}"
|
commit-branch: "${CI_COMMIT_BRANCH}"
|
||||||
|
|||||||
Generated
+138
-1
@@ -18,6 +18,24 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"flake-utils_2": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems_2"
|
||||||
|
},
|
||||||
|
"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": {
|
"fleet": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
@@ -72,6 +90,69 @@
|
|||||||
"url": "https://git.oleks.space/oleks/fleet-pins"
|
"url": "https://git.oleks.space/oleks/fleet-pins"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"fleet_2": {
|
||||||
|
"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": {
|
"nix2container": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
@@ -108,6 +189,46 @@
|
|||||||
"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_2",
|
||||||
|
"fleet": "fleet_2",
|
||||||
|
"nixpkgs": [
|
||||||
|
"parity",
|
||||||
|
"fleet",
|
||||||
|
"nixpkgs-ci"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1780379798,
|
||||||
|
"narHash": "sha256-vm88bZ2O/KHb14dUPlpuSMPzQlwDRwiTfZrZUMpo1Pw=",
|
||||||
|
"ref": "refs/heads/main",
|
||||||
|
"rev": "af64a8ea4c537f6b5e9f2bee0fbddc59648f7d32",
|
||||||
|
"revCount": 7,
|
||||||
|
"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": {
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
@@ -116,7 +237,8 @@
|
|||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"fleet",
|
"fleet",
|
||||||
"nixpkgs-projects"
|
"nixpkgs-projects"
|
||||||
]
|
],
|
||||||
|
"parity": "parity"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"systems": {
|
"systems": {
|
||||||
@@ -133,6 +255,21 @@
|
|||||||
"repo": "default",
|
"repo": "default",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"systems_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": "root",
|
"root": "root",
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
{
|
{
|
||||||
description = "alertmanager-gotify-bridge — pure-stdlib Python forwarder, containerized with Nix (nix2container). DESIGN/PARTIAL: amd64 leg only — see ci/MIGRATION.md.";
|
description = "alertmanager-gotify-bridge — pure-stdlib Python forwarder, containerized with Nix (nix2container), multi-arch via the shared parity-lib OCI builder.";
|
||||||
|
|
||||||
# ──────────────────────────────────────────────────────────────────────────
|
# ──────────────────────────────────────────────────────────────────────────
|
||||||
# SCAFFOLD / PARTIAL MIGRATION (emmett#44, archetype oci-image buildx→nix2container).
|
# LOCAL-PIPELINE PARITY (cluster #192, emmett#44). Archetype: nix2container OCI
|
||||||
# This flake intentionally implements ONLY the natively-buildable amd64 leg
|
# image (NOT a buildkit/escape-hatch repo — the whole payload is Nix-
|
||||||
# (`nix run .#publish-amd64`, dry-run by default). The arm64 cross leg, the
|
# expressible). The payload is pure-stdlib `bridge.py` next to a stock CPython
|
||||||
# multi-arch `publish-index`/`publish` apps, and the `.woodpecker.yaml` cutover
|
# closure, so BOTH arches build on emmett with no buildkit / qemu / docker:
|
||||||
# are DESIGNED in ci/MIGRATION.md but NOT yet wired. Do not treat this as the
|
# amd64 = native, arm64 = pkgsCross of stock python3 from the binary cache.
|
||||||
# finished pipeline. Pattern mirrors the reference impl
|
# The per-arch image derivations are kept verbatim; the stage/publish/
|
||||||
# (oleks/claude-plugin-registry @ 9850745).
|
# 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 = {
|
inputs = {
|
||||||
@@ -18,6 +20,8 @@
|
|||||||
nix2container.url = "github:nlewo/nix2container";
|
nix2container.url = "github:nlewo/nix2container";
|
||||||
nix2container.inputs.nixpkgs.follows = "nixpkgs";
|
nix2container.inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
|
||||||
|
parity.url = "git+https://git.oleks.space/oleks/parity-lib";
|
||||||
|
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -25,6 +29,7 @@
|
|||||||
{
|
{
|
||||||
nixpkgs,
|
nixpkgs,
|
||||||
nix2container,
|
nix2container,
|
||||||
|
parity,
|
||||||
flake-utils,
|
flake-utils,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
@@ -32,21 +37,20 @@
|
|||||||
system:
|
system:
|
||||||
let
|
let
|
||||||
pkgs = import nixpkgs { inherit system; };
|
pkgs = import nixpkgs { inherit system; };
|
||||||
inherit (pkgs) lib;
|
|
||||||
n2c = nix2container.packages.${system}.nix2container;
|
n2c = nix2container.packages.${system}.nix2container;
|
||||||
|
|
||||||
registry = "git.oleks.space/oleks/alertmanager-gotify-bridge";
|
registry = "git.oleks.space/oleks/alertmanager-gotify-bridge";
|
||||||
|
|
||||||
# TAG is derived identically for CI + local in shared code: CI exports
|
# TAG is derived in shared code: CI exports CI_COMMIT_TAG (parity-lib
|
||||||
# VERSION (= strip-v $CI_COMMIT_TAG); local dev may override $VERSION.
|
# strips the leading v / trailing -N), local dev may override $VERSION.
|
||||||
# No version.nix side-channel — the app is a static asset, the flake has
|
# No version.nix side-channel — the app is a static asset with no
|
||||||
# no version-baked source build, so the tag lives purely in $VERSION.
|
# version-baked source build, so the tag lives purely in $VERSION/tag.
|
||||||
version = "0.0.0-dev";
|
version = "0.0.0-dev";
|
||||||
|
|
||||||
# The whole payload: bridge.py + a python3 interpreter symlink under /app.
|
# The whole payload: bridge.py + a python3 interpreter symlink under /app.
|
||||||
# The symlink keeps the (arch-correct) python3 Nix closure tracked while
|
# The symlink keeps the (arch-correct) python3 Nix closure tracked while
|
||||||
# contributing no extra files. Parameterised over a pkg set so the SAME
|
# contributing no extra files. Parameterised over a pkg set so the SAME
|
||||||
# expression builds natively (amd64) and cross (arm64, future leg).
|
# expression builds natively (amd64) and cross (arm64).
|
||||||
appRoot =
|
appRoot =
|
||||||
targetPkgs: arch:
|
targetPkgs: arch:
|
||||||
pkgs.runCommand "app-root-${arch}" { } ''
|
pkgs.runCommand "app-root-${arch}" { } ''
|
||||||
@@ -94,111 +98,35 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# amd64 = native; arm64 = cross-compiled (stock python3 closure from the
|
||||||
|
# binary cache, no qemu). Both are buildable on emmett (amd64).
|
||||||
imageAmd64 = mkImage pkgs "amd64";
|
imageAmd64 = mkImage pkgs "amd64";
|
||||||
|
imageArm64 = mkImage pkgs.pkgsCross.aarch64-multiplatform "arm64";
|
||||||
|
|
||||||
# ── publish/stage apps (shared by CI + local; cannot drift). ──────────
|
# ── Publish apps: shared parity-lib nix2container builder (cluster #192).
|
||||||
# SAFETY: dry-run by default. Set PUBLISH=1 / --publish to actually push.
|
# Yields stage-<arch> / publish-<arch> / publish-index / publish /
|
||||||
passEntry = "infra/gitea/personal_access_token_packages_rw";
|
# push-staged. copy-to (skopeo) pushes per-arch, regctl assembles the
|
||||||
|
# index; no buildkit / docker daemon. Dry-run by default (--publish to
|
||||||
publishGate = ''
|
# push); token from $REGISTRY_TOKEN (CI from_secret) → pass fallback,
|
||||||
PUBLISH="''${PUBLISH:-0}"
|
# never echoed.
|
||||||
for a in "$@"; do
|
builders = parity.lib.mkParityBuilders pkgs;
|
||||||
case "$a" in
|
publishApps = builders.mkNix2ContainerPublish {
|
||||||
--publish) PUBLISH=1 ;;
|
imageName = registry;
|
||||||
--dry-run) PUBLISH=0 ;;
|
inherit version;
|
||||||
--help|-h)
|
images = {
|
||||||
echo "usage: [VERSION=x.y.z] [PUBLISH=1] $(basename "$0") [--publish|--dry-run|--help]" >&2
|
amd64.copyTo = imageAmd64.copyTo;
|
||||||
echo " dry-run by default: builds the amd64 image and prints what would be pushed." >&2
|
arm64.copyTo = imageArm64.copyTo;
|
||||||
echo " --publish / PUBLISH=1 actually mutates the registry." >&2
|
};
|
||||||
echo " NOTE: amd64 leg ONLY (scaffold) — see ci/MIGRATION.md." >&2
|
|
||||||
exit 0 ;;
|
|
||||||
*) echo "error: unknown argument '$a' (try --help)" >&2; exit 2 ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
TAG="''${VERSION:-${version}}"
|
|
||||||
'';
|
|
||||||
|
|
||||||
# Token resolved lazily (only when actually publishing); never echoed,
|
|
||||||
# never under set -x (writeShellApplication uses -euo pipefail only).
|
|
||||||
resolveToken = ''
|
|
||||||
TOKEN="''${REGISTRY_TOKEN:-}"
|
|
||||||
if [ -z "$TOKEN" ] && command -v pass >/dev/null 2>&1; then
|
|
||||||
TOKEN="$(pass show ${passEntry} 2>/dev/null || true)"
|
|
||||||
fi
|
|
||||||
if [ -z "$TOKEN" ]; then
|
|
||||||
echo "BLOCKER(empty-token): set REGISTRY_TOKEN env (CI from_secret) or have 'pass ${passEntry}' available; refusing to publish without credentials." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
'';
|
|
||||||
|
|
||||||
registryPreflight = ''
|
|
||||||
if ! curl -fsS -o /dev/null --max-time 10 "https://git.oleks.space/v2/" 2>/dev/null; then
|
|
||||||
echo "BLOCKER(registry-down): https://git.oleks.space/v2/ is unreachable — CI shares fate with the cluster (Zot/buildkit on armer/k3s). Re-run when the registry is back; the staged image in the Nix store is unchanged." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
'';
|
|
||||||
|
|
||||||
stageAmd64 = ''
|
|
||||||
echo "→ staging ${registry}:$TAG-amd64 (local build, no registry contact)"
|
|
||||||
OUT="$(nix build --no-link --print-out-paths "$FLAKE#image-amd64")"
|
|
||||||
echo " staged image derivation: $OUT"
|
|
||||||
'';
|
|
||||||
|
|
||||||
mkStageAmd64 = pkgs.writeShellApplication {
|
|
||||||
name = "stage-amd64";
|
|
||||||
runtimeInputs = [ pkgs.nix ];
|
|
||||||
text = ''
|
|
||||||
FLAKE="''${FLAKE:-.}"
|
|
||||||
''
|
|
||||||
+ publishGate
|
|
||||||
+ stageAmd64;
|
|
||||||
};
|
|
||||||
|
|
||||||
mkPublishAmd64 = pkgs.writeShellApplication {
|
|
||||||
name = "publish-amd64";
|
|
||||||
runtimeInputs = [
|
|
||||||
pkgs.regctl
|
|
||||||
pkgs.curl
|
|
||||||
pkgs.nix
|
|
||||||
];
|
|
||||||
text = ''
|
|
||||||
FLAKE="''${FLAKE:-.}"
|
|
||||||
''
|
|
||||||
+ publishGate
|
|
||||||
+ stageAmd64
|
|
||||||
+ ''
|
|
||||||
echo "→ ${registry}:$TAG-amd64"
|
|
||||||
if [ "$PUBLISH" != "1" ]; then
|
|
||||||
echo " [dry-run] would push ${registry}:$TAG-amd64 (set PUBLISH=1 / --publish to push)"
|
|
||||||
echo " [dry-run] NOTE: amd64 leg only — arm64 + index not yet implemented (ci/MIGRATION.md)"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
''
|
|
||||||
+ resolveToken
|
|
||||||
+ registryPreflight
|
|
||||||
+ ''
|
|
||||||
${lib.getExe imageAmd64.copyTo} --dest-creds "oleks:$TOKEN" "docker://${registry}:$TAG-amd64"
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
packages = {
|
packages = {
|
||||||
image-amd64 = imageAmd64;
|
image-amd64 = imageAmd64;
|
||||||
|
image-arm64 = imageArm64;
|
||||||
default = imageAmd64;
|
default = imageAmd64;
|
||||||
};
|
};
|
||||||
|
|
||||||
apps = {
|
apps = publishApps;
|
||||||
stage-amd64 = {
|
|
||||||
type = "app";
|
|
||||||
program = lib.getExe mkStageAmd64;
|
|
||||||
meta.description = "Build the amd64 nix2container image into the local store (no registry contact). Scaffold: amd64 leg only.";
|
|
||||||
};
|
|
||||||
publish-amd64 = {
|
|
||||||
type = "app";
|
|
||||||
program = lib.getExe mkPublishAmd64;
|
|
||||||
meta.description = "Stage + push the amd64 image (dry-run by default; PUBLISH=1 to push). Scaffold: amd64 leg only — see ci/MIGRATION.md.";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user