Files
pikasTech-agentrun/deploy/templates/tekton/pipeline.yaml
T
2026-06-02 02:41:56 +08:00

470 lines
22 KiB
YAML

apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
name: agentrun-v01-ci-image-publish
namespace: agentrun-ci
labels:
app.kubernetes.io/part-of: agentrun
agentrun.pikastech.local/lane: v0.1
spec:
params:
- name: git-url
type: string
default: git@github.com:pikasTech/agentrun.git
- name: git-read-url
type: string
default: http://git-mirror-http.devops-infra.svc.cluster.local/pikasTech/agentrun.git
- name: git-write-url
type: string
default: http://git-mirror-write.devops-infra.svc.cluster.local/pikasTech/agentrun.git
- name: source-branch
type: string
default: v0.1
- name: gitops-branch
type: string
default: v0.1-gitops
- name: revision
type: string
- name: registry-prefix
type: string
default: 127.0.0.1:5000/agentrun
- name: tools-image
type: string
default: 127.0.0.1:5000/hwlab/hwlab-ci-node-tools:node22-alpine-bun-v1
workspaces:
- name: source
- name: git-ssh
tasks:
- name: prepare-source
workspaces:
- name: source
workspace: source
taskSpec:
params:
- name: git-read-url
- name: revision
- name: tools-image
workspaces:
- name: source
steps:
- name: clone-and-check
image: $(params.tools-image)
env:
- name: HTTP_PROXY
value: http://127.0.0.1:10808
- name: HTTPS_PROXY
value: http://127.0.0.1:10808
- name: NO_PROXY
value: hyueapi.com,.hyueapi.com,127.0.0.1,localhost,::1,10.42.0.0/16,10.43.0.0/16,.svc,.cluster.local
- name: http_proxy
value: http://127.0.0.1:10808
- name: https_proxy
value: http://127.0.0.1:10808
- name: no_proxy
value: hyueapi.com,.hyueapi.com,127.0.0.1,localhost,::1,10.42.0.0/16,10.43.0.0/16,.svc,.cluster.local
- name: GIT_TERMINAL_PROMPT
value: "0"
script: |
#!/bin/sh
set -eu
rm -rf /workspace/source/repo
mkdir -p /workspace/source/repo
git init /workspace/source/repo
cd /workspace/source/repo
git remote add origin "$(params.git-read-url)"
git fetch --depth=1 origin "$(params.revision)"
git checkout --detach FETCH_HEAD
test "$(git rev-parse HEAD)" = "$(params.revision)"
bun install --frozen-lockfile
bun run check
bun scripts/agentrun-gitops-render.ts --out /tmp/agentrun-gitops-render-check --source-commit "$(params.revision)" --check
AGENTRUN_SELFTEST_CODEX_COMMAND="$(command -v bun)" \
AGENTRUN_SELFTEST_CODEX_ARGS="[\"$PWD/src/selftest/fake-codex-app-server.ts\"]" \
bun run self-test
params:
- name: git-read-url
value: $(params.git-read-url)
- name: revision
value: $(params.revision)
- name: tools-image
value: $(params.tools-image)
- name: plan-artifacts
runAfter: [prepare-source]
workspaces:
- name: source
workspace: source
taskSpec:
params:
- name: git-read-url
- name: gitops-branch
- name: revision
- name: registry-prefix
- name: tools-image
results:
- name: env-identity
- name: build-count
- name: reuse-count
- name: summary
workspaces:
- name: source
steps:
- name: plan
image: $(params.tools-image)
env:
- name: GIT_TERMINAL_PROMPT
value: "0"
script: |
#!/bin/sh
set -eu
cd /workspace/source/repo
node <<'NODE' > /workspace/source/env-identity
const { createHash } = require("node:crypto");
const { readFileSync } = require("node:fs");
const inputs = [
["toolsImage", "127.0.0.1:5000/hwlab/hwlab-ci-node-tools:node22-alpine-bun-v1"],
["systemPackages", "ca-certificates curl git kubectl nodejs openssh-client"],
["containerfile", readFileSync("deploy/container/Containerfile", "utf8")],
["bootScript", readFileSync("deploy/runtime/boot/agentrun-boot.sh", "utf8")],
["bootMgr", readFileSync("deploy/runtime/boot/agentrun-mgr.sh", "utf8")],
["bootRunner", readFileSync("deploy/runtime/boot/agentrun-runner.sh", "utf8")],
["packageJson", readFileSync("package.json", "utf8")],
["bunLock", readFileSync("bun.lock", "utf8")],
["tsconfig", readFileSync("tsconfig.json", "utf8")],
];
process.stdout.write(createHash("sha256").update(JSON.stringify(inputs)).digest("hex").slice(0, 20));
NODE
env_identity="$(cat /workspace/source/env-identity)"
rm -rf /workspace/source/gitops-prev
if git clone --depth=1 --branch "$(params.gitops-branch)" "$(params.git-read-url)" /workspace/source/gitops-prev >/tmp/agentrun-prev-gitops.log 2>&1; then
prev_catalog=/workspace/source/gitops-prev/deploy/artifact-catalog.v01.json
else
prev_catalog=/dev/null
fi
AGENTRUN_ENV_IDENTITY="$env_identity" \
AGENTRUN_PREV_CATALOG="$prev_catalog" \
AGENTRUN_REVISION="$(params.revision)" \
AGENTRUN_GITOPS_BRANCH="$(params.gitops-branch)" \
AGENTRUN_REGISTRY_PREFIX="$(params.registry-prefix)" \
node <<'NODE'
const { readFileSync, writeFileSync } = require("node:fs");
const { execFileSync } = require("node:child_process");
const envIdentity = process.env.AGENTRUN_ENV_IDENTITY;
const revision = process.env.AGENTRUN_REVISION;
const gitopsBranch = process.env.AGENTRUN_GITOPS_BRANCH;
const registryPrefix = process.env.AGENTRUN_REGISTRY_PREFIX;
let previousService = null;
try {
const catalog = JSON.parse(readFileSync(process.env.AGENTRUN_PREV_CATALOG, "utf8"));
previousService = (catalog.services || []).find((item) => item.serviceId === "agentrun-mgr" && item.envIdentity === envIdentity && /^sha256:[a-f0-9]{64}$/.test(item.envDigest || item.digest || "")) || null;
} catch {}
if (previousService === null) {
try {
const digest = execFileSync("curl", ["-fsSI", "-H", "Accept: application/vnd.docker.distribution.manifest.v2+json", `http://127.0.0.1:5000/v2/agentrun/agentrun-mgr-env/manifests/${envIdentity}`], { encoding: "utf8" })
.split(/\r?\n/)
.map((line) => line.split(": "))
.find(([key]) => String(key).toLowerCase() === "docker-content-digest")?.[1]
?.trim();
if (/^sha256:[a-f0-9]{64}$/.test(digest || "")) {
previousService = {
serviceId: "agentrun-mgr",
artifactKind: "env-reuse",
status: "registry-reuse",
image: `${registryPrefix}/agentrun-mgr-env:${envIdentity}`,
digest,
repositoryDigest: `${registryPrefix}/agentrun-mgr-env@${digest}`,
imageTag: envIdentity,
envIdentity,
envImage: `${registryPrefix}/agentrun-mgr-env:${envIdentity}`,
envDigest: digest,
envRepositoryDigest: `${registryPrefix}/agentrun-mgr-env@${digest}`,
bootCommit: null,
};
}
} catch {}
}
const reused = previousService !== null;
const plan = {
lane: "v0.1",
sourceBranch: "v0.1",
gitopsBranch,
sourceCommitId: revision,
envIdentity,
toolchainInputs: ["127.0.0.1:5000/hwlab/hwlab-ci-node-tools:node22-alpine-bun-v1", "deploy/container/Containerfile", "deploy/runtime/boot/*.sh", "package.json", "bun.lock", "tsconfig.json", "tools:ca-certificates curl git kubectl nodejs openssh-client"],
buildServices: reused ? [] : ["agentrun-mgr"],
reusedServices: reused ? ["agentrun-mgr"] : [],
unsafeReuseServices: [],
previousService,
summary: `build=${reused ? 0 : 1} reuse=${reused ? 1 : 0} unsafeReuse=0`,
};
writeFileSync("/workspace/source/ci-plan.json", `${JSON.stringify(plan, null, 2)}\n`);
writeFileSync("/tekton/results/env-identity", envIdentity);
writeFileSync("/tekton/results/build-count", String(plan.buildServices.length));
writeFileSync("/tekton/results/reuse-count", String(plan.reusedServices.length));
writeFileSync("/tekton/results/summary", plan.summary);
console.log(JSON.stringify({ event: "agentrun-ci-plan", status: "succeeded", sourceCommitId: revision, envIdentity, buildServices: plan.buildServices, reusedServices: plan.reusedServices, unsafeReuseServices: [], summary: plan.summary }));
NODE
params:
- name: git-read-url
value: $(params.git-read-url)
- name: gitops-branch
value: $(params.gitops-branch)
- name: revision
value: $(params.revision)
- name: registry-prefix
value: $(params.registry-prefix)
- name: tools-image
value: $(params.tools-image)
- name: image-publish
runAfter: [plan-artifacts]
workspaces:
- name: source
workspace: source
taskSpec:
params:
- name: revision
- name: registry-prefix
- name: tools-image
results:
- name: image
- name: digest
- name: repository-digest
- name: env-identity
- name: status
sidecars:
- name: buildkitd
image: moby/buildkit:rootless
args:
- --addr
- unix:///workspace/buildkit-run/buildkitd.sock
- --oci-worker-no-process-sandbox
env:
- name: HTTP_PROXY
value: http://127.0.0.1:10808
- name: HTTPS_PROXY
value: http://127.0.0.1:10808
- name: NO_PROXY
value: hyueapi.com,.hyueapi.com,127.0.0.1,localhost,::1,10.42.0.0/16,10.43.0.0/16,.svc,.cluster.local
- name: http_proxy
value: http://127.0.0.1:10808
- name: https_proxy
value: http://127.0.0.1:10808
- name: no_proxy
value: hyueapi.com,.hyueapi.com,127.0.0.1,localhost,::1,10.42.0.0/16,10.43.0.0/16,.svc,.cluster.local
securityContext:
allowPrivilegeEscalation: true
appArmorProfile:
type: Unconfined
seccompProfile:
type: Unconfined
runAsUser: 1000
runAsGroup: 1000
volumeMounts:
- name: buildkit-run
mountPath: /workspace/buildkit-run
steps:
- name: prepare-buildctl
image: moby/buildkit:rootless
script: |
#!/bin/sh
set -eu
mkdir -p /workspace/buildkit-bin
cp /usr/bin/buildctl /workspace/buildkit-bin/buildctl
chmod +x /workspace/buildkit-bin/buildctl
volumeMounts:
- name: buildkit-bin
mountPath: /workspace/buildkit-bin
- name: build-or-reuse
image: $(params.tools-image)
env:
- name: HTTP_PROXY
value: http://127.0.0.1:10808
- name: HTTPS_PROXY
value: http://127.0.0.1:10808
- name: NO_PROXY
value: hyueapi.com,.hyueapi.com,127.0.0.1,localhost,::1,10.42.0.0/16,10.43.0.0/16,.svc,.cluster.local
script: |
#!/bin/sh
set -eu
cd /workspace/source/repo
env_identity="$(cat /workspace/source/env-identity)"
if node -e 'const p=require("/workspace/source/ci-plan.json"); process.exit((p.buildServices||[]).length===0 ? 0 : 1)'; then
node <<'NODE'
const { readFileSync, writeFileSync } = require("node:fs");
const plan = JSON.parse(readFileSync("/workspace/source/ci-plan.json", "utf8"));
const service = plan.previousService;
if (!service) throw new Error("reuse plan missing previousService");
const image = service.envImage || service.image;
const digest = service.envDigest || service.digest;
const repositoryDigest = service.envRepositoryDigest || service.repositoryDigest;
writeFileSync("/tekton/results/image", image);
writeFileSync("/tekton/results/digest", digest);
writeFileSync("/tekton/results/repository-digest", repositoryDigest);
writeFileSync("/tekton/results/env-identity", plan.envIdentity);
writeFileSync("/tekton/results/status", "reused");
console.log(JSON.stringify({ event: "agentrun-env-image", status: "reused", serviceId: "agentrun-mgr", envIdentity: plan.envIdentity, image, digest, summary: plan.summary }));
NODE
exit 0
fi
image="$(params.registry-prefix)/agentrun-mgr-env:${env_identity}"
buildctl=/workspace/buildkit-bin/buildctl
for attempt in $(seq 1 60); do
if "$buildctl" --addr unix:///workspace/buildkit-run/buildkitd.sock debug workers >/dev/null 2>&1; then break; fi
sleep 1
done
"$buildctl" --addr unix:///workspace/buildkit-run/buildkitd.sock build \
--frontend dockerfile.v0 \
--local context=. \
--local dockerfile=deploy/container \
--opt filename=Containerfile \
--opt build-arg:HTTP_PROXY=http://127.0.0.1:10808 \
--opt build-arg:HTTPS_PROXY=http://127.0.0.1:10808 \
--opt build-arg:NO_PROXY=hyueapi.com,.hyueapi.com,127.0.0.1,localhost,::1,10.42.0.0/16,10.43.0.0/16,.svc,.cluster.local \
--output type=image,name="$image",push=true,registry.insecure=true
digest="$(curl -fsSI -H "Accept: application/vnd.docker.distribution.manifest.v2+json" "http://127.0.0.1:5000/v2/agentrun/agentrun-mgr-env/manifests/$env_identity" | awk -F': ' 'tolower($1)=="docker-content-digest" {gsub(/\r/,"",$2); print $2; exit}')"
test -n "$digest"
curl -fsSI -H "Accept: application/vnd.docker.distribution.manifest.v2+json" "http://127.0.0.1:5000/v2/agentrun/agentrun-mgr-env/manifests/$digest" >/dev/null
printf '%s' "$image" > /tekton/results/image
printf '%s' "$digest" > /tekton/results/digest
printf '%s' "$(params.registry-prefix)/agentrun-mgr-env@$digest" > /tekton/results/repository-digest
printf '%s' "$env_identity" > /tekton/results/env-identity
printf '%s' built > /tekton/results/status
printf '{"event":"agentrun-env-image","status":"built","serviceId":"agentrun-mgr","envIdentity":"%s","image":"%s","digest":"%s"}\n' "$env_identity" "$image" "$digest"
volumeMounts:
- name: buildkit-bin
mountPath: /workspace/buildkit-bin
- name: buildkit-run
mountPath: /workspace/buildkit-run
volumes:
- name: buildkit-bin
emptyDir: {}
- name: buildkit-run
emptyDir: {}
params:
- name: revision
value: $(params.revision)
- name: registry-prefix
value: $(params.registry-prefix)
- name: tools-image
value: $(params.tools-image)
- name: gitops-promote
runAfter: [image-publish]
workspaces:
- name: source
workspace: source
taskSpec:
params:
- name: git-write-url
- name: gitops-branch
- name: revision
- name: registry-prefix
- name: image
- name: digest
- name: repository-digest
- name: env-identity
- name: image-status
- name: tools-image
workspaces:
- name: source
steps:
- name: promote
image: $(params.tools-image)
env:
- name: GIT_TERMINAL_PROMPT
value: "0"
- name: AGENTRUN_IMAGE
value: $(params.image)
- name: AGENTRUN_DIGEST
value: $(params.digest)
- name: AGENTRUN_REPOSITORY_DIGEST
value: $(params.repository-digest)
- name: AGENTRUN_ENV_IDENTITY
value: $(params.env-identity)
- name: AGENTRUN_IMAGE_STATUS
value: $(params.image-status)
- name: AGENTRUN_REVISION
value: $(params.revision)
- name: AGENTRUN_GITOPS_BRANCH
value: $(params.gitops-branch)
script: |
#!/bin/sh
set -eu
cd /workspace/source/repo
node <<'NODE' > /workspace/source/artifact-catalog.v01.json
const { readFileSync } = require("node:fs");
const plan = JSON.parse(readFileSync("/workspace/source/ci-plan.json", "utf8"));
const service = {
serviceId: "agentrun-mgr",
artifactKind: "env-reuse",
status: process.env.AGENTRUN_IMAGE_STATUS,
image: process.env.AGENTRUN_IMAGE,
digest: process.env.AGENTRUN_DIGEST,
repositoryDigest: process.env.AGENTRUN_REPOSITORY_DIGEST,
imageTag: process.env.AGENTRUN_ENV_IDENTITY,
envIdentity: process.env.AGENTRUN_ENV_IDENTITY,
envImage: process.env.AGENTRUN_IMAGE,
envDigest: process.env.AGENTRUN_DIGEST,
envRepositoryDigest: process.env.AGENTRUN_REPOSITORY_DIGEST,
bootCommit: process.env.AGENTRUN_REVISION,
bootScript: "deploy/runtime/boot/agentrun-boot.sh",
provenance: {
sourceCommitId: process.env.AGENTRUN_REVISION,
toolchainInputs: plan.toolchainInputs,
buildServices: plan.buildServices,
reusedServices: plan.reusedServices,
unsafeReuseServices: plan.unsafeReuseServices,
previousSourceCommitId: plan.previousService?.bootCommit || null,
},
};
const catalog = {
lane: "v0.1",
sourceBranch: "v0.1",
gitopsBranch: process.env.AGENTRUN_GITOPS_BRANCH,
sourceCommitId: process.env.AGENTRUN_REVISION,
summary: plan.summary,
services: [service],
};
console.log(JSON.stringify(catalog, null, 2));
NODE
rm -rf /workspace/source/rendered
bun scripts/agentrun-gitops-render.ts --out /workspace/source/rendered --source-commit "$(params.revision)" --registry-prefix "$(params.registry-prefix)" --catalog /workspace/source/artifact-catalog.v01.json --require-catalog
rm -rf /workspace/source/gitops
git clone --branch "$(params.gitops-branch)" "$(params.git-write-url)" /workspace/source/gitops || {
git clone "$(params.git-write-url)" /workspace/source/gitops
cd /workspace/source/gitops
git checkout --orphan "$(params.gitops-branch)"
git rm -rf . >/dev/null 2>&1 || true
}
cd /workspace/source/gitops
git config user.email agentrun-ci@g14.local
git config user.name agentrun-ci
mkdir -p deploy/gitops/g14 deploy
rm -rf deploy/gitops/g14/runtime-v01 deploy/gitops/g14/argocd
cp -a /workspace/source/rendered/runtime-v01 deploy/gitops/g14/runtime-v01
cp -a /workspace/source/rendered/argocd deploy/gitops/g14/argocd
cp /workspace/source/rendered/artifact-catalog.v01.json deploy/artifact-catalog.v01.json
git add deploy
git commit -m "gitops: promote agentrun v0.1 $(params.revision)" || true
git push origin "$(params.gitops-branch)"
printf '{"event":"agentrun-gitops-promote","status":"succeeded","sourceCommitId":"%s","envIdentity":"%s","imageStatus":"%s","summary":%s}\n' "$(params.revision)" "$(params.env-identity)" "$(params.image-status)" "$(node -e 'const p=require("/workspace/source/ci-plan.json"); console.log(JSON.stringify(p.summary))')"
params:
- name: git-write-url
value: $(params.git-write-url)
- name: gitops-branch
value: $(params.gitops-branch)
- name: revision
value: $(params.revision)
- name: registry-prefix
value: $(params.registry-prefix)
- name: image
value: $(tasks.image-publish.results.image)
- name: digest
value: $(tasks.image-publish.results.digest)
- name: repository-digest
value: $(tasks.image-publish.results.repository-digest)
- name: env-identity
value: $(tasks.image-publish.results.env-identity)
- name: image-status
value: $(tasks.image-publish.results.status)
- name: tools-image
value: $(params.tools-image)