189 lines
8.1 KiB
Groovy
189 lines
8.1 KiB
Groovy
// 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"
|
||
}
|
||
}
|
||
}
|