buildDocker.groovy hardcoded harbor.35.238.248.203.nip.io as the push target, so the registry could not move without editing this shared library and every consumer moving in the same commit. It now reads config.harbor_registry, whose default lives in homelabPipeline.groovy beside harbor_project and every other key. The stage errors rather than defaulting when the value is missing. Carrying a second copy of the literal would leave two defaults free to disagree, and an unset value would otherwise build an image named "null/<project>/<repo>" — which docker accepts as a hostname and then fails to resolve, pointing nowhere near the cause. The dind pod no longer mounts the registry CA. That mount existed because the registry was a nip.io name, which no public CA will issue for, so cert-manager signed Harbor from a private CA; the node pool was told to trust it for pulls, but a push comes from dockerd inside the build pod, which has its own trust store. harbor.infra.deployshed.com carries a Let's Encrypt certificate that both already trust, so the mount, its volume and the whole arrangement go away rather than being repointed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LEsTefWWifp4ikvhHF5s6N
91 lines
4.9 KiB
Groovy
91 lines
4.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
|
|
// The Harbor project images are pushed to. Named apps-registry on this
|
|
// cluster, not the homelab's "homelab" — the project has to already
|
|
// exist, and Harbor rejects a push to a missing one with
|
|
// "unauthorized: project <name> not found", which reads like a
|
|
// credentials problem rather than a missing project.
|
|
config.harbor_project = config.harbor_project ?: 'apps-registry'
|
|
// The registry hostname images are pushed to and pulled from. This is
|
|
// the ONLY default for it — buildDocker.groovy deliberately errors
|
|
// rather than carrying a second copy, since two defaults for one value
|
|
// are free to disagree and the loser only shows up as a push to the
|
|
// wrong registry.
|
|
//
|
|
// It must be spelled identically here, in the dockerconfigjson auths
|
|
// key, and in Harbor's own externalURL: docker matches both stored
|
|
// credentials and TLS trust by exact hostname, so a mismatch fails as
|
|
// "unauthorized" rather than as anything resembling a name problem.
|
|
config.harbor_registry = config.harbor_registry ?: 'harbor.infra.deployshed.com'
|
|
// 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)
|
|
}
|
|
}
|
|
}
|
|
}
|