pipeline { triggers { pollSCM('H/5 * * * *') } agent { kubernetes { label 'harbor-arm-build' defaultContainer 'builder' yaml """ apiVersion: v1 kind: Pod spec: nodeSelector: kubernetes.io/arch: arm64 hardware: rpi5 containers: - name: dind image: docker:27-dind securityContext: privileged: true env: - name: DOCKER_TLS_CERTDIR value: "" command: - /bin/sh - -c args: - | set -euo pipefail apk add --no-cache dnsmasq cat > /etc/dnsmasq.conf <<'EOF' filter-aaaa server=10.43.0.10 EOF dnsmasq echo "nameserver 127.0.0.1" > /etc/resolv.conf exec dockerd-entrypoint.sh --mtu=1400 volumeMounts: - name: dind-storage mountPath: /var/lib/docker - name: builder image: docker:27 command: ["cat"] tty: true env: - name: DOCKER_HOST value: tcp://localhost:2375 - name: DOCKER_TLS_CERTDIR value: "" volumeMounts: - name: workspace-volume mountPath: /home/jenkins/agent - name: docker-config-writable mountPath: /root/.docker - name: docker-config-secret mountPath: /docker-config volumes: - name: docker-config-secret secret: secretName: harbor-robot-pipeline items: - key: .dockerconfigjson path: config.json - name: docker-config-writable emptyDir: {} - name: workspace-volume emptyDir: {} - name: dind-storage emptyDir: {} """ } } environment { VERSION = 'v2.14.1' TAG_SUFFIX = '-arm64' // Avoid `REGISTRY` here because Harbor's Makefiles use `REGISTRY=registry` and // run sub-makes with `-e`, so environment variables override make vars. IMAGE_NAMESPACE = 'registry.bstein.dev/infra' HARBOR_TARBALL = "https://github.com/goharbor/harbor/archive/refs/tags/${VERSION}.tar.gz" } options { disableConcurrentBuilds() } stages { stage('Checkout Jenkinsfile') { steps { git credentialsId: 'gitea-pat', url: 'https://scm.bstein.dev/bstein/harbor-arm-build.git' } } stage('Prep toolchain') { steps { container('builder') { sh ''' set -euo pipefail apk add --no-cache bash curl make tar gzip git coreutils go ncurses ''' } } } stage('Fetch harbor source') { steps { container('builder') { sh ''' set -euo pipefail rm -rf harbor-src mkdir -p harbor-src curl -sSL "${HARBOR_TARBALL}" | tar xz -C harbor-src ''' } } } stage('Build & push arm64 images') { steps { container('builder') { sh ''' set -euo pipefail VERSIONTAG="${VERSION}${TAG_SUFFIX}.${BUILD_NUMBER}" export VERSIONTAG mkdir -p /root/.docker cp /docker-config/config.json /root/.docker/config.json # Harbor's build uses git metadata; Jenkins workspace ownership can trigger # Git's safe.directory protection in containerized builds. git config --global --add safe.directory '*' # `harbor-src/` itself matches `harbor-*`, so exclude it. SRC_DIR=$(find harbor-src -mindepth 1 -maxdepth 1 -type d -name "harbor-*" | head -n1) cd "${SRC_DIR}" export DOCKER_BUILDKIT=1 # Harbor's root Makefile hard-sets many defaults (e.g. IMAGENAMESPACE=goharbor, # PULL_BASE_FROM_DOCKERHUB=true). Environment exports are not sufficient because # makefile assignments override the environment. Pass overrides on the make # command line so they win. make compile make \ VERSIONTAG="${VERSIONTAG}" \ BASEIMAGETAG="${VERSIONTAG}" \ IMAGENAMESPACE="${IMAGE_NAMESPACE}" \ BASEIMAGENAMESPACE="${IMAGE_NAMESPACE}" \ DOCKERNETWORK=host \ PULL_BASE_FROM_DOCKERHUB=false \ BUILD_BASE=true \ BUILDTRIVYADP=false \ BUILD_INSTALLER=true \ build # Retag a few upstream image names to our internal naming convention # (so Helm values can keep using `harbor-*` consistently). docker tag "${IMAGE_NAMESPACE}/prepare:${VERSIONTAG}" "${IMAGE_NAMESPACE}/harbor-prepare:${VERSIONTAG}" || true docker tag "${IMAGE_NAMESPACE}/redis-photon:${VERSIONTAG}" "${IMAGE_NAMESPACE}/harbor-redis:${VERSIONTAG}" || true docker tag "${IMAGE_NAMESPACE}/nginx-photon:${VERSIONTAG}" "${IMAGE_NAMESPACE}/harbor-nginx:${VERSIONTAG}" || true docker tag "${IMAGE_NAMESPACE}/registry-photon:${VERSIONTAG}" "${IMAGE_NAMESPACE}/harbor-registry:${VERSIONTAG}" || true # Push every image we just built for this tag under our namespace. docker images --format '{{.Repository}}:{{.Tag}}' \ | awk -v ns="${IMAGE_NAMESPACE}/" -v tag="${VERSIONTAG}" 'index($0, ns)==1 && $0 ~ ":"tag"$"' \ | sort -u \ | while read -r img; do echo "Pushing ${img}" docker push "${img}" done ''' } } } } post { always { echo 'done' } } }