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() } 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 VERSION_TAG="${HARBOR_VERSION_RESOLVED}${TAG_SUFFIX}.${BUILD_NUMBER}" export VERSIONTAG="${VERSION_TAG}" export BASEIMAGETAG="${VERSION_TAG}" 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 "${HARBOR_SRC_DIR}" make compile make \ VERSIONTAG="${VERSION_TAG}" \ BASEIMAGETAG="${VERSION_TAG}" \ 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 pair_src="${pair%%:*}" pair_dst="${pair##*:}" src="${IMAGE_NAMESPACE}/${pair_src}:${VERSION_TAG}" dst="${IMAGE_NAMESPACE}/${pair_dst}:${VERSION_TAG}" 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="${VERSION_TAG}" 'index($0, ns)==1 && $0 ~ ":"tag"$"' \ | sort -u \ | while read -r img; do echo "Pushing ${img}" podman push "${img}" done ''' } } } } post { always { echo "done" } } }