The GCP counterpart of devops-lib. Registered in Jenkins under the same name, so consuming repos need no change: the two-line Jenkinsfile is identical on both clusters, and which library it resolves to is a property of the Jenkins running it. Substantive changes, all consequences of GKE being a real cloud: - Harbor speaks TLS here, so dind no longer passes --insecure-registry. It mounts the private CA at /etc/docker/certs.d/harbor.35.238.248.203.nip.io/ca.crt instead, from the registry-ca ConfigMap. This is not redundant with the node pool's trust: that covers pulls, performed by containerd on the node, while the push comes from dockerd in the build pod with its own trust store. Without it, pushes fail TLS verification while pulls of the same image succeed — which reads like a broken registry rather than a missing trust anchor. - The registry hostname changes in the push target and all five fallback Dockerfiles. It still must be spelled identically everywhere, because Docker matches credentials and trust by exact hostname. - helm_repo_url moves to cluster DNS. That clone runs in a build pod, so sending it out through the ingress and back would make the pipeline depend on Contour for pod-to-pod traffic. syncArgoApp already addressed ArgoCD this way and needed no change. - build-tools.Dockerfile is removed: devops-base-images-gcp owns it now, next to the mirrored base images, and the pod references the result by tag at base-images/build-tools:1. The base-images project is public, so the pod can pull it before it has any credentials. Verified: no homelab addresses remain; the pod template parses with the CA mount, the new image and no insecure-registry flag; and every fallback template's base image, with the default version buildDocker would pick, is present in the mirror manifest — an unmirrored tag now fails the build rather than silently falling back to Docker Hub. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LEsTefWWifp4ikvhHF5s6N
75 lines
3.9 KiB
Groovy
75 lines
3.9 KiB
Groovy
// New entry point — the homelab equivalent of the real devops-lib's
|
|
// buildPipeline.groovy. Same shape: a scripted pipeline global, so a
|
|
// service Jenkinsfile needs nothing but `@Library('devops-lib') _` plus
|
|
// one call to this — no pipeline{}/agent{}/stages{} block in the
|
|
// consuming repo at all, matching gkeCICD.groovy's Podcall precedent
|
|
// (podTemplate { node(POD_LABEL) { ... } }) rather than the declarative
|
|
// style the earlier version of this Jenkinsfile template used.
|
|
//
|
|
// Only repo_name is required — everything else defaults sensibly for a
|
|
// single-service repo on this one homelab cluster. Override any key by
|
|
// passing it explicitly, same as the real buildPipeline's param map, or
|
|
// by committing a config.yaml to the repo root (loadConfig merges it in
|
|
// after checkout — repo-committed values win over these defaults, same
|
|
// as the real system's config.yaml).
|
|
//
|
|
// dockerBuildVersion (e.g. 'go-1.22', 'node-20', 'python-3.12', 'java-21',
|
|
// 'php-8.3') is read by buildDocker.groovy only when the repo has no
|
|
// Dockerfile of its own — it picks which resources/com/homelab/<lang>-
|
|
// Dockerfile template to render and which base-image version to bake in.
|
|
// Repos that already ship a Dockerfile (like demo-go-app) never touch
|
|
// this key at all; it has no default because there's no sensible one to
|
|
// fall back to.
|
|
def call(Map config) {
|
|
config.service_name = config.service_name ?: config.repo_name
|
|
config.argo_app_name = config.argo_app_name ?: config.repo_name
|
|
config.harbor_project = config.harbor_project ?: 'homelab'
|
|
// Cluster DNS, not the ingress hostname: this clone happens from a build
|
|
// pod, so it is pod-to-pod traffic and has no business leaving the
|
|
// cluster and coming back in through Contour.
|
|
config.helm_repo_url = config.helm_repo_url ?: 'http://gitea-http.gitea.svc.cluster.local:3000/gitadmin/devops-helm-charts-gcp.git'
|
|
config.image_tag_yq_path = config.image_tag_yq_path ?: '.deployment.image.tag'
|
|
|
|
// Every stage file (both the ones adapted for this homelab and the
|
|
// untouched legacy ones carried over from the real devops-lib) reads
|
|
// `env.FAILURE` when setting currentBuild.result on error — the real
|
|
// system must define this as a global Jenkins environment variable
|
|
// somewhere upstream of buildPipeline.groovy, since it's referenced
|
|
// everywhere but never set anywhere in this repo. Left undefined,
|
|
// `env.FAILURE` is null, and `currentBuild.result = null` throws
|
|
// `NoSuchMethodError`/`NullPointerException` deep inside Jenkins'
|
|
// own result-normalization code — masking whatever the real error
|
|
// was. Defining it once here, before any stage runs, is the minimal
|
|
// fix rather than touching every individual stage file.
|
|
env.FAILURE = 'FAILURE'
|
|
|
|
podTemplate(yaml: libraryResource('org/homelab/dind-pod.yaml')) {
|
|
node(POD_LABEL) {
|
|
def checkOutObj = new com.homelab.stages.checkOut()
|
|
def loadConfigObj = new com.homelab.stages.loadConfig()
|
|
def runHooksObj = new com.homelab.stages.runHooks()
|
|
def buildDockerObj = new com.homelab.stages.buildDocker()
|
|
def updateHelmTagObj = new com.homelab.stages.updateHelmTag()
|
|
def syncArgoAppObj = new com.homelab.stages.syncArgoApp()
|
|
def notifyObj = new com.homelab.stages.notify()
|
|
|
|
try {
|
|
checkOutObj.run(config)
|
|
loadConfigObj.run(config)
|
|
runHooksObj.run(config, 'pre_build')
|
|
buildDockerObj.run(config)
|
|
runHooksObj.run(config, 'post_build')
|
|
updateHelmTagObj.run(config)
|
|
syncArgoAppObj.run(config)
|
|
}
|
|
catch (Exception e) {
|
|
currentBuild.result = 'FAILURE'
|
|
log.error(e.toString())
|
|
}
|
|
finally {
|
|
notifyObj.run(config)
|
|
}
|
|
}
|
|
}
|
|
}
|