135 lines
4.6 KiB
Python
135 lines
4.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Render thin ci-fleet-publish-based pipelines for the quartet family
|
|
(oleks/ci-scripts#17) — PREP/PLANNING script, not wired into anything yet.
|
|
|
|
SCOPE NOTE (surfaced to team-lead, not silently assumed): #17 lists 6 repos,
|
|
but manifests/*.yaml shows only 2 are actually `kind: matrix` (real buildx
|
|
per-arch-build + manifest-consolidate quartets): xonsh-image, csi-s3. The
|
|
other 4 are shaped differently and don't map onto the plugin's
|
|
buildx-build/buildx-manifest flow at all:
|
|
- the-eye, emdash.kotkanagrilli.fi: kind: single — one native-arch build,
|
|
no manifest step. These want `flow: publish` (single-step, like the
|
|
fleet family), not the buildx quartet flow.
|
|
- flake-hub, woodpecker-peek: kind: split — separate per-arch files using
|
|
`nix run .#publish-*`, no docker buildx involved at all. Same as above,
|
|
`flow: publish` per arch file, not buildx-build/buildx-manifest.
|
|
This script only renders the 2 true matrix-kind repos. The other 4 need a
|
|
render_thin_fleet.py-style treatment instead — flagged as follow-up, not
|
|
done here.
|
|
|
|
For xonsh-image/csi-s3, migrating to the plugin's buildx-build/buildx-manifest
|
|
flow means the plugin's generic `docker buildx build --push <context>`
|
|
(building the repo's own Dockerfile directly) REPLACES what `ci/local.sh
|
|
--arch/--manifest` used to do internally. This is a bigger behavioral swap
|
|
than the fleet family's migration (which just moves inline shell into
|
|
`run:`) — needs explicit confirmation that ci/local.sh's Dockerfile build is
|
|
the ONLY thing it does before this ships (see report).
|
|
|
|
Usage:
|
|
python3 generator/render_thin_quartet.py --out /path/to/scratch
|
|
"""
|
|
|
|
import argparse
|
|
import pathlib
|
|
|
|
import yaml
|
|
|
|
HERE = pathlib.Path(__file__).parent.parent
|
|
PLUGIN_IMAGE = "git.oleks.space/oleks/ci-fleet-publish:v1"
|
|
|
|
GENERATED_HEADER = (
|
|
"# GENERATED by oleks/ci-scripts — do not hand-edit.\n"
|
|
"# Source: oleks/ci-scripts manifests/{repo}.yaml + "
|
|
"generator/render_thin_quartet.py (oleks/ci-scripts#17).\n"
|
|
"# Re-render with: python3 generator/render_thin_quartet.py --out <repo>/.woodpecker\n"
|
|
"\n"
|
|
)
|
|
|
|
|
|
def render_build(manifest: dict, arch: str, image_name: str) -> str:
|
|
node_selector = manifest.get("node_selector")
|
|
backend_options_block = ""
|
|
if node_selector:
|
|
lines = "\n".join(f" {k}: {v}" for k, v in node_selector.items())
|
|
backend_options_block = (
|
|
" backend_options:\n kubernetes:\n nodeSelector:\n" + lines + "\n"
|
|
)
|
|
|
|
return f"""{GENERATED_HEADER}labels:
|
|
arch: {arch}
|
|
|
|
when:
|
|
- event: tag
|
|
ref: "refs/tags/v*"
|
|
|
|
steps:
|
|
- name: build-{arch}
|
|
image: {PLUGIN_IMAGE}
|
|
environment:
|
|
REGISTRY_TOKEN:
|
|
from_secret: registry_token
|
|
settings:
|
|
flow: buildx-build
|
|
image_name: "{image_name}"
|
|
tag_scheme: "{{version}}-{{arch}}"
|
|
{backend_options_block}"""
|
|
|
|
|
|
def render_manifest(manifest: dict, arches: list, image_name: str) -> str:
|
|
platforms = ",".join(arches)
|
|
return f"""{GENERATED_HEADER}when:
|
|
- event: tag
|
|
ref: "refs/tags/v*"
|
|
|
|
depends_on:
|
|
{chr(10).join(f" - build-{a}" for a in arches)}
|
|
|
|
# oleks/ci-scripts#9: run even if a per-arch build failed — the plugin's
|
|
# buildx-manifest flow itself probes the registry for which per-arch tags
|
|
# actually landed and builds the manifest from whatever exists.
|
|
runs_on:
|
|
- success
|
|
- failure
|
|
|
|
steps:
|
|
- name: manifest
|
|
image: {PLUGIN_IMAGE}
|
|
environment:
|
|
REGISTRY_TOKEN:
|
|
from_secret: registry_token
|
|
settings:
|
|
flow: buildx-manifest
|
|
image_name: "{image_name}"
|
|
platforms: "{platforms}"
|
|
tag_scheme: "{{version}}-{{arch}}"
|
|
"""
|
|
|
|
|
|
def main():
|
|
ap = argparse.ArgumentParser()
|
|
ap.add_argument("--out", type=pathlib.Path, required=True)
|
|
args = ap.parse_args()
|
|
|
|
manifests_dir = HERE / "manifests"
|
|
for path in sorted(manifests_dir.glob("*.yaml")):
|
|
manifest = yaml.safe_load(path.read_text())
|
|
if manifest.get("kind") != "matrix":
|
|
print(f"skip {manifest['repo']} (kind={manifest.get('kind')}, not a buildx quartet)")
|
|
continue
|
|
repo = manifest["repo"]
|
|
image_name = f"git.oleks.space/oleks/{repo}"
|
|
arches = manifest["arches"]
|
|
out_dir = args.out / repo
|
|
out_dir.mkdir(parents=True, exist_ok=True)
|
|
for arch in arches:
|
|
target = out_dir / f"build-{arch}.yaml"
|
|
target.write_text(render_build(manifest, arch, image_name))
|
|
print(f"wrote {target}")
|
|
target = out_dir / "manifest.yaml"
|
|
target.write_text(render_manifest(manifest, arches, image_name))
|
|
print(f"wrote {target}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|