diff --git a/.tekton/hwlab-nc01-v03-pac.yaml b/.tekton/hwlab-nc01-v03-pac.yaml index 21b1bd12..82de4ef8 100644 --- a/.tekton/hwlab-nc01-v03-pac.yaml +++ b/.tekton/hwlab-nc01-v03-pac.yaml @@ -9,7 +9,7 @@ metadata: pipelinesascode.tekton.dev/on-cel-expression: "event == 'push' && target_branch == 'v0.3' && node == 'NC01'" pipelinesascode.tekton.dev/max-keep-runs: "8" unidesk.ai/owning-config-ref: "config/hwlab-node-lanes.yaml#lanes.v03.targets.NC01" - unidesk.ai/effective-config-sha256: sha256:006b744ab45984d288c71ff75c1bf4d027007ada2123d12cb066dabaa4657b10 + unidesk.ai/effective-config-sha256: sha256:fe147c2f6591cbe4fb8621d77668974d4b00a8c021b852dc4b88e1f0ad7ccf3f unidesk.ai/source-artifact-renderer: hwlab-runtime-lane unidesk.ai/source-artifact-mode: remote-pipeline-annotation pipelinesascode.tekton.dev/pipeline: ci/pipelines/hwlab-nc01-v03-ci-image-publish.yaml diff --git a/ci/pipelines/hwlab-nc01-v03-ci-image-publish.yaml b/ci/pipelines/hwlab-nc01-v03-ci-image-publish.yaml index d6c5468b..5ed2fa37 100644 --- a/ci/pipelines/hwlab-nc01-v03-ci-image-publish.yaml +++ b/ci/pipelines/hwlab-nc01-v03-ci-image-publish.yaml @@ -13,7 +13,7 @@ metadata: hwlab.pikastech.local/download-profile: jd01-node-default hwlab.pikastech.local/network-profile: jd01-node-ci-egress unidesk.ai/owning-config-ref: "config/hwlab-node-lanes.yaml#lanes.v03.targets.NC01" - unidesk.ai/effective-config-sha256: sha256:006b744ab45984d288c71ff75c1bf4d027007ada2123d12cb066dabaa4657b10 + unidesk.ai/effective-config-sha256: sha256:fe147c2f6591cbe4fb8621d77668974d4b00a8c021b852dc4b88e1f0ad7ccf3f unidesk.ai/source-artifact-renderer: hwlab-runtime-lane unidesk.ai/source-artifact-mode: remote-pipeline-annotation spec: diff --git a/scripts/gitops-render.mjs b/scripts/gitops-render.mjs index dae54112..9c3e1d6e 100644 --- a/scripts/gitops-render.mjs +++ b/scripts/gitops-render.mjs @@ -72,6 +72,7 @@ import { ciLaneSettings, tektonControlPlaneReconcilerCronJob, tektonPipeline, + tektonTasks, tektonPipelineRunTemplate, tektonPollerCronJob, tektonRbac @@ -213,6 +214,7 @@ async function plannedFiles(args) { putJson("registry/registry.yaml", registryManifest()); if (isRuntimeLane(args.lane)) putJson("devops-infra/git-mirror.yaml", devopsInfraGitMirrorManifest(args, deploy)); putJson(`${settings.tektonDir}/rbac.yaml`, tektonRbac(args)); + putJson(`${settings.tektonDir}/tasks.yaml`, { apiVersion: "v1", kind: "List", items: tektonTasks(args, deploy) }); putJson(`${settings.tektonDir}/pipeline.yaml`, tektonPipeline(args, deploy)); if (!isRuntimeLane(args.lane)) { putJson(`${settings.tektonDir}/poller.yaml`, tektonPollerCronJob(args, deploy)); diff --git a/scripts/src/gitops-render/tekton-manifests.mjs b/scripts/src/gitops-render/tekton-manifests.mjs index 5d555130..e64402d8 100644 --- a/scripts/src/gitops-render/tekton-manifests.mjs +++ b/scripts/src/gitops-render/tekton-manifests.mjs @@ -99,7 +99,7 @@ function tektonRbac(args = { lane: "node" }) { metadata: { name: pipelineRunWriterName, namespace: "hwlab-ci" }, rules: [ { apiGroups: ["tekton.dev"], resources: ["pipelineruns"], verbs: ["get", "list", "create"] }, - { apiGroups: ["tekton.dev"], resources: ["pipelines"], verbs: ["get", "patch", "create"] }, + { apiGroups: ["tekton.dev"], resources: ["pipelines", "tasks"], verbs: ["get", "patch", "create"] }, { apiGroups: ["batch"], resources: ["cronjobs"], verbs: ["get", "patch", "create"] }, { apiGroups: ["rbac.authorization.k8s.io"], resources: ["roles", "rolebindings"], verbs: ["get", "patch", "create"] }, { apiGroups: [""], resources: ["serviceaccounts"], verbs: ["get", "patch", "create"] } @@ -175,7 +175,7 @@ function tektonRbac(args = { lane: "node" }) { metadata: { name: "hwlab-tekton-pipelinerun-writer", namespace: "hwlab-ci" }, rules: [ { apiGroups: ["tekton.dev"], resources: ["pipelineruns"], verbs: ["get", "list", "create"] }, - { apiGroups: ["tekton.dev"], resources: ["pipelines"], verbs: ["get", "patch", "create"] }, + { apiGroups: ["tekton.dev"], resources: ["pipelines", "tasks"], verbs: ["get", "patch", "create"] }, { apiGroups: ["batch"], resources: ["cronjobs"], verbs: ["get", "patch", "create"] }, { apiGroups: ["rbac.authorization.k8s.io"], resources: ["roles", "rolebindings"], verbs: ["get", "patch", "create"] }, { apiGroups: [""], resources: ["serviceaccounts"], verbs: ["get", "patch", "create"] } @@ -477,6 +477,63 @@ function imagePublishTaskSet(args = { lane: "node" }, deploy = null) { ]; } +function taskResourceName(pipelineName, taskName) { + return `${pipelineName}-${taskName}`.replace(/[^a-z0-9-]/gu, "-").slice(0, 63).replace(/-+$/u, ""); +} + +function reusableTaskResource(pipelineName, task) { + return { + apiVersion: "tekton.dev/v1", + kind: "Task", + metadata: { + name: taskResourceName(pipelineName, task.name), + namespace: "hwlab-ci", + labels: { + "app.kubernetes.io/part-of": "hwlab", + "hwlab.pikastech.local/tekton-pipeline": pipelineName + } + }, + spec: task.taskSpec + }; +} + +function tektonTasks(args = { lane: "node" }, deploy = null) { + const settings = ciLaneSettings(args); + const prepareSource = { + name: "prepare-source", + taskSpec: { + params: [ + { name: "git-url" }, { name: "git-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" }, { name: "git-ssh" }], + steps: [{ name: "prepare-source", image: ciToolsRunnerImage, env: proxyEnv(), script: prepareSourceScript() }] + } + }; + const pipelineTasks = [ + prepareSource, + ...primitiveValidationTasks.map(primitiveValidationTask), + ...imagePublishTaskSet(args, deploy), + { + name: "gitops-promote", + taskSpec: { + params: [ + { name: "git-url" }, { name: "git-read-url" }, { name: "git-write-url" }, + { 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: "git-ssh" }], + steps: [{ name: "promote", image: ciToolsRunnerImage, env: proxyEnv(), script: gitopsPromoteScript() }] + } + }, + ...(isRuntimeLane(settings.lane) ? [] : [{ name: "runtime-ready", taskSpec: runtimeReadyTask({ profile: settings.profile }).taskSpec }]) + ]; + return pipelineTasks.map((task) => reusableTaskResource(settings.pipelineName, task)); +} + function tektonPipeline(args = { lane: "node" }, deploy = null) { const settings = ciLaneSettings(args); const runtimePath = gitopsPathForProfile(args, settings.profile); @@ -824,6 +881,7 @@ export { serviceWorkVolume, tektonControlPlaneReconcilerCronJob, tektonPipeline, + tektonTasks, tektonPipelineRunTemplate, tektonPollerCronJob, tektonRbac diff --git a/scripts/src/gitops-render/templates/control-plane-reconcile.sh b/scripts/src/gitops-render/templates/control-plane-reconcile.sh index 1e404cf8..d064a71c 100644 --- a/scripts/src/gitops-render/templates/control-plane-reconcile.sh +++ b/scripts/src/gitops-render/templates/control-plane-reconcile.sh @@ -42,6 +42,7 @@ const fieldManager = requiredEnv("FIELD_MANAGER"); const eventName = requiredEnv("RECONCILE_EVENT"); const manifestFiles = [ "deploy/gitops/node/" + tektonDir + "/rbac.yaml", + "deploy/gitops/node/" + tektonDir + "/tasks.yaml", "deploy/gitops/node/" + tektonDir + "/pipeline.yaml", ...(process.env.LANE === "v02" ? [] : [ "deploy/gitops/node/" + tektonDir + "/poller.yaml", @@ -54,6 +55,7 @@ const plurals = new Map([ ["Role", "roles"], ["RoleBinding", "rolebindings"], ["Pipeline", "pipelines"], + ["Task", "tasks"], ["CronJob", "cronjobs"], ["Application", "applications"], ["AppProject", "appprojects"]