ci: complete JD01 PaC Gitea env reuse flow
This commit is contained in:
@@ -617,7 +617,7 @@ controlPlane:
|
||||
path: deploy/gitops/node/jd01/runtime-v02
|
||||
argoNamespace: argocd
|
||||
argoApplication: agentrun-jd01-v02
|
||||
repoURL: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/agentrun.git
|
||||
repoURL: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git
|
||||
deployment:
|
||||
format: unidesk-yaml-only
|
||||
gitopsRoot: deploy/gitops/node/jd01
|
||||
@@ -643,7 +643,7 @@ controlPlane:
|
||||
unideskSshEndpointEnv:
|
||||
name: UNIDESK_MAIN_SERVER_IP
|
||||
value: 74.48.78.17
|
||||
bootRepoUrl: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/agentrun.git
|
||||
bootRepoUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git
|
||||
imageBuild:
|
||||
context: .
|
||||
containerfile: deploy/container/Containerfile
|
||||
@@ -772,7 +772,7 @@ controlPlane:
|
||||
readDeployment: git-mirror-http
|
||||
writeService: git-mirror-write
|
||||
writeDeployment: git-mirror-write
|
||||
readUrl: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/agentrun.git
|
||||
readUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git
|
||||
writeUrl: http://git-mirror-write.devops-infra.svc.cluster.local:8080/pikasTech/agentrun.git
|
||||
cachePvc: hwlab-git-mirror-cache
|
||||
cacheHostPath: null
|
||||
|
||||
@@ -84,6 +84,7 @@ sourceAuthority:
|
||||
owner: mirrors
|
||||
name: pikasTech-agentrun
|
||||
mirrorMode: controlled-push
|
||||
publicRead: true
|
||||
readUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git
|
||||
gitops:
|
||||
branch: jd01-v0.2-gitops
|
||||
@@ -104,6 +105,7 @@ sourceAuthority:
|
||||
owner: mirrors
|
||||
name: pikasTech-unidesk
|
||||
mirrorMode: controlled-push
|
||||
publicRead: true
|
||||
readUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-unidesk.git
|
||||
gitops:
|
||||
branch: master
|
||||
|
||||
@@ -57,7 +57,7 @@ repository:
|
||||
concurrencyLimit: 1
|
||||
params:
|
||||
git_read_url: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git
|
||||
git_write_url: http://git-mirror-write.devops-infra.svc.cluster.local:8080/pikasTech/agentrun.git
|
||||
git_write_url: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git
|
||||
source_branch: v0.2
|
||||
gitops_branch: jd01-v0.2-gitops
|
||||
source_snapshot_prefix: refs/unidesk/snapshots/gitea-actions/agentrun-v0.2
|
||||
|
||||
@@ -265,6 +265,14 @@ function agentRunBuildPublishTask(spec: AgentRunLaneSpec): Record<string, unknow
|
||||
image: "$(params.buildkit-image)",
|
||||
env: [
|
||||
{ name: "BUILDKITD_FLAGS", value: "--oci-worker-no-process-sandbox --oci-worker-net=host --allow-insecure-entitlement network.host" },
|
||||
{ name: "HTTP_PROXY", value: "$(params.build-http-proxy)" },
|
||||
{ name: "http_proxy", value: "$(params.build-http-proxy)" },
|
||||
{ name: "HTTPS_PROXY", value: "$(params.build-https-proxy)" },
|
||||
{ name: "https_proxy", value: "$(params.build-https-proxy)" },
|
||||
{ name: "ALL_PROXY", value: "$(params.build-https-proxy)" },
|
||||
{ name: "all_proxy", value: "$(params.build-https-proxy)" },
|
||||
{ name: "NO_PROXY", value: "$(params.build-no-proxy)" },
|
||||
{ name: "no_proxy", value: "$(params.build-no-proxy)" },
|
||||
],
|
||||
securityContext: { privileged: true, runAsUser: 1000, runAsGroup: 1000 },
|
||||
script: agentRunTektonBuildImageScript(),
|
||||
@@ -272,6 +280,9 @@ function agentRunBuildPublishTask(spec: AgentRunLaneSpec): Record<string, unknow
|
||||
{
|
||||
name: "publish-gitops",
|
||||
image: "$(params.tools-image)",
|
||||
env: [
|
||||
{ name: "GITEA_TOKEN", valueFrom: { secretKeyRef: { name: "pac-gitea-agentrun-jd01-v02", key: "token", optional: true } } },
|
||||
],
|
||||
script: agentRunTektonGitopsPublishScript(spec),
|
||||
},
|
||||
],
|
||||
@@ -381,6 +392,7 @@ function agentRunTektonProbeImageScript(): string {
|
||||
"else",
|
||||
" printf '{\"ok\":false,\"status\":\"cache-miss\",\"sourceCommit\":\"%s\",\"envIdentity\":\"%s\",\"valuesPrinted\":false}\\n' \"$(params.revision)\" \"$env_identity\" > \"$root/build-result.json\"",
|
||||
"fi",
|
||||
"chmod a+rw \"$root/build-result.json\"",
|
||||
"cat \"$root/build-result.json\"",
|
||||
].join("\n");
|
||||
}
|
||||
@@ -428,8 +440,14 @@ function agentRunTektonGitopsPublishScript(spec: AgentRunLaneSpec): string {
|
||||
"build_result=\"$root/build-result.json\"",
|
||||
"test -s \"$build_result\"",
|
||||
`templates_b64=${JSON.stringify(templateB64)}`,
|
||||
"git_write_url='$(params.git-write-url)'",
|
||||
"git_auth_url=\"$git_write_url\"",
|
||||
"if printf '%s' \"$git_write_url\" | grep -q '^http://gitea-http\\.'; then",
|
||||
" test -n \"${GITEA_TOKEN:-}\"",
|
||||
" git_auth_url=$(printf '%s' \"$git_write_url\" | sed \"s#^http://#http://x-access-token:${GITEA_TOKEN}@#\")",
|
||||
"fi",
|
||||
"rm -rf \"$root/gitops\"",
|
||||
"git clone \"$(params.git-write-url)\" \"$root/gitops\"",
|
||||
"git clone \"$git_auth_url\" \"$root/gitops\"",
|
||||
"cd \"$root/gitops\"",
|
||||
"git fetch origin \"$(params.gitops-branch)\" || true",
|
||||
"if git rev-parse --verify \"refs/remotes/origin/$(params.gitops-branch)^{commit}\" >/dev/null 2>&1; then git checkout -B \"$(params.gitops-branch)\" \"refs/remotes/origin/$(params.gitops-branch)\"; else git checkout --orphan \"$(params.gitops-branch)\"; git rm -rf . >/dev/null 2>&1 || true; fi",
|
||||
@@ -455,6 +473,7 @@ function agentRunTektonGitopsPublishScript(spec: AgentRunLaneSpec): string {
|
||||
"NODE",
|
||||
"git add source.json \"$(params.artifact-catalog)\" \"$(params.gitops-root)\"",
|
||||
"if git diff --quiet --cached; then changed=false; else changed=true; git -c user.email=agentrun@unidesk.local -c user.name='UniDesk AgentRun PaC' commit -m \"deploy: render AgentRun $(params.gitops-branch) from PaC\"; fi",
|
||||
"git remote set-url origin \"$git_auth_url\"",
|
||||
"git push -u origin \"$(params.gitops-branch)\"",
|
||||
"gitops_commit=$(git rev-parse HEAD)",
|
||||
"BUILD_RESULT=\"$build_result\" CHANGED=\"$changed\" GITOPS_COMMIT=\"$gitops_commit\" node <<'NODE'",
|
||||
|
||||
@@ -349,15 +349,19 @@ try:
|
||||
for repo in repos:
|
||||
owner = repo["gitea"]["owner"]
|
||||
if owner not in orgs:
|
||||
orgs[owner] = request("POST", "/api/v1/orgs", {"username": owner, "full_name": "UniDesk internal mirrors", "visibility": "private"}, expected=(201,), tolerate=(409, 422))
|
||||
orgs[owner] = {
|
||||
"create": request("POST", "/api/v1/orgs", {"username": owner, "full_name": "UniDesk internal mirrors", "visibility": "public"}, expected=(201,), tolerate=(409, 422)),
|
||||
"patch": request("PATCH", f"/api/v1/orgs/{owner}", {"full_name": "UniDesk internal mirrors", "visibility": "public"}, expected=(200,), tolerate=()),
|
||||
}
|
||||
repositories.append({
|
||||
"key": repo["key"],
|
||||
"owner": owner,
|
||||
"name": repo["gitea"]["name"],
|
||||
"create": request("POST", f"/api/v1/orgs/{owner}/repos", {"name": repo["gitea"]["name"], "private": False, "auto_init": False, "description": f"UniDesk controlled mirror for {repo['upstream']['repository']}"}, expected=(201,), tolerate=(409, 422)),
|
||||
"create": request("POST", f"/api/v1/orgs/{owner}/repos", {"name": repo["gitea"]["name"], "private": not bool(repo["gitea"].get("publicRead")), "auto_init": False, "description": f"UniDesk controlled mirror for {repo['upstream']['repository']}"}, expected=(201,), tolerate=(409, 422)),
|
||||
"patch": request("PATCH", f"/api/v1/repos/{owner}/{repo['gitea']['name']}", {"private": not bool(repo["gitea"].get("publicRead")), "description": f"UniDesk controlled mirror for {repo['upstream']['repository']}"}, expected=(200,), tolerate=()),
|
||||
})
|
||||
payload = {"auth": auth, "orgs": orgs, "repositories": repositories}
|
||||
ok = auth.get("ok") and all(v.get("ok") for v in orgs.values()) and all(item["create"].get("ok") for item in repositories)
|
||||
ok = auth.get("ok") and all(v["create"].get("ok") and v["patch"].get("ok") for v in orgs.values()) and all(item["create"].get("ok") and item["patch"].get("ok") for item in repositories)
|
||||
except Exception as exc:
|
||||
payload = {
|
||||
"auth": {"ok": False},
|
||||
|
||||
@@ -164,12 +164,13 @@ interface GiteaMirrorRepository {
|
||||
cloneUrl: string;
|
||||
branch: string;
|
||||
};
|
||||
gitea: {
|
||||
owner: string;
|
||||
name: string;
|
||||
mirrorMode: "controlled-push";
|
||||
readUrl: string;
|
||||
};
|
||||
gitea: {
|
||||
owner: string;
|
||||
name: string;
|
||||
mirrorMode: "controlled-push";
|
||||
publicRead: boolean;
|
||||
readUrl: string;
|
||||
};
|
||||
gitops: {
|
||||
branch: string;
|
||||
flushDisposition: string;
|
||||
@@ -484,6 +485,7 @@ function parseMirrorRepository(record: Record<string, unknown>, index: number):
|
||||
owner: y.stringField(gitea, "owner", `${path}.gitea`),
|
||||
name: giteaRepoNameField(gitea, "name", `${path}.gitea`),
|
||||
mirrorMode: y.enumField(gitea, "mirrorMode", `${path}.gitea`, ["controlled-push"] as const),
|
||||
publicRead: y.booleanField(gitea, "publicRead", `${path}.gitea`),
|
||||
readUrl: urlField(gitea, "readUrl", `${path}.gitea`),
|
||||
},
|
||||
gitops: {
|
||||
|
||||
@@ -79,10 +79,20 @@ ensure_token() {
|
||||
|
||||
ensure_webhook() {
|
||||
hooks=$(gitea_api GET "repos/$UNIDESK_PAC_GITEA_OWNER/$UNIDESK_PAC_GITEA_REPO/hooks")
|
||||
hook_id=$(printf '%s' "$hooks" | tr '{' '\n' | awk -v url="$UNIDESK_PAC_WEBHOOK_URL" 'index($0, url)>0 { if (match($0, /"id"[[:space:]]*:[[:space:]]*[0-9]+/)) { print substr($0, RSTART); exit } }' | sed -n 's/[^0-9]*\([0-9][0-9]*\).*/\1/p')
|
||||
hook_ids=$(HOOKS_JSON="$hooks" node <<'NODE'
|
||||
const data = JSON.parse(process.env.HOOKS_JSON || '[]');
|
||||
const url = process.env.UNIDESK_PAC_WEBHOOK_URL;
|
||||
for (const item of data) if (item?.config?.url === url && item?.id) console.log(item.id);
|
||||
NODE
|
||||
)
|
||||
hook_id=$(printf '%s\n' "$hook_ids" | sed -n '1p')
|
||||
body=$(printf '{"type":"gitea","config":{"url":"%s","content_type":"json","secret":"%s"},"events":["push"],"active":true}' "$UNIDESK_PAC_WEBHOOK_URL" "$UNIDESK_PAC_WEBHOOK_SECRET")
|
||||
if [ -n "$hook_id" ]; then
|
||||
gitea_api PATCH "repos/$UNIDESK_PAC_GITEA_OWNER/$UNIDESK_PAC_GITEA_REPO/hooks/$hook_id" "$body" >/dev/null
|
||||
printf '%s\n' "$hook_ids" | sed -n '2,$p' | while IFS= read -r duplicate_id; do
|
||||
[ -n "$duplicate_id" ] || continue
|
||||
gitea_api DELETE "repos/$UNIDESK_PAC_GITEA_OWNER/$UNIDESK_PAC_GITEA_REPO/hooks/$duplicate_id" >/dev/null || true
|
||||
done
|
||||
else
|
||||
created=$(gitea_api POST "repos/$UNIDESK_PAC_GITEA_OWNER/$UNIDESK_PAC_GITEA_REPO/hooks" "$body")
|
||||
hook_id=$(printf '%s' "$created" | sed -n 's/.*"id"[[:space:]]*:[[:space:]]*\([0-9][0-9]*\).*/\1/p')
|
||||
@@ -164,9 +174,11 @@ condition_status() {
|
||||
}
|
||||
|
||||
pipeline_rows() {
|
||||
payload=$(kubectl -n "$UNIDESK_PAC_TARGET_NAMESPACE" get pipelinerun -o json 2>/dev/null || echo '{"items":[]}')
|
||||
PIPELINE_JSON="$payload" node <<'NODE'
|
||||
const input = process.env.PIPELINE_JSON || '{"items":[]}';
|
||||
payload_file=$(mktemp)
|
||||
kubectl -n "$UNIDESK_PAC_TARGET_NAMESPACE" get pipelinerun -o json >"$payload_file" 2>/dev/null || printf '{"items":[]}' >"$payload_file"
|
||||
node - "$payload_file" <<'NODE'
|
||||
const fs = require('node:fs');
|
||||
const input = fs.readFileSync(process.argv[2], 'utf8') || '{"items":[]}';
|
||||
const data = input ? JSON.parse(input) : { items: [] };
|
||||
function cond(item) {
|
||||
const c = (item.status?.conditions || []).find((x) => x.type === 'Succeeded') || {};
|
||||
@@ -198,12 +210,15 @@ const rows = (data.items || [])
|
||||
});
|
||||
process.stdout.write(JSON.stringify(rows));
|
||||
NODE
|
||||
rm -f "$payload_file"
|
||||
}
|
||||
|
||||
task_rows() {
|
||||
payload=$(kubectl -n "$UNIDESK_PAC_TARGET_NAMESPACE" get taskrun -o json 2>/dev/null || echo '{"items":[]}')
|
||||
TASK_JSON="$payload" node <<'NODE'
|
||||
const input = process.env.TASK_JSON || '{"items":[]}';
|
||||
payload_file=$(mktemp)
|
||||
kubectl -n "$UNIDESK_PAC_TARGET_NAMESPACE" get taskrun -o json >"$payload_file" 2>/dev/null || printf '{"items":[]}' >"$payload_file"
|
||||
node - "$payload_file" <<'NODE'
|
||||
const fs = require('node:fs');
|
||||
const input = fs.readFileSync(process.argv[2], 'utf8') || '{"items":[]}';
|
||||
const data = input ? JSON.parse(input) : { items: [] };
|
||||
const pr = process.env.UNIDESK_PAC_TARGET_PIPELINERUN || '';
|
||||
function cond(item) {
|
||||
@@ -226,6 +241,37 @@ const rows = (data.items || [])
|
||||
});
|
||||
process.stdout.write(JSON.stringify(rows));
|
||||
NODE
|
||||
rm -f "$payload_file"
|
||||
}
|
||||
|
||||
artifact_summary() {
|
||||
if [ -z "${UNIDESK_PAC_TARGET_PIPELINERUN:-}" ]; then
|
||||
printf '{}'
|
||||
return
|
||||
fi
|
||||
log_file=$(mktemp)
|
||||
kubectl -n "$UNIDESK_PAC_TARGET_NAMESPACE" logs -l "tekton.dev/pipelineRun=$UNIDESK_PAC_TARGET_PIPELINERUN" --all-containers --tail=240 >"$log_file" 2>/dev/null || true
|
||||
node - "$log_file" <<'NODE'
|
||||
const fs = require('node:fs');
|
||||
const lines = fs.readFileSync(process.argv[2], 'utf8').split(/\r?\n/);
|
||||
const records = [];
|
||||
for (const line of lines) {
|
||||
const trimmed = line.trim();
|
||||
if (!trimmed.startsWith('{') || !trimmed.endsWith('}')) continue;
|
||||
try { records.push(JSON.parse(trimmed)); } catch {}
|
||||
}
|
||||
const publish = [...records].reverse().find((item) => item.phase === 'gitops-publish' || item.gitopsCommit);
|
||||
const image = publish || [...records].reverse().find((item) => item.imageStatus || item.status === 'reused' || item.status === 'built');
|
||||
process.stdout.write(JSON.stringify(image ? {
|
||||
imageStatus: image.imageStatus || image.status || null,
|
||||
envIdentity: image.envIdentity || null,
|
||||
digest: image.digest || null,
|
||||
gitopsCommit: image.gitopsCommit || null,
|
||||
sourceCommit: image.sourceCommit || null,
|
||||
valuesPrinted: false,
|
||||
} : { valuesPrinted: false }));
|
||||
NODE
|
||||
rm -f "$log_file"
|
||||
}
|
||||
|
||||
hook_summary() {
|
||||
@@ -246,14 +292,15 @@ status_action() {
|
||||
latest=$(printf '%s' "$pipelines" | node -e 'const fs=require("fs"); const a=JSON.parse(fs.readFileSync(0,"utf8")||"[]"); process.stdout.write(a[0]?.name||"")')
|
||||
export UNIDESK_PAC_TARGET_PIPELINERUN="$latest"
|
||||
tasks=$(task_rows)
|
||||
artifact=$(artifact_summary)
|
||||
hooks=$(hook_summary)
|
||||
argo=$(kubectl -n "$UNIDESK_PAC_ARGO_NAMESPACE" get application "$UNIDESK_PAC_ARGO_APPLICATION" -o json 2>/dev/null | node -e 'const fs=require("fs"); const s=fs.readFileSync(0,"utf8").trim(); if(!s){process.stdout.write("{}"); process.exit(0)} const a=JSON.parse(s); process.stdout.write(JSON.stringify({sync:a.status?.sync?.status||null, health:a.status?.health?.status||null, revision:a.status?.sync?.revision||null}))' || echo '{}')
|
||||
printf '{"ok":%s,"crdPresent":%s,"controllerReady":"%s","repositoryCondition":"%s","webhooks":%s,"pipelineRuns":%s,"taskRuns":%s,"argo":%s,"valuesPrinted":false}\n' \
|
||||
printf '{"ok":%s,"crdPresent":%s,"controllerReady":"%s","repositoryCondition":"%s","webhooks":%s,"pipelineRuns":%s,"taskRuns":%s,"artifact":%s,"argo":%s,"valuesPrinted":false}\n' \
|
||||
"$( [ -n "$crd" ] && [ "$controller_ready" != "0/0" ] && echo true || echo false )" \
|
||||
"$( [ -n "$crd" ] && echo true || echo false )" \
|
||||
"$(json_string "$controller_ready")" \
|
||||
"$(json_string "$repository_condition")" \
|
||||
"$hooks" "$pipelines" "$tasks" "$argo"
|
||||
"$hooks" "$pipelines" "$tasks" "$artifact" "$argo"
|
||||
}
|
||||
|
||||
webhook_test_action() {
|
||||
|
||||
@@ -316,7 +316,7 @@ async function status(config: UniDeskConfig, options: CommonOptions): Promise<Re
|
||||
target: targetSummary(target),
|
||||
config: compactConfigSummary(pac),
|
||||
summary,
|
||||
remote: options.raw ? parsed : options.full ? parsed : summary ?? compactCapture(result, { full: true }),
|
||||
remote: parsed === null ? compactCapture(result, { full: true }) : options.raw || options.full ? parsed : summary,
|
||||
next: nextCommands(target.id),
|
||||
};
|
||||
}
|
||||
@@ -464,6 +464,7 @@ function statusSummary(payload: Record<string, unknown>): Record<string, unknown
|
||||
webhookCount: arrayRecords(payload.webhooks).length,
|
||||
latestPipelineRun: latest,
|
||||
taskRuns,
|
||||
artifact: record(payload.artifact),
|
||||
argo: record(payload.argo),
|
||||
valuesPrinted: false,
|
||||
};
|
||||
@@ -581,6 +582,7 @@ function renderStatus(result: Record<string, unknown>): RenderedCliResult {
|
||||
const summary = record(result.summary);
|
||||
const latest = record(summary.latestPipelineRun);
|
||||
const taskRuns = arrayRecords(summary.taskRuns);
|
||||
const artifact = record(summary.artifact);
|
||||
const argo = record(summary.argo);
|
||||
const lines = [
|
||||
"PLATFORM-INFRA PIPELINES-AS-CODE STATUS",
|
||||
@@ -592,6 +594,9 @@ function renderStatus(result: Record<string, unknown>): RenderedCliResult {
|
||||
"TASKRUN DURATIONS",
|
||||
...(taskRuns.length === 0 ? ["-"] : table(["TASKRUN", "STATUS", "REASON", "DURATION_S"], taskRuns.map((item) => [short(stringValue(item.name), 56), stringValue(item.status), stringValue(item.reason), stringValue(item.durationSeconds)]))),
|
||||
"",
|
||||
"IMAGE / GITOPS",
|
||||
...table(["IMAGE_STATUS", "ENV_ID", "DIGEST", "GITOPS"], [[stringValue(artifact.imageStatus), stringValue(artifact.envIdentity), short(stringValue(artifact.digest), 18), short(stringValue(artifact.gitopsCommit))]]),
|
||||
"",
|
||||
"ARGO",
|
||||
...table(["SYNC", "HEALTH", "REVISION"], [[stringValue(argo.sync), stringValue(argo.health), short(stringValue(argo.revision))]]),
|
||||
"",
|
||||
|
||||
Reference in New Issue
Block a user