1b55b3b888
Jenkins docker agents run sh without array syntax; set simulator/migrate images with POSIX conditionals.
206 lines
9.4 KiB
Groovy
206 lines
9.4 KiB
Groovy
// oVirt API Simulator — CI/CD: multi-arch push (Harbor + Docker Hub) + deploy
|
|
//
|
|
// Один файл: Build (DinD) → Deploy (kubectl set image в релиз simulators).
|
|
// Первый install lab — через DevOpsTools/K3S: make addon-simulators
|
|
// (Ingress https://ovirt.devops.org.ru уже из addon values).
|
|
//
|
|
// Версия образа = VERSION из коммита. Локальный bump: make bump-patch / make push.
|
|
// Теги: :{VERSION} и :latest (без sha).
|
|
//
|
|
// Credentials (Global):
|
|
// harbor-devops-tools-push-pull-access — Harbor devops-tools (robot)
|
|
// docker-hub — Docker Hub (inecs)
|
|
// k3s-kubeconfig — kubeconfig к K3S
|
|
// ssh-gitea-key — SCM checkout Gitea (в job)
|
|
|
|
pipeline {
|
|
agent none
|
|
|
|
options {
|
|
buildDiscarder(logRotator(numToKeepStr: '20'))
|
|
disableConcurrentBuilds()
|
|
timeout(time: 60, unit: 'MINUTES')
|
|
timestamps()
|
|
}
|
|
|
|
environment {
|
|
HARBOR_REGISTRY = 'hub.antropoff.ru'
|
|
HARBOR_IMAGE = 'hub.antropoff.ru/devops-tools/ovirt-api-simulator'
|
|
DOCKERHUB_IMAGE = 'inecs/ovirt-api-simulator'
|
|
BUILDX_BUILDER = "jenkins-ovirt-api-simulator-${env.BUILD_NUMBER}"
|
|
HELM_NAMESPACE = 'simulators'
|
|
DEPLOYMENT_NAME = 'simulators-ovirt'
|
|
INGRESS_HOST = 'ovirt.devops.org.ru'
|
|
TZ = 'Europe/Moscow'
|
|
}
|
|
|
|
stages {
|
|
stage('Build & push') {
|
|
when {
|
|
anyOf {
|
|
branch 'main'
|
|
branch 'master'
|
|
}
|
|
}
|
|
agent { label 'docker' }
|
|
stages {
|
|
stage('Checkout') {
|
|
steps {
|
|
checkout scm
|
|
}
|
|
}
|
|
|
|
stage('Version') {
|
|
steps {
|
|
script {
|
|
env.IMAGE_VERSION = readFile('VERSION').trim()
|
|
if (!env.IMAGE_VERSION) {
|
|
error('VERSION file is empty')
|
|
}
|
|
echo "IMAGE_VERSION from VERSION → ${env.IMAGE_VERSION}"
|
|
}
|
|
}
|
|
}
|
|
|
|
stage('Buildx push') {
|
|
steps {
|
|
withCredentials([
|
|
usernamePassword(
|
|
credentialsId: 'harbor-devops-tools-push-pull-access',
|
|
usernameVariable: 'HARBOR_USER',
|
|
passwordVariable: 'HARBOR_PASS'
|
|
),
|
|
usernamePassword(
|
|
credentialsId: 'docker-hub',
|
|
usernameVariable: 'DOCKERHUB_USER',
|
|
passwordVariable: 'DOCKERHUB_PASS'
|
|
)
|
|
]) {
|
|
container('docker') {
|
|
sh '''
|
|
set -eux
|
|
|
|
test -n "${IMAGE_VERSION}"
|
|
echo "Building tags: ${IMAGE_VERSION}, latest (amd64+arm64)"
|
|
|
|
echo "$HARBOR_PASS" | docker login "$HARBOR_REGISTRY" -u "$HARBOR_USER" --password-stdin
|
|
echo "$DOCKERHUB_PASS" | docker login -u "$DOCKERHUB_USER" --password-stdin
|
|
|
|
docker buildx rm "$BUILDX_BUILDER" 2>/dev/null || true
|
|
docker buildx create --name "$BUILDX_BUILDER" --driver docker-container --use
|
|
docker buildx inspect --bootstrap >/dev/null
|
|
|
|
docker buildx build \
|
|
--platform linux/amd64,linux/arm64 \
|
|
--target runtime \
|
|
--build-arg "APP_VERSION=${IMAGE_VERSION}" \
|
|
--provenance=false --sbom=false --push \
|
|
-t "${HARBOR_IMAGE}:${IMAGE_VERSION}" \
|
|
-t "${HARBOR_IMAGE}:latest" \
|
|
-t "${DOCKERHUB_IMAGE}:${IMAGE_VERSION}" \
|
|
-t "${DOCKERHUB_IMAGE}:latest" \
|
|
-f Dockerfile .
|
|
|
|
echo "--- Harbor ---"
|
|
docker buildx imagetools inspect "${HARBOR_IMAGE}:${IMAGE_VERSION}" | sed -n '1,40p'
|
|
echo "--- Docker Hub ---"
|
|
docker buildx imagetools inspect "${DOCKERHUB_IMAGE}:${IMAGE_VERSION}" | sed -n '1,40p'
|
|
|
|
docker buildx rm "$BUILDX_BUILDER" || true
|
|
'''
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
stage('Deploy') {
|
|
steps {
|
|
withCredentials([
|
|
file(credentialsId: 'k3s-kubeconfig', variable: 'KUBECONFIG')
|
|
]) {
|
|
container('docker') {
|
|
sh '''
|
|
set -eux
|
|
|
|
if ! command -v kubectl >/dev/null 2>&1; then
|
|
apk add --no-cache curl >/dev/null
|
|
ARCH="$(uname -m)"
|
|
case "$ARCH" in
|
|
x86_64) ARCH=amd64 ;;
|
|
aarch64|arm64) ARCH=arm64 ;;
|
|
esac
|
|
KVER="$(curl -fsSL https://dl.k8s.io/release/stable.txt)"
|
|
curl -fsSLo /usr/local/bin/kubectl \
|
|
"https://dl.k8s.io/release/${KVER}/bin/linux/${ARCH}/kubectl"
|
|
chmod +x /usr/local/bin/kubectl
|
|
fi
|
|
|
|
kubectl version --client || true
|
|
|
|
if ! kubectl -n "$HELM_NAMESPACE" get deploy "$DEPLOYMENT_NAME" >/dev/null 2>&1; then
|
|
echo "Deployment ${HELM_NAMESPACE}/${DEPLOYMENT_NAME} not found." >&2
|
|
echo "Сначала: make addon-simulators (Ingress ${INGRESS_HOST})." >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "Rolling ${DOCKERHUB_IMAGE}:${IMAGE_VERSION} → ${HELM_NAMESPACE}/${DEPLOYMENT_NAME}"
|
|
echo "Public URL: https://${INGRESS_HOST}/"
|
|
|
|
# POSIX sh (Alpine ash): no bash arrays. One set-image when migrate exists.
|
|
INITS="$(kubectl -n "$HELM_NAMESPACE" get deploy "$DEPLOYMENT_NAME" \
|
|
-o jsonpath='{.spec.template.spec.initContainers[*].name}' || true)"
|
|
if printf '%s\n' $INITS | grep -qx migrate; then
|
|
kubectl -n "$HELM_NAMESPACE" set image \
|
|
"deployment/${DEPLOYMENT_NAME}" \
|
|
"simulator=${DOCKERHUB_IMAGE}:${IMAGE_VERSION}" \
|
|
"migrate=${DOCKERHUB_IMAGE}:${IMAGE_VERSION}"
|
|
else
|
|
kubectl -n "$HELM_NAMESPACE" set image \
|
|
"deployment/${DEPLOYMENT_NAME}" \
|
|
"simulator=${DOCKERHUB_IMAGE}:${IMAGE_VERSION}"
|
|
fi
|
|
|
|
kubectl -n "$HELM_NAMESPACE" rollout status \
|
|
"deployment/${DEPLOYMENT_NAME}" --timeout=1200s
|
|
kubectl -n "$HELM_NAMESPACE" get deploy,po,ing -o wide
|
|
'''
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
try {
|
|
container('docker') {
|
|
sh 'docker buildx rm "$BUILDX_BUILDER" 2>/dev/null || true'
|
|
}
|
|
} catch (Ignored) {
|
|
// pod may already be gone
|
|
}
|
|
}
|
|
}
|
|
success {
|
|
echo "✓ ${DOCKERHUB_IMAGE}:{${IMAGE_VERSION},latest} → https://${INGRESS_HOST}/"
|
|
}
|
|
failure {
|
|
echo "✗ Build/push/deploy failed — см. лог"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
post {
|
|
success {
|
|
echo "✓ Version: ${IMAGE_VERSION}"
|
|
echo "✓ Harbor: ${HARBOR_IMAGE}:{${IMAGE_VERSION},latest}"
|
|
echo "✓ Hub: ${DOCKERHUB_IMAGE}:{${IMAGE_VERSION},latest}"
|
|
echo "✓ Live: https://${INGRESS_HOST}/"
|
|
}
|
|
failure {
|
|
echo "✗ Pipeline failed"
|
|
}
|
|
}
|
|
}
|