pipeline { agent { kubernetes { label 'ariadne' defaultContainer 'builder' yaml """ apiVersion: v1 kind: Pod metadata: labels: app: ariadne spec: nodeSelector: kubernetes.io/arch: arm64 node-role.kubernetes.io/worker: "true" containers: - name: dind image: docker:27-dind securityContext: privileged: true env: - name: DOCKER_TLS_CERTDIR value: "" args: - --mtu=1400 - --host=unix:///var/run/docker.sock - --host=tcp://0.0.0.0:2375 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: harbor-config mountPath: /docker-config - name: tester image: python:3.12-slim command: ["cat"] tty: true volumeMounts: - name: workspace-volume mountPath: /home/jenkins/agent volumes: - name: workspace-volume emptyDir: {} - name: docker-config-writable emptyDir: {} - name: dind-storage emptyDir: {} - name: harbor-config secret: secretName: harbor-bstein-robot items: - key: .dockerconfigjson path: config.json """ } } environment { REGISTRY = 'registry.bstein.dev/bstein' IMAGE = "${REGISTRY}/ariadne" VERSION_TAG = 'dev' SEMVER = 'dev' COVERAGE_MIN = '99' COVERAGE_JSON = 'build/coverage.json' JUNIT_XML = 'build/junit.xml' METRICS_PREFIX = 'ariadne_ci' VM_IMPORT_URL = 'http://victoria-metrics-single-server.monitoring.svc.cluster.local:8428/api/v1/import/prometheus' REPO_NAME = 'ariadne' } options { disableConcurrentBuilds() } triggers { pollSCM('H/2 * * * *') } stages { stage('Checkout') { steps { checkout scm } } stage('Unit tests') { steps { container('tester') { sh ''' set -euo pipefail python -m pip install --no-cache-dir -r requirements.txt -r requirements-dev.txt mkdir -p build python -m ruff check ariadne --select C90,PLR python -m slipcover \ --json \ --out "${COVERAGE_JSON}" \ --source ariadne \ --fail-under "${COVERAGE_MIN}" \ -m pytest -ra -vv --durations=20 --junitxml "${JUNIT_XML}" python - <<'PY' import json with open("build/coverage.json", "r", encoding="utf-8") as handle: payload = json.load(handle) summary = payload.get("summary") or {} percent = summary.get("percent_covered") print(f"Coverage summary: {percent:.2f}%" if percent is not None else "Coverage summary unavailable") PY ''' } } } stage('Publish test metrics') { steps { container('tester') { sh ''' set -euo pipefail python scripts/publish_test_metrics.py ''' } } } stage('Prep toolchain') { steps { container('builder') { sh ''' set -euo pipefail apk add --no-cache bash git jq mkdir -p /root/.docker cp /docker-config/config.json /root/.docker/config.json ''' } } } stage('Compute version') { steps { container('builder') { script { sh ''' set -euo pipefail if git describe --tags --exact-match >/dev/null 2>&1; then SEMVER="$(git describe --tags --exact-match)" else SEMVER="0.1.0-${BUILD_NUMBER}" fi if ! echo "$SEMVER" | grep -Eq '^v?[0-9]+[.][0-9]+[.][0-9]+([-.][0-9A-Za-z]+)?$'; then SEMVER="0.1.0-${BUILD_NUMBER}" fi echo "SEMVER=${SEMVER}" > build.env ''' def props = readProperties file: 'build.env' env.SEMVER = props['SEMVER'] ?: "0.1.0-${env.BUILD_NUMBER}" env.VERSION_TAG = env.SEMVER } } } } stage('Buildx setup') { steps { container('builder') { sh ''' set -euo pipefail for i in $(seq 1 10); do if docker info >/dev/null 2>&1; then break fi sleep 2 done docker buildx create --name bstein-builder --driver docker-container --bootstrap --use || docker buildx use bstein-builder ''' } } } stage('Build & push image') { steps { container('builder') { sh ''' set -euo pipefail VERSION_TAG="$(cut -d= -f2 build.env)" docker buildx build \ --platform linux/arm64 \ --tag "${IMAGE}:${VERSION_TAG}" \ --tag "${IMAGE}:latest" \ --push \ . ''' } } } } post { always { junit allowEmptyResults: true, testResults: 'build/junit.xml' archiveArtifacts artifacts: 'build/junit.xml,build/coverage.json', allowEmptyArchive: true, fingerprint: true script { def props = fileExists('build.env') ? readProperties(file: 'build.env') : [:] echo "Build complete for ${props['SEMVER'] ?: env.VERSION_TAG}" } } } }