Files
pikasTech-HWLAB/scripts/src/gitops-render/tekton-manifests.mjs
T

831 lines
32 KiB
JavaScript

import {
argoApplicationName,
buildkitRunnerImage,
ciToolsRunnerImage,
defaultDevBaseImage,
defaultRegistryPrefix,
defaultServiceIds,
defaultSourceRepo,
gitopsPathFor,
gitopsPathForProfile,
gitopsTargetForProfile,
isRuntimeLane,
namespaceNameForProfile,
primitiveValidationTasks,
proxyEnv,
serviceIdsForLane,
servicesParamForLane
} from "./core.mjs";
import {
ciTimingShellFunction,
collectArtifactsScript,
controlPlaneReconcileScript,
gitopsPromoteScript,
perServicePublishScript,
planArtifactsScript,
pollerScript,
prepareSourceScript,
primitiveValidationTask,
primitiveValidationTaskNames
} from "./tekton-scripts.mjs";
function ciLaneSettings(argsOrLane = "node") {
const lane = typeof argsOrLane === "string" ? argsOrLane : argsOrLane.lane;
if (isRuntimeLane(lane)) {
const namespace = namespaceNameForProfile(lane);
return {
lane,
profile: lane,
gitopsTarget: lane,
pipelineName: `${namespace}-ci-image-publish`,
pipelineRunPrefix: `${namespace}-ci-poll`,
serviceAccountName: `${namespace}-tekton-runner`,
pollerName: `${namespace}-branch-poller`,
controlPlaneReconcilerName: `${namespace}-control-plane-reconciler`,
tektonDir: `tekton-${lane}`,
catalogPath: typeof argsOrLane === "object" ? argsOrLane.catalogPath : `deploy/artifact-catalog.${lane}.json`,
imageTagMode: typeof argsOrLane === "object" ? argsOrLane.imageTagMode : "full",
runtimeNamespace: namespace
};
}
return {
lane: "node",
profile: "dev",
gitopsTarget: "node",
pipelineName: "hwlab-node-ci-image-publish",
pipelineRunPrefix: "hwlab-node-ci-poll",
serviceAccountName: "hwlab-tekton-runner",
pollerName: "hwlab-node-branch-poller",
controlPlaneReconcilerName: "hwlab-node-control-plane-reconciler",
tektonDir: "tekton",
catalogPath: "deploy/artifact-catalog.dev.json",
imageTagMode: "short",
runtimeNamespace: "hwlab-dev"
};
}
function tektonRbac(args = { lane: "node" }) {
const settings = ciLaneSettings(args);
if (isRuntimeLane(settings.lane)) {
const runtimeObserverName = `${settings.runtimeNamespace}-runtime-observer`;
const pipelineRunWriterName = `${settings.runtimeNamespace}-pipelinerun-writer`;
const argoReconcilerName = `${settings.runtimeNamespace}-argocd-reconciler`;
return {
apiVersion: "v1",
kind: "List",
items: [
{ apiVersion: "v1", kind: "Namespace", metadata: { name: "hwlab-ci" } },
{ apiVersion: "v1", kind: "ServiceAccount", metadata: { name: settings.serviceAccountName, namespace: "hwlab-ci" } },
{
apiVersion: "rbac.authorization.k8s.io/v1",
kind: "Role",
metadata: { name: runtimeObserverName, namespace: settings.runtimeNamespace },
rules: [
{ apiGroups: [""], resources: ["pods", "services", "configmaps"], verbs: ["get", "list", "watch"] },
{ apiGroups: ["apps"], resources: ["deployments", "statefulsets"], verbs: ["get", "list", "watch"] },
{ apiGroups: ["batch"], resources: ["jobs"], verbs: ["get", "list", "watch"] }
]
},
{
apiVersion: "rbac.authorization.k8s.io/v1",
kind: "RoleBinding",
metadata: { name: runtimeObserverName, namespace: settings.runtimeNamespace },
subjects: [{ kind: "ServiceAccount", name: settings.serviceAccountName, namespace: "hwlab-ci" }],
roleRef: { apiGroup: "rbac.authorization.k8s.io", kind: "Role", name: runtimeObserverName }
},
{
apiVersion: "rbac.authorization.k8s.io/v1",
kind: "Role",
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: ["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"] }
]
},
{
apiVersion: "rbac.authorization.k8s.io/v1",
kind: "RoleBinding",
metadata: { name: pipelineRunWriterName, namespace: "hwlab-ci" },
subjects: [{ kind: "ServiceAccount", name: settings.serviceAccountName, namespace: "hwlab-ci" }],
roleRef: { apiGroup: "rbac.authorization.k8s.io", kind: "Role", name: pipelineRunWriterName }
},
{
apiVersion: "rbac.authorization.k8s.io/v1",
kind: "Role",
metadata: { name: argoReconcilerName, namespace: "argocd" },
rules: [
{ apiGroups: ["argoproj.io"], resources: ["applications", "appprojects"], verbs: ["get", "patch", "create"] },
{ apiGroups: ["rbac.authorization.k8s.io"], resources: ["roles", "rolebindings"], verbs: ["get", "patch", "create"] }
]
},
{
apiVersion: "rbac.authorization.k8s.io/v1",
kind: "RoleBinding",
metadata: { name: argoReconcilerName, namespace: "argocd" },
subjects: [{ kind: "ServiceAccount", name: settings.serviceAccountName, namespace: "hwlab-ci" }],
roleRef: { apiGroup: "rbac.authorization.k8s.io", kind: "Role", name: argoReconcilerName }
}
]
};
}
return {
apiVersion: "v1",
kind: "List",
items: [
{ apiVersion: "v1", kind: "Namespace", metadata: { name: "hwlab-ci" } },
{ apiVersion: "v1", kind: "ServiceAccount", metadata: { name: "hwlab-tekton-runner", namespace: "hwlab-ci" } },
{
apiVersion: "rbac.authorization.k8s.io/v1",
kind: "Role",
metadata: { name: "hwlab-node-control-plane-reconciler", namespace: "hwlab-dev" },
rules: [
{ apiGroups: ["rbac.authorization.k8s.io"], resources: ["roles", "rolebindings"], verbs: ["get", "patch", "create"] }
]
},
{
apiVersion: "rbac.authorization.k8s.io/v1",
kind: "RoleBinding",
metadata: { name: "hwlab-node-control-plane-reconciler", namespace: "hwlab-dev" },
subjects: [{ kind: "ServiceAccount", name: "hwlab-tekton-runner", namespace: "hwlab-ci" }],
roleRef: { apiGroup: "rbac.authorization.k8s.io", kind: "Role", name: "hwlab-node-control-plane-reconciler" }
},
{
apiVersion: "rbac.authorization.k8s.io/v1",
kind: "Role",
metadata: { name: "hwlab-tekton-runtime-observer", namespace: "hwlab-dev" },
rules: [
{ apiGroups: [""], resources: ["pods", "services", "configmaps"], verbs: ["get", "list", "watch"] },
{ apiGroups: ["apps"], resources: ["deployments", "statefulsets"], verbs: ["get", "list", "watch"] },
{ apiGroups: ["batch"], resources: ["jobs"], verbs: ["get", "list", "watch"] }
]
},
{
apiVersion: "rbac.authorization.k8s.io/v1",
kind: "RoleBinding",
metadata: { name: "hwlab-tekton-runtime-observer", namespace: "hwlab-dev" },
subjects: [{ kind: "ServiceAccount", name: "hwlab-tekton-runner", namespace: "hwlab-ci" }],
roleRef: { apiGroup: "rbac.authorization.k8s.io", kind: "Role", name: "hwlab-tekton-runtime-observer" }
},
{
apiVersion: "rbac.authorization.k8s.io/v1",
kind: "Role",
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: ["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"] }
]
},
{
apiVersion: "rbac.authorization.k8s.io/v1",
kind: "RoleBinding",
metadata: { name: "hwlab-tekton-pipelinerun-writer", namespace: "hwlab-ci" },
subjects: [{ kind: "ServiceAccount", name: "hwlab-tekton-runner", namespace: "hwlab-ci" }],
roleRef: { apiGroup: "rbac.authorization.k8s.io", kind: "Role", name: "hwlab-tekton-pipelinerun-writer" }
}
]
};
}
function buildTaskName(serviceId) {
return `build-${serviceId}`;
}
function affectedResultName(serviceId) {
return `affected-${serviceId}`;
}
function buildResultName(serviceId) {
return `build-${serviceId}`;
}
const serviceResultFields = Object.freeze([
"status",
"service-id",
"image",
"image-tag",
"digest",
"repository-digest",
"source-commit-id",
"component-input-hash",
"environment-input-hash",
"code-input-hash",
"runtime-mode",
"boot-repo",
"boot-commit",
"boot-sh",
"build-created-at",
"build-backend",
"reused-from",
"go-base-image",
"go-base-image-status",
"go-base-digest",
"go-base-build-duration-ms",
"go-base-buildkit-cache-ref"
]);
function serviceResultParamName(serviceId, field) {
return `${serviceId}-${field}`;
}
function serviceResultEnvName(serviceId, field) {
return `HWLAB_SERVICE_RESULT_${serviceId.toUpperCase().replace(/[^A-Z0-9]+/gu, "_")}_${field.toUpperCase().replace(/[^A-Z0-9]+/gu, "_")}`;
}
function serviceResultParams(serviceIds = defaultServiceIds) {
return serviceIds.flatMap((serviceId) => serviceResultFields.map((field) => ({ name: serviceResultParamName(serviceId, field), default: "" })));
}
function serviceResultParamValues(serviceIds = defaultServiceIds) {
return serviceIds.flatMap((serviceId) => serviceResultFields.map((field) => ({
name: serviceResultParamName(serviceId, field),
value: `$(tasks.${buildTaskName(serviceId)}.results.${field})`
})));
}
function serviceResultEnv(serviceIds = defaultServiceIds) {
return serviceIds.flatMap((serviceId) => serviceResultFields.map((field) => ({
name: serviceResultEnvName(serviceId, field),
value: `$(params.${serviceResultParamName(serviceId, field)})`
})));
}
function serviceWorkVolume() {
return { name: "service-work", emptyDir: {} };
}
function buildkitBinVolume() {
return { name: "buildkit-bin", emptyDir: {} };
}
function buildkitRunVolume() {
return { name: "buildkit-run", emptyDir: {} };
}
function prepareBuildkitClientStep() {
return {
name: "prepare-buildkit-client",
image: buildkitRunnerImage,
securityContext: { runAsUser: 0, runAsGroup: 0 },
volumeMounts: [{ name: "buildkit-bin", mountPath: "/workspace/buildkit-bin" }],
script: `#!/bin/sh
set -eu
mkdir -p /workspace/buildkit-bin
cp /usr/bin/buildctl /workspace/buildkit-bin/
chmod +x /workspace/buildkit-bin/*
`
};
}
function buildkitSidecar() {
return {
name: "buildkitd",
image: buildkitRunnerImage,
args: ["--addr", "unix:///workspace/buildkit-run/buildkitd.sock", "--oci-worker-no-process-sandbox"],
env: proxyEnv(),
volumeMounts: [{ name: "buildkit-run", mountPath: "/workspace/buildkit-run" }],
securityContext: {
runAsUser: 1000,
runAsGroup: 1000,
allowPrivilegeEscalation: true,
appArmorProfile: { type: "Unconfined" },
seccompProfile: { type: "Unconfined" }
}
};
}
function planArtifactsTask({ serviceIds = defaultServiceIds } = {}) {
return {
name: "plan-artifacts",
runAfter: primitiveValidationTaskNames(),
workspaces: [{ name: "source", workspace: "source" }],
taskSpec: {
params: [
{ name: "git-url" },
{ name: "git-read-url" },
{ name: "gitops-branch" },
{ name: "lane" },
{ name: "revision" },
{ name: "catalog-path" },
{ name: "registry-prefix" },
{ name: "services" }
],
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` }
]),
workspaces: [{ name: "source" }],
steps: [{
name: "plan",
image: ciToolsRunnerImage,
env: [
{ name: "HWLAB_SELECTED_SERVICES", value: "$(params.services)" },
{ name: "HWLAB_DEV_REGISTRY_K8S_NATIVE", value: "1" },
{ name: "HWLAB_TEKTON_PIPELINERUN", value: "$(context.pipelineRun.name)" },
...proxyEnv()
],
script: planArtifactsScript()
}]
},
params: [
{ name: "git-url", value: "$(params.git-url)" },
{ name: "git-read-url", value: "$(params.git-read-url)" },
{ name: "gitops-branch", value: "$(params.gitops-branch)" },
{ name: "lane", value: "$(params.lane)" },
{ name: "revision", value: "$(params.revision)" },
{ name: "catalog-path", value: "$(params.catalog-path)" },
{ name: "registry-prefix", value: "$(params.registry-prefix)" },
{ name: "services", value: "$(params.services)" }
]
};
}
function perServiceBuildTask(serviceId, { runAfter = ["plan-artifacts"] } = {}) {
return {
name: buildTaskName(serviceId),
runAfter,
workspaces: [{ name: "source", workspace: "source" }],
when: [{ input: `$(tasks.plan-artifacts.results.${buildResultName(serviceId)})`, operator: "in", values: ["true"] }],
taskSpec: {
params: [
{ name: "revision" },
{ name: "lane" },
{ name: "catalog-path" },
{ name: "image-tag-mode" },
{ name: "registry-prefix" },
{ name: "service-id" },
{ name: "base-image" },
{ name: "build-cache-mode" }
],
results: serviceResultFields.map((field) => ({ name: field, description: `${serviceId} ${field}` })),
workspaces: [{ name: "source" }],
volumes: [serviceWorkVolume(), buildkitBinVolume(), buildkitRunVolume()],
sidecars: [buildkitSidecar()],
steps: [
prepareBuildkitClientStep(),
{
name: "publish",
image: ciToolsRunnerImage,
securityContext: { runAsUser: 1000, runAsGroup: 1000 },
env: proxyEnv(),
volumeMounts: [{ name: "service-work", mountPath: "/workspace/service-work" }, { name: "buildkit-bin", mountPath: "/workspace/buildkit-bin" }, { name: "buildkit-run", mountPath: "/workspace/buildkit-run" }],
script: perServicePublishScript()
}
]
},
params: [
{ name: "revision", value: "$(params.revision)" },
{ 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: "service-id", value: serviceId },
{ name: "base-image", value: "$(params.base-image)" },
{ name: "build-cache-mode", value: "$(params.build-cache-mode)" }
]
};
}
function collectArtifactsTask({ serviceIds = defaultServiceIds } = {}) {
return {
name: "collect-artifacts",
runAfter: serviceIds.map(buildTaskName),
workspaces: [{ name: "source", workspace: "source" }],
taskSpec: {
params: [
{ name: "revision" },
{ name: "lane" },
{ name: "catalog-path" },
{ name: "image-tag-mode" },
{ name: "registry-prefix" },
{ name: "services" },
{ name: "base-image" }
],
workspaces: [{ name: "source" }],
steps: [{ name: "collect", image: ciToolsRunnerImage, env: proxyEnv(), script: collectArtifactsScript() }]
},
params: [
{ name: "revision", value: "$(params.revision)" },
{ 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: "base-image", value: "$(params.base-image)" }
]
};
}
function runtimeReadyScript() {
return `#!/bin/sh
set -eu
${ciTimingShellFunction()}
export HWLAB_TEKTON_PIPELINERUN="$(context.pipelineRun.name)"
export HWLAB_TEKTON_TASKRUN="$(context.taskRun.name)"
export HWLAB_TEKTON_TASK="runtime-ready"
export HWLAB_SOURCE_REVISION="$(params.revision)"
export HWLAB_RUNTIME_READY_TIMEOUT_MS="$(params.timeout-ms)"
cd /workspace/source/repo
node scripts/ci/runtime-ready.mjs
`;
}
function runtimeReadyTask({ profile = "dev" } = {}) {
return {
name: "runtime-ready",
runAfter: ["gitops-promote"],
workspaces: [{ name: "source", workspace: "source" }],
taskSpec: {
params: [{ name: "revision" }, { name: "runtime-namespace" }, { name: "gitops-target" }, { name: "argo-application" }, { name: "timeout-ms" }],
workspaces: [{ name: "source" }],
steps: [{
name: "runtime-ready",
image: ciToolsRunnerImage,
env: [
...proxyEnv(),
{ name: "HWLAB_RUNTIME_NAMESPACE", value: "$(params.runtime-namespace)" },
{ name: "HWLAB_GITOPS_TARGET", value: "$(params.gitops-target)" },
{ name: "HWLAB_ARGO_APPLICATION", value: "$(params.argo-application)" }
],
script: runtimeReadyScript()
}]
},
params: [
{ name: "revision", value: "$(params.revision)" },
{ name: "runtime-namespace", value: namespaceNameForProfile(profile) },
{ name: "gitops-target", value: gitopsTargetForProfile(profile) },
{ name: "argo-application", value: argoApplicationName(profile) },
{ name: "timeout-ms", value: "$(params.runtime-ready-timeout-ms)" }
]
};
}
function imagePublishTaskSet(args = { lane: "node" }, deploy = null) {
const serviceIds = serviceIdsForLane(args.lane, deploy);
const buildTasks = serviceIds.map((serviceId) => perServiceBuildTask(serviceId, {
runAfter: ["plan-artifacts"]
}));
return [
planArtifactsTask({ serviceIds }),
...buildTasks,
collectArtifactsTask({ serviceIds })
];
}
function tektonPipeline(args = { lane: "node" }, deploy = null) {
const settings = ciLaneSettings(args);
const runtimePath = gitopsPathForProfile(args, settings.profile);
const preFlushRuntimeReadyTasks = isRuntimeLane(settings.lane)
? []
: [{
...runtimeReadyTask({ profile: settings.profile }),
when: [{ input: "$(tasks.gitops-promote.results.runtime-ready-required)", operator: "in", values: ["true"] }]
}];
return {
apiVersion: "tekton.dev/v1",
kind: "Pipeline",
metadata: {
name: settings.pipelineName,
namespace: "hwlab-ci",
labels: {
"app.kubernetes.io/part-of": "hwlab",
"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"
}
},
spec: {
params: [
{ name: "git-url", type: "string", default: defaultSourceRepo },
{ name: "git-read-url", type: "string", default: args.gitReadUrl },
{ name: "git-write-url", type: "string", default: args.gitWriteUrl },
{ name: "source-branch", type: "string", default: args.sourceBranch },
{ name: "gitops-branch", type: "string", default: args.gitopsBranch },
{ name: "lane", type: "string", default: settings.lane },
{ name: "catalog-path", type: "string", default: args.catalogPath || settings.catalogPath },
{ name: "image-tag-mode", type: "string", default: args.imageTagMode || settings.imageTagMode },
{ name: "runtime-path", type: "string", default: runtimePath },
{ name: "revision", type: "string", description: "Full git commit SHA; the only source truth for image tags." },
{ name: "registry-prefix", type: "string", default: defaultRegistryPrefix },
{ name: "services", type: "string", default: servicesParamForLane(args.lane, deploy) },
{ name: "base-image", type: "string", default: defaultDevBaseImage },
{ name: "build-cache-mode", type: "string", default: "registry" },
{ name: "runtime-ready-timeout-ms", type: "string", default: "60000" }
],
workspaces: [
{ name: "source" },
{ name: "git-ssh" }
],
tasks: [
{
name: "prepare-source",
workspaces: [
{ name: "source", workspace: "source" },
{ name: "git-ssh", workspace: "git-ssh" }
],
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() }]
},
params: [
{ name: "git-url", value: "$(params.git-url)" },
{ name: "git-read-url", value: "$(params.git-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: "git-ssh", workspace: "git-ssh" }
],
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() }]
},
params: [
{ name: "git-url", value: "$(params.git-url)" },
{ name: "git-read-url", value: "$(params.git-read-url)" },
{ name: "git-write-url", value: "$(params.git-write-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: "runtime-path", value: "$(params.runtime-path)" },
{ name: "revision", value: "$(params.revision)" },
{ name: "registry-prefix", value: "$(params.registry-prefix)" }
]
},
...preFlushRuntimeReadyTasks
]
}
};
}
function tektonPipelineRunTemplate({ source, args }) {
const settings = ciLaneSettings(args);
const runtimePath = gitopsPathForProfile(args, settings.profile);
return {
apiVersion: "tekton.dev/v1",
kind: "PipelineRun",
metadata: {
generateName: `${settings.pipelineRunPrefix}-manual-`,
namespace: "hwlab-ci",
labels: {
"app.kubernetes.io/part-of": "hwlab",
"hwlab.pikastech.local/gitops-target": settings.gitopsTarget,
"hwlab.pikastech.local/source-commit": source.full
}
},
spec: {
pipelineRef: { name: settings.pipelineName },
taskRunTemplate: {
serviceAccountName: settings.serviceAccountName,
podTemplate: {
hostNetwork: true,
dnsPolicy: "ClusterFirstWithHostNet",
securityContext: { fsGroup: 1000 }
}
},
params: [
{ name: "git-url", value: args.sourceRepo },
{ name: "git-read-url", value: args.gitReadUrl },
{ name: "git-write-url", value: args.gitWriteUrl },
{ name: "source-branch", value: args.sourceBranch },
{ name: "gitops-branch", value: args.gitopsBranch },
{ name: "lane", value: settings.lane },
{ name: "catalog-path", value: args.catalogPath || settings.catalogPath },
{ name: "image-tag-mode", value: args.imageTagMode || settings.imageTagMode },
{ name: "runtime-path", value: runtimePath },
{ name: "revision", value: source.full },
{ name: "registry-prefix", value: args.registryPrefix },
{ name: "base-image", value: defaultDevBaseImage },
{ name: "build-cache-mode", value: "registry" }
],
workspaces: [
{ name: "source", volumeClaimTemplate: { spec: { accessModes: ["ReadWriteOnce"], resources: { requests: { storage: "8Gi" } } } } },
{ name: "git-ssh", secret: { secretName: "hwlab-git-ssh" } }
]
}
};
}
function tektonPollerCronJob(args, deploy) {
const settings = ciLaneSettings(args);
if (settings.lane === "v02") throw new Error("v02 CI/CD is manually triggered by UniDesk CLI and must not render a branch poller CronJob");
return {
apiVersion: "batch/v1",
kind: "CronJob",
metadata: {
name: settings.pollerName,
namespace: "hwlab-ci",
labels: {
"app.kubernetes.io/part-of": "hwlab",
"hwlab.pikastech.local/gitops-target": settings.gitopsTarget
},
annotations: {
"hwlab.pikastech.local/source-branch": args.sourceBranch,
"hwlab.pikastech.local/gitops-branch": args.gitopsBranch
}
},
spec: {
schedule: settings.lane === "v02" ? "*/10 * * * *" : "* * * * *",
concurrencyPolicy: "Forbid",
successfulJobsHistoryLimit: 3,
failedJobsHistoryLimit: 3,
jobTemplate: {
spec: {
backoffLimit: 1,
template: {
metadata: {
labels: {
"app.kubernetes.io/part-of": "hwlab",
"hwlab.pikastech.local/gitops-target": settings.gitopsTarget
}
},
spec: {
serviceAccountName: settings.serviceAccountName,
restartPolicy: "Never",
hostNetwork: true,
dnsPolicy: "ClusterFirstWithHostNet",
containers: [{
name: "poll",
image: ciToolsRunnerImage,
imagePullPolicy: "IfNotPresent",
env: [
...proxyEnv(),
{ name: "POD_NAMESPACE", valueFrom: { fieldRef: { fieldPath: "metadata.namespace" } } },
{ name: "PIPELINE_NAME", value: settings.pipelineName },
{ name: "PIPELINERUN_PREFIX", value: settings.pipelineRunPrefix },
{ name: "SERVICE_ACCOUNT_NAME", value: settings.serviceAccountName },
{ name: "GITOPS_TARGET", value: settings.gitopsTarget },
{ name: "LANE", value: settings.lane },
{ name: "CATALOG_PATH", value: args.catalogPath || settings.catalogPath },
{ name: "IMAGE_TAG_MODE", value: args.imageTagMode || settings.imageTagMode },
{ name: "RUNTIME_PATH", value: gitopsPathForProfile(args, settings.profile) },
{ name: "GIT_URL", value: args.sourceRepo },
{ name: "GIT_READ_URL", value: args.gitReadUrl },
{ name: "SOURCE_BRANCH", value: args.sourceBranch },
{ name: "GITOPS_BRANCH", value: args.gitopsBranch },
{ name: "REGISTRY_PREFIX", value: args.registryPrefix },
{ name: "SERVICES", value: servicesParamForLane(args.lane, deploy) },
{ name: "BASE_IMAGE", value: defaultDevBaseImage }
],
volumeMounts: [{ name: "git-ssh", mountPath: "/workspace/git-ssh", readOnly: true }],
command: ["/bin/sh", "-c"],
args: [pollerScript()]
}],
volumes: [{ name: "git-ssh", secret: { secretName: "hwlab-git-ssh" } }]
}
}
}
}
}
};
}
function tektonControlPlaneReconcilerCronJob(args) {
const settings = ciLaneSettings(args);
if (settings.lane === "v02") throw new Error("v02 CI/CD is manually triggered by UniDesk CLI and must not render a control-plane reconciler CronJob");
return {
apiVersion: "batch/v1",
kind: "CronJob",
metadata: {
name: settings.controlPlaneReconcilerName,
namespace: "hwlab-ci",
labels: {
"app.kubernetes.io/part-of": "hwlab",
"hwlab.pikastech.local/gitops-target": settings.gitopsTarget
},
annotations: {
"hwlab.pikastech.local/source-branch": args.sourceBranch,
"hwlab.pikastech.local/gitops-branch": args.gitopsBranch,
"hwlab.pikastech.local/purpose": "render-and-apply-node-ci-control-plane"
}
},
spec: {
schedule: "*/10 * * * *",
concurrencyPolicy: "Forbid",
successfulJobsHistoryLimit: 3,
failedJobsHistoryLimit: 3,
jobTemplate: {
spec: {
backoffLimit: 1,
template: {
metadata: {
labels: {
"app.kubernetes.io/part-of": "hwlab",
"hwlab.pikastech.local/gitops-target": settings.gitopsTarget
}
},
spec: {
serviceAccountName: settings.serviceAccountName,
restartPolicy: "Never",
hostNetwork: true,
dnsPolicy: "ClusterFirstWithHostNet",
containers: [{
name: "reconcile",
image: ciToolsRunnerImage,
imagePullPolicy: "IfNotPresent",
env: [
...proxyEnv(),
{ name: "POD_NAMESPACE", valueFrom: { fieldRef: { fieldPath: "metadata.namespace" } } },
{ name: "LANE", value: settings.lane },
{ name: "CATALOG_PATH", value: args.catalogPath || settings.catalogPath },
{ name: "IMAGE_TAG_MODE", value: args.imageTagMode || settings.imageTagMode },
{ name: "TEKTON_DIR", value: settings.tektonDir },
{ name: "ARGO_FILES", value: settings.lane === "v02" ? `${gitopsPathFor(args, "argocd/project.yaml")},${gitopsPathFor(args, "argocd/application-v02.yaml")}` : "" },
{ name: "FIELD_MANAGER", value: settings.controlPlaneReconcilerName },
{ name: "RECONCILE_EVENT", value: `${settings.gitopsTarget}-control-plane-reconciled` },
{ name: "GIT_URL", value: args.sourceRepo },
{ name: "GIT_READ_URL", value: args.gitReadUrl },
{ name: "SOURCE_BRANCH", value: args.sourceBranch },
{ name: "GITOPS_BRANCH", value: args.gitopsBranch },
{ name: "REGISTRY_PREFIX", value: args.registryPrefix }
],
volumeMounts: [{ name: "git-ssh", mountPath: "/workspace/git-ssh", readOnly: true }],
command: ["/bin/sh", "-c"],
args: [controlPlaneReconcileScript()]
}],
volumes: [{ name: "git-ssh", secret: { secretName: "hwlab-git-ssh" } }]
}
}
}
}
}
};
}
export {
affectedResultName,
buildResultName,
buildTaskName,
buildkitBinVolume,
buildkitRunVolume,
buildkitSidecar,
ciLaneSettings,
collectArtifactsTask,
imagePublishTaskSet,
perServiceBuildTask,
planArtifactsTask,
prepareBuildkitClientStep,
runtimeReadyScript,
runtimeReadyTask,
serviceResultEnv,
serviceResultEnvName,
serviceResultParamName,
serviceResultParams,
serviceResultParamValues,
serviceWorkVolume,
tektonControlPlaneReconcilerCronJob,
tektonPipeline,
tektonPipelineRunTemplate,
tektonPollerCronJob,
tektonRbac
};