blob: 10953dbc694ca027bc3b7bb7ce393c246540abbf (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
pipeline {
agent any
environment {
REGISTRY = 'registry.example.com/docker-images'
}
stages {
stage('Detect changed images') {
steps {
script {
def base = env.CHANGE_TARGET ? "origin/${env.CHANGE_TARGET}" : "HEAD~1"
// returnStdout gives a String. Trim, split, and FORCE to a List.
def diffOutput = sh(
script: "git diff --name-only ${base} HEAD || true",
returnStdout: true
).trim()
// 'as List' avoids the non-serializable String[] array
def changedFiles = diffOutput ? (diffOutput.split('\n') as List) : []
// Build a plain List of unique top-level dirs (Strings only)
def candidates = []
for (String f : changedFiles) {
def top = f.split('/')[0]
if (top && !candidates.contains(top)) {
candidates.add(top)
}
}
// fileExists is a pipeline STEP, so it must stay in CPS land
// (i.e. a normal for-loop, NOT inside @NonCPS or a findAll closure)
def toBuild = []
for (String dir : candidates) {
if (fileExists("${dir}/Dockerfile")) {
toBuild.add(dir)
}
}
// Store only a plain String in env
env.IMAGES_TO_BUILD = toBuild.join(',')
echo "Images to build: ${env.IMAGES_TO_BUILD ?: '(none)'}"
}
}
}
stage('Build & push') {
when { expression { env.IMAGES_TO_BUILD } }
steps {
script {
def shortSha = env.GIT_COMMIT.take(8)
env.IMAGES_TO_BUILD.split(',').each { img ->
def tag = "${REGISTRY}/${img}"
sh """
docker build --tls=false\
--label org.opencontainers.image.source=${env.GIT_URL} \
--label org.opencontainers.image.revision=${env.GIT_COMMIT} \
-t ${tag}:${shortSha} \
${img}/
"""
if (env.BRANCH_NAME == 'main') {
sh """
docker tag --tls=false ${tag}:${shortSha} ${tag}:latest
docker push --tls=false ${tag}:${shortSha}
docker push --tls=false ${tag}:latest
"""
}
}
}
}
}
}
}
|