feat: support env reuse and git mirror in v0.1 cicd

This commit is contained in:
Codex
2026-06-02 00:52:19 +08:00
parent f34312c424
commit df38f605fa
11 changed files with 365 additions and 79 deletions
+211 -47
View File
@@ -11,6 +11,12 @@ spec:
- 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
@@ -33,17 +39,13 @@ spec:
workspaces:
- name: source
workspace: source
- name: git-ssh
workspace: git-ssh
taskSpec:
params:
- name: git-url
- name: source-branch
- name: git-read-url
- name: revision
- name: tools-image
workspaces:
- name: source
- name: git-ssh
steps:
- name: clone-and-check
image: $(params.tools-image)
@@ -60,37 +62,132 @@ spec:
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
apk add --no-cache git openssh-client curl
mkdir -p /root/.ssh
cp /workspace/git-ssh/ssh-privatekey /root/.ssh/id_rsa
chmod 600 /root/.ssh/id_rsa
ssh-keyscan github.com >> /root/.ssh/known_hosts 2>/dev/null
apk add --no-cache git curl
rm -rf /workspace/source/repo
git clone --branch "$(params.source-branch)" "$(params.git-url)" /workspace/source/repo
mkdir -p /workspace/source/repo
git init /workspace/source/repo
cd /workspace/source/repo
git config --global --add safe.directory /workspace/source/repo
git checkout "$(params.revision)"
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
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-url
value: $(params.git-url)
- name: source-branch
value: $(params.source-branch)
- name: git-read-url
value: $(params.git-read-url)
- name: revision
value: $(params.revision)
- name: tools-image
value: $(params.tools-image)
- name: image-publish
- 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
results:
- name: env-identity
- name: build-count
- name: reuse-count
- name: summary
workspaces:
- name: source
steps:
- name: plan
image: oven/bun:1.2.15-alpine
env:
- name: GIT_TERMINAL_PROMPT
value: "0"
script: |
#!/bin/sh
set -eu
apk add --no-cache git nodejs
cd /workspace/source/repo
node <<'NODE' > /workspace/source/env-identity
const { createHash } = require("node:crypto");
const { readFileSync } = require("node:fs");
const inputs = [
["baseImage", "oven/bun:1.2.15-alpine"],
["systemPackages", "ca-certificates 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 envIdentity = process.env.AGENTRUN_ENV_IDENTITY;
const revision = process.env.AGENTRUN_REVISION;
const gitopsBranch = process.env.AGENTRUN_GITOPS_BRANCH;
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 {}
const reused = previousService !== null;
const plan = {
lane: "v0.1",
sourceBranch: "v0.1",
gitopsBranch,
sourceCommitId: revision,
envIdentity,
toolchainInputs: ["oven/bun:1.2.15-alpine", "deploy/container/Containerfile", "deploy/runtime/boot/*.sh", "package.json", "bun.lock", "tsconfig.json", "apk:ca-certificates 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: image-publish
runAfter: [plan-artifacts]
workspaces:
- name: source
workspace: source
@@ -102,6 +199,8 @@ spec:
- name: image
- name: digest
- name: repository-digest
- name: env-identity
- name: status
sidecars:
- name: buildkitd
image: moby/buildkit:rootless
@@ -145,7 +244,7 @@ spec:
volumeMounts:
- name: buildkit-bin
mountPath: /workspace/buildkit-bin
- name: build-and-push
- name: build-or-reuse
image: oven/bun:1.2.15-alpine
env:
- name: HTTP_PROXY
@@ -157,9 +256,28 @@ spec:
script: |
#!/bin/sh
set -eu
apk add --no-cache curl
apk add --no-cache curl nodejs
cd /workspace/source/repo
image="$(params.registry-prefix)/agentrun-mgr:$(params.revision)"
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
@@ -174,12 +292,15 @@ spec:
--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/manifests/$(params.revision)" | awk -F': ' 'tolower($1)=="docker-content-digest" {gsub(/\r/,"",$2); print $2; exit}')"
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/manifests/$digest" >/dev/null
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@$digest" > /tekton/results/repository-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
@@ -200,47 +321,85 @@ spec:
workspaces:
- name: source
workspace: source
- name: git-ssh
workspace: git-ssh
taskSpec:
params:
- name: git-url
- 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
workspaces:
- name: source
- name: git-ssh
steps:
- name: promote
image: oven/bun:1.2.15-alpine
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: 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
apk add --no-cache git openssh-client
mkdir -p /root/.ssh
cp /workspace/git-ssh/ssh-privatekey /root/.ssh/id_rsa
chmod 600 /root/.ssh/id_rsa
ssh-keyscan github.com >> /root/.ssh/known_hosts 2>/dev/null
apk add --no-cache git openssh-client nodejs
cd /workspace/source/repo
cat > /workspace/source/artifact-catalog.v01.json <<EOF
{"lane":"v0.1","sourceBranch":"v0.1","gitopsBranch":"$(params.gitops-branch)","sourceCommitId":"$(params.revision)","services":[{"serviceId":"agentrun-mgr","image":"$(params.image)","digest":"$(params.digest)","repositoryDigest":"$(params.repository-digest)","imageTag":"$(params.revision)"}]}
EOF
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-url)" /workspace/source/gitops || {
git clone "$(params.git-url)" /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
@@ -256,9 +415,10 @@ spec:
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-url
value: $(params.git-url)
- name: git-write-url
value: $(params.git-write-url)
- name: gitops-branch
value: $(params.gitops-branch)
- name: revision
@@ -271,3 +431,7 @@ spec:
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)
@@ -16,6 +16,10 @@ spec:
params:
- name: revision
value: REPLACE_WITH_FULL_SOURCE_COMMIT
- name: git-read-url
value: http://git-mirror-http.devops-infra.svc.cluster.local/pikasTech/agentrun.git
- name: git-write-url
value: http://git-mirror-write.devops-infra.svc.cluster.local/pikasTech/agentrun.git
workspaces:
- name: source
volumeClaimTemplate: