pipeline { parameters { string( name: 'HARBOR_VERSION', defaultValue: '', description: 'Harbor tag to build (e.g. v2.14.1). Leave empty to build the latest release.' ) } agent { kubernetes { label 'harbor-arm-build' defaultContainer 'builder' yaml """ apiVersion: v1 kind: Pod spec: nodeSelector: kubernetes.io/arch: arm64 containers: - name: builder image: quay.io/podman/stable:v5.2 tty: true command: ["cat"] securityContext: privileged: true env: - name: DOCKER_CONFIG value: /root/.docker - name: REGISTRY_AUTH_FILE value: /root/.docker/config.json - name: XDG_RUNTIME_DIR value: /var/run/containers volumeMounts: - name: workspace-volume mountPath: /home/jenkins/agent - name: docker-config-secret mountPath: /docker-config - name: containers-storage mountPath: /var/lib/containers - name: podman-runtime mountPath: /var/run/containers volumes: - name: docker-config-secret secret: secretName: harbor-robot-pipeline items: - key: .dockerconfigjson path: config.json - name: workspace-volume emptyDir: {} - name: containers-storage emptyDir: {} - name: podman-runtime emptyDir: {} """ } } environment { IMAGE_NAMESPACE = 'registry.bstein.dev/infra' TAG_SUFFIX = '-arm64' REGISTRY_URL = 'registry.bstein.dev' } options { disableConcurrentBuilds() timestamps() } stages { stage('Checkout pipeline repo') { steps { git credentialsId: 'gitea-pat', url: 'https://scm.bstein.dev/bstein/harbor-arm-build.git' } } stage('Setup tooling') { steps { container('builder') { sh ''' set -euo pipefail microdnf -y install git make curl tar gzip jq golang podman-docker python3 mkdir -p "${DOCKER_CONFIG}" cp /docker-config/config.json "${DOCKER_CONFIG}/config.json" # Make the Docker CLI invoke podman (buildah backend). ln -sf /usr/bin/podman /usr/local/bin/docker mkdir -p "${XDG_RUNTIME_DIR}" ''' } } } stage('Resolve version') { steps { container('builder') { script { def resolved = sh( label: 'pick version', returnStdout: true, script: ''' set -euo pipefail if [ -n "${HARBOR_VERSION:-}" ]; then echo "${HARBOR_VERSION}" exit 0 fi curl -sSL https://api.github.com/repos/goharbor/harbor/releases/latest | python3 - <<'PY' import json, sys data = json.load(sys.stdin) print(data.get("tag_name", "").strip()) PY ''' ).trim() env.HARBOR_VERSION_RESOLVED = resolved env.HARBOR_SRC_DIR = "harbor-src/harbor-${resolved.startsWith('v') ? resolved.substring(1) : resolved}" } } } } stage('Fetch source') { steps { container('builder') { sh """ set -euo pipefail rm -rf harbor-src mkdir -p harbor-src curl -sSL "https://github.com/goharbor/harbor/archive/refs/tags/${env.HARBOR_VERSION_RESOLVED}.tar.gz" | tar xz -C harbor-src ls -la harbor-src """ } } } stage('Build & push (podman/buildah)') { steps { container('builder') { sh """ set -euo pipefail export VERSIONTAG=\"${env.HARBOR_VERSION_RESOLVED}${TAG_SUFFIX}.${BUILD_NUMBER}\" export BASEIMAGETAG=\"${env.HARBOR_VERSION_RESOLVED}${TAG_SUFFIX}.${BUILD_NUMBER}\" export IMAGENAMESPACE=\"${IMAGE_NAMESPACE}\" export BASEIMAGENAMESPACE=\"${IMAGE_NAMESPACE}\" export DOCKERNETWORK=host export PULL_BASE_FROM_DOCKERHUB=false export BUILD_BASE=true export BUILDTRIVYADP=false export BUILD_INSTALLER=true export BUILDAH_ISOLATION=chroot export REGISTRY_AUTH_FILE=\"${DOCKER_CONFIG}/config.json\" git config --global --add safe.directory '*' cd \"${env.HARBOR_SRC_DIR}\" make compile make \\ VERSIONTAG=\"${env.HARBOR_VERSION_RESOLVED}${TAG_SUFFIX}.${BUILD_NUMBER}\" \\ BASEIMAGETAG=\"${env.HARBOR_VERSION_RESOLVED}${TAG_SUFFIX}.${BUILD_NUMBER}\" \\ IMAGENAMESPACE=\"${IMAGE_NAMESPACE}\" \\ BASEIMAGENAMESPACE=\"${IMAGE_NAMESPACE}\" \\ DOCKERNETWORK=host \\ PULL_BASE_FROM_DOCKERHUB=false \\ BUILD_BASE=true \\ BUILDTRIVYADP=false \\ BUILD_INSTALLER=true \\ build for pair in \\ \"prepare:harbor-prepare\" \\ \"redis-photon:harbor-redis\" \\ \"nginx-photon:harbor-nginx\" \\ \"registry-photon:harbor-registry\"; do src=\"${IMAGE_NAMESPACE}/\\$(echo \"$pair\" | cut -d: -f1):${env.HARBOR_VERSION_RESOLVED}${TAG_SUFFIX}.${BUILD_NUMBER}\" dst=\"${IMAGE_NAMESPACE}/\\$(echo \"$pair\" | cut -d: -f2):${env.HARBOR_VERSION_RESOLVED}${TAG_SUFFIX}.${BUILD_NUMBER}\" if podman image exists \"$src\"; then podman tag \"$src\" \"$dst\" || true fi done podman images --format '{{.Repository}}:{{.Tag}}' \\ | awk -v ns=\"${IMAGE_NAMESPACE}/\" -v tag=\"${env.HARBOR_VERSION_RESOLVED}${TAG_SUFFIX}.${BUILD_NUMBER}\" 'index($0, ns)==1 && $0 ~ ":"tag"$"' \\ | sort -u \\ | while read -r img; do echo \"Pushing ${img}\" podman push \"${img}\" done """ } } } } post { always { echo "done" } } }