Files
wrapped/Jenkinsfile
T
Sergey Antropoff a4b750afef
devops-tools/wrapped/wrapped-build/pipeline/head This commit looks good
devops-tools/wrapped/wrapped-deploy/pipeline/head This commit looks good
Убраны short-sha теги образа: в Hub/Harbor публикуются только SemVer и latest.
2026-07-29 13:41:17 +03:00

189 lines
8.1 KiB
Groovy
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Wrapped — CI: multi-arch push (Harbor + Docker Hub), затем асинхронный Deploy
//
// Ресурсы k3s: Builder и Deploy не должны держать два DinD-пода сразу.
// 1) стадии сборки на agent label 'docker' (DinD)
// 2) при успехе — trigger Deploy с wait:false и agent none → Builder-под умирает
// 3) Deploy стартует отдельно уже без Builder
//
// Версия образа = VERSION из коммита. Bump: make bump-patch / make push.
//
// Credentials (Global):
// harbor-devops-tools-push-pull-access — Harbor devops-tools (robot)
// docker-hub — Docker Hub (inecs)
// ssh-gitea-key — SCM checkout Gitea
// gitea-jenkins-token — Gitea PAT; для статусов коммита: write:repository
// k3s-kubeconfig — в job Deploy (Jenkinsfile.deploy)
//
// Deploy job: devops-tools/wrapped/wrapped-deploy/main
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/wrapped'
DOCKERHUB_IMAGE = 'inecs/wrapped'
BUILDX_BUILDER = "jenkins-wrapped-${env.BUILD_NUMBER}"
DEPLOY_JOB = 'devops-tools/wrapped/wrapped-deploy/main'
TZ = 'Europe/Moscow'
}
stages {
stage('Build image') {
when {
anyOf {
branch 'main'
branch 'master'
}
}
agent { label 'docker' }
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Version') {
steps {
script {
// Без git в DinD-контейнере: dubious ownership → exit 128
env.IMAGE_VERSION = readFile('VERSION').trim()
if (!env.IMAGE_VERSION) {
error('VERSION file is empty')
}
echo "IMAGE_VERSION from VERSION → ${env.IMAGE_VERSION}"
}
}
}
stage('Build & 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 (no short-sha)"
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
# Arch-слои только в Harbor (промежуточные теги), не в Docker Hub
docker buildx build \
--platform linux/amd64 \
--provenance=false --sbom=false --push \
-t "${HARBOR_IMAGE}:${IMAGE_VERSION}-amd64" \
-f Dockerfile .
docker buildx build \
--platform linux/arm64 \
--provenance=false --sbom=false --push \
-t "${HARBOR_IMAGE}:${IMAGE_VERSION}-arm64" \
-f Dockerfile .
# Публичные теги: только SemVer + latest
for IMAGE in "$HARBOR_IMAGE" "$DOCKERHUB_IMAGE"; do
docker buildx imagetools create \
-t "${IMAGE}:${IMAGE_VERSION}" \
-t "${IMAGE}:latest" \
"${HARBOR_IMAGE}:${IMAGE_VERSION}-amd64" \
"${HARBOR_IMAGE}:${IMAGE_VERSION}-arm64"
done
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
'''
}
}
}
}
}
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 "✓ Build OK: ${DOCKERHUB_IMAGE}:{${IMAGE_VERSION},latest}"
}
failure {
echo "✗ Build/push не удались — Deploy не запускается"
}
}
}
// Без DinD: только очередь Deploy, Builder-под уже освобождён
stage('Trigger deploy') {
when {
anyOf {
branch 'main'
branch 'master'
}
}
agent none
steps {
script {
echo "Build finished — triggering ${DEPLOY_JOB} → ${DOCKERHUB_IMAGE}:${IMAGE_VERSION} (wait: false)"
build(
job: env.DEPLOY_JOB,
wait: false,
propagate: false,
parameters: [
string(name: 'IMAGE_REPOSITORY', value: env.DOCKERHUB_IMAGE),
string(name: 'IMAGE_TAG', value: env.IMAGE_VERSION),
string(name: 'IMAGE_PULL_POLICY', value: 'Always'),
]
)
echo "Deploy queued; Builder pipeline exits and releases cluster resources."
}
}
}
}
post {
success {
echo "✓ Version: ${IMAGE_VERSION}"
echo "✓ Image: ${DOCKERHUB_IMAGE}:{${IMAGE_VERSION},latest}"
echo "✓ Deploy: ${DEPLOY_JOB} triggered (async)"
}
failure {
echo "✗ Сборка не удалась — см. лог Build image"
}
}
}