fix: 收敛HWLAB L2发布TaskRun
合并严格串行的计划与发布阶段,并在无构建计划时跳过build TaskRun。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -322,7 +322,7 @@ function planArtifactsTask({ serviceIds = defaultServiceIds } = {}) {
|
||||
results: serviceIds.flatMap((serviceId) => [
|
||||
{ name: affectedResultName(serviceId), description: `${serviceId} rollout affected according to ci-plan` },
|
||||
{ name: buildResultName(serviceId), description: `${serviceId} image build required according to ci-plan` }
|
||||
]),
|
||||
]).concat([{ name: "build-required", description: "true when at least one planned service image must be built" }]),
|
||||
workspaces: [{ name: "source" }],
|
||||
steps: [{
|
||||
name: "plan",
|
||||
@@ -402,12 +402,46 @@ function perServiceBuildTask(serviceId, { runAfter = ["plan-artifacts"] } = {})
|
||||
function perServiceBuildMatrixTask(serviceIds, { runAfter = ["plan-artifacts"] } = {}) {
|
||||
const task = perServiceBuildTask(serviceIds[0], { runAfter });
|
||||
task.name = "build-services";
|
||||
delete task.when;
|
||||
task.when = [{ input: "$(tasks.plan-artifacts.results.build-required)", operator: "in", values: ["true"] }];
|
||||
task.params = task.params.filter((param) => param.name !== "service-id");
|
||||
task.matrix = { params: [{ name: "service-id", value: serviceIds }] };
|
||||
return task;
|
||||
}
|
||||
|
||||
function mergeNamedEntries(...groups) {
|
||||
const entries = new Map();
|
||||
for (const group of groups) {
|
||||
for (const entry of group || []) {
|
||||
if (!entries.has(entry.name)) entries.set(entry.name, entry);
|
||||
}
|
||||
}
|
||||
return [...entries.values()];
|
||||
}
|
||||
|
||||
function releasePlanTask({ serviceIds = defaultServiceIds } = {}) {
|
||||
const plan = planArtifactsTask({ serviceIds });
|
||||
const prepareParams = [
|
||||
{ name: "git-url" }, { name: "git-read-url" }, { name: "gitops-read-url" }, { name: "source-branch" },
|
||||
{ name: "gitops-branch" }, { name: "lane" }, { name: "catalog-path" }, { name: "image-tag-mode" },
|
||||
{ name: "registry-prefix" }, { name: "services" }, { name: "revision" }
|
||||
];
|
||||
const prepareBindings = prepareParams.map(({ name }) => ({ name, value: `$(params.${name})` }));
|
||||
return {
|
||||
name: "plan-artifacts",
|
||||
workspaces: [{ name: "source", workspace: "source" }],
|
||||
taskSpec: {
|
||||
params: mergeNamedEntries(prepareParams, plan.taskSpec.params),
|
||||
results: plan.taskSpec.results,
|
||||
workspaces: [{ name: "source" }],
|
||||
steps: [
|
||||
{ name: "prepare-source", image: ciToolsRunnerImage, env: proxyEnv(), script: prepareSourceScript() },
|
||||
plan.taskSpec.steps[0]
|
||||
]
|
||||
},
|
||||
params: mergeNamedEntries(prepareBindings, plan.params)
|
||||
};
|
||||
}
|
||||
|
||||
function collectArtifactsTask({ serviceIds = defaultServiceIds } = {}) {
|
||||
return {
|
||||
name: "collect-artifacts",
|
||||
@@ -438,6 +472,52 @@ function collectArtifactsTask({ serviceIds = defaultServiceIds } = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
function gitopsPromoteTask() {
|
||||
return {
|
||||
name: "gitops-promote",
|
||||
workspaces: [
|
||||
{ name: "source", workspace: "source" },
|
||||
{ name: "gitea-auth", workspace: "gitea-auth" }
|
||||
],
|
||||
taskSpec: {
|
||||
params: [
|
||||
{ name: "git-url" }, { name: "git-read-url" }, { name: "gitops-read-url" }, { name: "git-write-url" }, { name: "gitops-username" },
|
||||
{ name: "source-branch" }, { name: "gitops-branch" }, { name: "lane" }, { name: "catalog-path" },
|
||||
{ name: "image-tag-mode" }, { name: "runtime-path" }, { name: "revision" }, { name: "registry-prefix" }
|
||||
],
|
||||
results: [{ name: "runtime-ready-required", description: "true when GitOps promotion changed runtime desired state and runtime readiness must be observed" }],
|
||||
workspaces: [{ name: "source" }, { name: "gitea-auth" }],
|
||||
steps: [{ name: "promote", image: ciToolsRunnerImage, env: proxyEnv(), script: gitopsPromoteScript() }]
|
||||
},
|
||||
params: [
|
||||
{ name: "git-url", value: "$(params.git-url)" }, { name: "git-read-url", value: "$(params.git-read-url)" },
|
||||
{ name: "gitops-read-url", value: "$(params.gitops-read-url)" }, { name: "git-write-url", value: "$(params.git-write-url)" },
|
||||
{ name: "gitops-username", value: "$(params.gitops-username)" }, { name: "source-branch", value: "$(params.source-branch)" },
|
||||
{ name: "gitops-branch", value: "$(params.gitops-branch)" }, { name: "lane", value: "$(params.lane)" },
|
||||
{ name: "catalog-path", value: "$(params.catalog-path)" }, { name: "image-tag-mode", value: "$(params.image-tag-mode)" },
|
||||
{ name: "runtime-path", value: "$(params.runtime-path)" }, { name: "revision", value: "$(params.revision)" },
|
||||
{ name: "registry-prefix", value: "$(params.registry-prefix)" }
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
function releaseArtifactsTask({ serviceIds = defaultServiceIds } = {}) {
|
||||
const collect = collectArtifactsTask({ serviceIds });
|
||||
const promote = gitopsPromoteTask();
|
||||
return {
|
||||
name: "release-artifacts",
|
||||
runAfter: ["build-services"],
|
||||
workspaces: promote.workspaces,
|
||||
taskSpec: {
|
||||
params: mergeNamedEntries(collect.taskSpec.params, promote.taskSpec.params),
|
||||
results: promote.taskSpec.results,
|
||||
workspaces: promote.taskSpec.workspaces,
|
||||
steps: [collect.taskSpec.steps[0], promote.taskSpec.steps[0]]
|
||||
},
|
||||
params: mergeNamedEntries(collect.params, promote.params)
|
||||
};
|
||||
}
|
||||
|
||||
function runtimeReadyScript() {
|
||||
return `#!/bin/sh
|
||||
set -eu
|
||||
@@ -549,12 +629,13 @@ function tektonTasks(args = { lane: "node" }, deploy = null) {
|
||||
|
||||
function tektonPipeline(args = { lane: "node" }, deploy = null) {
|
||||
const settings = ciLaneSettings(args, deploy);
|
||||
const serviceIds = serviceIdsForLane(args.lane, deploy);
|
||||
const runtimePath = gitopsPathForProfile(args, settings.profile, deploy);
|
||||
const preFlushRuntimeReadyTasks = isRuntimeLane(settings.lane)
|
||||
? []
|
||||
: [{
|
||||
...runtimeReadyTask({ profile: settings.profile, deploy }),
|
||||
when: [{ input: "$(tasks.gitops-promote.results.runtime-ready-required)", operator: "in", values: ["true"] }]
|
||||
when: [{ input: "$(tasks.release-artifacts.results.runtime-ready-required)", operator: "in", values: ["true"] }]
|
||||
}];
|
||||
return {
|
||||
apiVersion: "tekton.dev/v1",
|
||||
@@ -567,9 +648,9 @@ function tektonPipeline(args = { lane: "node" }, deploy = null) {
|
||||
"hwlab.pikastech.local/gitops-target": settings.gitopsTarget
|
||||
},
|
||||
annotations: {
|
||||
"hwlab.pikastech.local/source-config": "scripts/gitops-render.mjs#tekton-native-primitive-ci",
|
||||
"hwlab.pikastech.local/ci-contract": "tekton-native-primitive-tasks",
|
||||
"hwlab.pikastech.local/policy": "native-per-service-taskrun-image-publish"
|
||||
"hwlab.pikastech.local/source-config": "scripts/gitops-render.mjs#bounded-release-taskruns",
|
||||
"hwlab.pikastech.local/ci-contract": "plan-build-release-taskruns",
|
||||
"hwlab.pikastech.local/policy": "reviewed-plan-exact-scope"
|
||||
}
|
||||
},
|
||||
spec: {
|
||||
@@ -601,87 +682,9 @@ function tektonPipeline(args = { lane: "node" }, deploy = null) {
|
||||
{ name: "gitea-auth" }
|
||||
],
|
||||
tasks: [
|
||||
{
|
||||
name: "prepare-source",
|
||||
workspaces: [
|
||||
{ name: "source", workspace: "source" }
|
||||
],
|
||||
taskSpec: {
|
||||
params: [
|
||||
{ name: "git-url" },
|
||||
{ name: "git-read-url" },
|
||||
{ name: "gitops-read-url" },
|
||||
{ name: "source-branch" },
|
||||
{ name: "gitops-branch" },
|
||||
{ name: "lane" },
|
||||
{ name: "catalog-path" },
|
||||
{ name: "image-tag-mode" },
|
||||
{ name: "registry-prefix" },
|
||||
{ name: "services" },
|
||||
{ name: "revision" }
|
||||
],
|
||||
workspaces: [{ name: "source" }],
|
||||
steps: [{ name: "prepare-source", image: ciToolsRunnerImage, env: proxyEnv(), script: prepareSourceScript() }]
|
||||
},
|
||||
params: [
|
||||
{ name: "git-url", value: "$(params.git-url)" },
|
||||
{ name: "git-read-url", value: "$(params.git-read-url)" },
|
||||
{ name: "gitops-read-url", value: "$(params.gitops-read-url)" },
|
||||
{ name: "source-branch", value: "$(params.source-branch)" },
|
||||
{ name: "gitops-branch", value: "$(params.gitops-branch)" },
|
||||
{ name: "lane", value: "$(params.lane)" },
|
||||
{ name: "catalog-path", value: "$(params.catalog-path)" },
|
||||
{ name: "image-tag-mode", value: "$(params.image-tag-mode)" },
|
||||
{ name: "registry-prefix", value: "$(params.registry-prefix)" },
|
||||
{ name: "services", value: "$(params.services)" },
|
||||
{ name: "revision", value: "$(params.revision)" }
|
||||
]
|
||||
},
|
||||
...primitiveValidationTasks.map(primitiveValidationTask),
|
||||
...imagePublishTaskSet(args, deploy),
|
||||
{
|
||||
name: "gitops-promote",
|
||||
runAfter: ["collect-artifacts"],
|
||||
workspaces: [
|
||||
{ name: "source", workspace: "source" },
|
||||
{ name: "gitea-auth", workspace: "gitea-auth" }
|
||||
],
|
||||
taskSpec: {
|
||||
params: [
|
||||
{ name: "git-url" },
|
||||
{ name: "git-read-url" },
|
||||
{ name: "gitops-read-url" },
|
||||
{ name: "git-write-url" },
|
||||
{ name: "gitops-username" },
|
||||
{ name: "source-branch" },
|
||||
{ name: "gitops-branch" },
|
||||
{ name: "lane" },
|
||||
{ name: "catalog-path" },
|
||||
{ name: "image-tag-mode" },
|
||||
{ name: "runtime-path" },
|
||||
{ name: "revision" },
|
||||
{ name: "registry-prefix" }
|
||||
],
|
||||
results: [{ name: "runtime-ready-required", description: "true when GitOps promotion changed runtime desired state and runtime readiness must be observed" }],
|
||||
workspaces: [{ name: "source" }, { name: "gitea-auth" }],
|
||||
steps: [{ name: "promote", image: ciToolsRunnerImage, env: proxyEnv(), script: gitopsPromoteScript() }]
|
||||
},
|
||||
params: [
|
||||
{ name: "git-url", value: "$(params.git-url)" },
|
||||
{ name: "git-read-url", value: "$(params.git-read-url)" },
|
||||
{ name: "gitops-read-url", value: "$(params.gitops-read-url)" },
|
||||
{ name: "git-write-url", value: "$(params.git-write-url)" },
|
||||
{ name: "gitops-username", value: "$(params.gitops-username)" },
|
||||
{ name: "source-branch", value: "$(params.source-branch)" },
|
||||
{ name: "gitops-branch", value: "$(params.gitops-branch)" },
|
||||
{ name: "lane", value: "$(params.lane)" },
|
||||
{ name: "catalog-path", value: "$(params.catalog-path)" },
|
||||
{ name: "image-tag-mode", value: "$(params.image-tag-mode)" },
|
||||
{ name: "runtime-path", value: "$(params.runtime-path)" },
|
||||
{ name: "revision", value: "$(params.revision)" },
|
||||
{ name: "registry-prefix", value: "$(params.registry-prefix)" }
|
||||
]
|
||||
},
|
||||
releasePlanTask({ serviceIds }),
|
||||
perServiceBuildMatrixTask(serviceIds, { runAfter: ["plan-artifacts"] }),
|
||||
releaseArtifactsTask({ serviceIds }),
|
||||
...preFlushRuntimeReadyTasks
|
||||
]
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ const entries = allServices.map((serviceId) => {
|
||||
codeChanged: service.codeChanged ?? null
|
||||
};
|
||||
});
|
||||
fs.writeFileSync("/tekton/results/build-required", entries.some((entry) => entry.buildRequired) ? "true" : "false");
|
||||
for (const entry of entries) {
|
||||
fs.writeFileSync("/tekton/results/affected-" + entry.serviceId, entry.affected ? "true" : "false");
|
||||
fs.writeFileSync("/tekton/results/build-" + entry.serviceId, entry.buildRequired ? "true" : "false");
|
||||
|
||||
Reference in New Issue
Block a user