2025-01-17 08:25:04 +00:00
|
|
|
#!groovy
|
|
|
|
|
|
|
|
|
|
import com.freeleaps.devops.SourceFetcher
|
2025-01-21 09:01:31 +00:00
|
|
|
import com.freeleaps.devops.DependenciesResolver
|
2025-02-04 02:23:25 +00:00
|
|
|
import com.freeleaps.devops.CommitMessageLinter
|
|
|
|
|
import com.freeleaps.devops.ChangedComponentsDetector
|
2025-02-05 08:29:52 +00:00
|
|
|
import com.freeleaps.devops.CodeLintExecutor
|
2025-02-07 07:18:40 +00:00
|
|
|
import com.freeleaps.devops.SASTExecutor
|
|
|
|
|
import com.freeleaps.devops.ImageBuilder
|
2025-02-07 07:22:40 +00:00
|
|
|
import com.freeleaps.devops.SemanticReleasingExecutor
|
2025-02-17 10:45:22 +00:00
|
|
|
import com.freeleaps.devops.ArgoApplicationVersionUpdater
|
2025-02-05 08:29:52 +00:00
|
|
|
|
|
|
|
|
import com.freeleaps.devops.enums.DependenciesManager
|
|
|
|
|
import com.freeleaps.devops.enums.ServiceLanguage
|
|
|
|
|
import com.freeleaps.devops.enums.CodeLinterTypes
|
2025-02-07 07:18:40 +00:00
|
|
|
import com.freeleaps.devops.enums.ImageBuilderTypes
|
2025-02-22 11:14:36 +00:00
|
|
|
import org.csanchez.jenkins.plugins.kubernetes.pod.yaml.YamlMergeStrategy
|
|
|
|
|
import org.csanchez.jenkins.plugins.kubernetes.pod.yaml.Merge
|
|
|
|
|
|
2025-01-17 08:25:04 +00:00
|
|
|
|
2025-02-04 06:59:41 +00:00
|
|
|
def generateComponentStages(component, configurations) {
|
2025-02-07 07:57:10 +00:00
|
|
|
def stages = []
|
|
|
|
|
stages.addAll([
|
|
|
|
|
// Build Agent Setup
|
2025-02-09 23:03:47 +00:00
|
|
|
{stage("${component.name} :: Build Agent Setup") {
|
2025-02-07 07:57:10 +00:00
|
|
|
script {
|
2025-02-22 12:33:26 +00:00
|
|
|
if (env.executeMode == "fully" || env.changedComponents.split(/\s+/).toList().contains(component.name)) {
|
2025-02-07 07:57:10 +00:00
|
|
|
def buildAgentImage = component.buildAgentImage
|
|
|
|
|
if (buildAgentImage == null || buildAgentImage.isEmpty()) {
|
|
|
|
|
log.warn("Pipeline", "Not set buildAgentImage for ${component.name}, using default build agent image")
|
|
|
|
|
|
|
|
|
|
def language = ServiceLanguage.parse(component.language)
|
|
|
|
|
switch(language) {
|
|
|
|
|
case ServiceLanguage.PYTHON:
|
|
|
|
|
buildAgentImage = "docker.io/python:3.10-slim-buster"
|
|
|
|
|
break
|
|
|
|
|
case ServiceLanguage.JS:
|
|
|
|
|
buildAgentImage = "docker.io/node:lts-alpine"
|
|
|
|
|
break
|
|
|
|
|
default:
|
|
|
|
|
error("Unknown service language")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
log.info("Pipeline", "Using ${buildAgentImage} as build agent image for ${component.name}")
|
2025-02-09 23:17:11 +00:00
|
|
|
env."${component.name}_buildAgentImage" = buildAgentImage
|
2025-02-07 07:57:10 +00:00
|
|
|
}
|
|
|
|
|
}
|
2025-02-09 23:03:47 +00:00
|
|
|
}},
|
2025-02-07 07:57:10 +00:00
|
|
|
// Dependencies Resolving
|
2025-02-09 23:03:47 +00:00
|
|
|
{stage("${component.name} :: Dependencies Resolving") {
|
2025-02-04 06:59:41 +00:00
|
|
|
podTemplate(
|
|
|
|
|
label: "dep-resolver-${component.name}",
|
2025-02-20 09:28:45 +00:00
|
|
|
yaml: """
|
|
|
|
|
apiVersion: v1
|
|
|
|
|
kind: Pod
|
|
|
|
|
spec:
|
|
|
|
|
affinity:
|
|
|
|
|
nodeAffinity:
|
|
|
|
|
requiredDuringSchedulingIgnoredDuringExecution:
|
|
|
|
|
nodeSelectorTerms:
|
|
|
|
|
- matchExpressions:
|
|
|
|
|
- key: "node-role.kubernetes.io/devops"
|
|
|
|
|
operator: In
|
|
|
|
|
values: ["true"]
|
|
|
|
|
tolerations:
|
|
|
|
|
- key: "node-role.kubernetes.io/devops"
|
|
|
|
|
operator: Equal
|
|
|
|
|
value: "true"
|
|
|
|
|
effect: "NoSchedule"
|
|
|
|
|
""",
|
2025-02-22 11:17:25 +00:00
|
|
|
yamlMergeStrategy: merge(),
|
2025-02-04 06:59:41 +00:00
|
|
|
containers: [
|
|
|
|
|
containerTemplate(
|
|
|
|
|
name: 'dep-resolver',
|
2025-02-09 23:17:11 +00:00
|
|
|
image: env."${component.name}_buildAgentImage",
|
2025-02-04 06:59:41 +00:00
|
|
|
ttyEnabled: true,
|
2025-02-04 07:47:02 +00:00
|
|
|
command: 'sleep',
|
|
|
|
|
args: 'infinity'
|
2025-02-04 06:59:41 +00:00
|
|
|
)
|
|
|
|
|
]
|
|
|
|
|
) {
|
|
|
|
|
node("dep-resolver-${component.name}") {
|
2025-02-04 07:49:33 +00:00
|
|
|
container('dep-resolver') {
|
|
|
|
|
script {
|
2025-02-22 12:33:26 +00:00
|
|
|
if (env.executeMode == "fully" || env.changedComponents.split(/\s+/).toList().contains(component.name)) {
|
2025-02-09 23:17:11 +00:00
|
|
|
def buildAgentImage = env."${component.name}_buildAgentImage"
|
|
|
|
|
log.info("Pipeline", "Using ${buildAgentImage} as build agent image for dependencies resolving")
|
2025-02-04 07:49:33 +00:00
|
|
|
def sourceFetcher = new SourceFetcher(this)
|
|
|
|
|
sourceFetcher.fetch(configurations)
|
2025-02-04 07:22:59 +00:00
|
|
|
|
2025-02-04 07:49:33 +00:00
|
|
|
def language = ServiceLanguage.parse(component.language)
|
|
|
|
|
def depManager = DependenciesManager.parse(component.dependenciesManager)
|
2025-02-04 07:22:59 +00:00
|
|
|
|
2025-02-07 07:18:40 +00:00
|
|
|
def dependenciesResolver = new DependenciesResolver(this, language, env.workroot + "/" + component.root + "/")
|
2025-02-04 07:49:33 +00:00
|
|
|
dependenciesResolver.useManager(depManager)
|
|
|
|
|
|
|
|
|
|
if (component.buildCacheEnabled) {
|
|
|
|
|
dependenciesResolver.enableCachingSupport()
|
|
|
|
|
} else {
|
|
|
|
|
dependenciesResolver.disableCachingSupport()
|
|
|
|
|
}
|
2025-02-04 07:25:40 +00:00
|
|
|
|
2025-02-04 07:49:33 +00:00
|
|
|
dependenciesResolver.resolve(component)
|
|
|
|
|
}
|
2025-02-04 06:38:58 +00:00
|
|
|
}
|
2025-02-04 06:59:41 +00:00
|
|
|
}
|
2025-02-04 06:50:08 +00:00
|
|
|
}
|
2025-02-04 06:59:41 +00:00
|
|
|
}
|
2025-02-09 23:03:47 +00:00
|
|
|
}},
|
2025-02-07 07:57:10 +00:00
|
|
|
])
|
2025-02-05 08:29:52 +00:00
|
|
|
|
2025-02-07 07:57:10 +00:00
|
|
|
if (component.lintEnabled != null && component.lintEnabled) {
|
|
|
|
|
stages.addAll([
|
|
|
|
|
// Code Linter Environment Preparation
|
2025-02-09 23:03:47 +00:00
|
|
|
{stage("${component.name} :: Code Linter Preparation") {
|
2025-02-07 07:57:10 +00:00
|
|
|
script {
|
2025-02-22 12:33:26 +00:00
|
|
|
if (env.executeMode == "fully" || env.changedComponents.split(/\s+/).toList().contains(component.name)) {
|
2025-02-07 07:57:10 +00:00
|
|
|
if (component.lintEnabled != null && component.lintEnabled) {
|
|
|
|
|
log.info("Pipeline", "Code linting has enabled, preparing linter...")
|
2025-02-05 08:29:52 +00:00
|
|
|
|
2025-02-07 07:57:10 +00:00
|
|
|
if (component.linter == null || component.linter.isEmpty()) {
|
|
|
|
|
log.error("Pipeline", "Not set linter for ${component.name}, using default linter settings as fallback")
|
|
|
|
|
}
|
2025-02-05 08:29:52 +00:00
|
|
|
|
2025-02-07 07:57:10 +00:00
|
|
|
def linter = CodeLinterTypes.parse(component.linter)
|
2025-02-05 08:29:52 +00:00
|
|
|
|
2025-02-07 07:57:10 +00:00
|
|
|
if (linter == null) {
|
|
|
|
|
log.error("Pipeline", "Unknown linter for ${component.name}, skipping code linting")
|
|
|
|
|
}
|
2025-02-05 08:29:52 +00:00
|
|
|
|
2025-02-07 07:57:10 +00:00
|
|
|
if (linter.language != ServiceLanguage.parse(component.language)) {
|
|
|
|
|
log.error("Pipeline", "Linter ${linter.linter} is not supported for ${component.language}, skipping code linting")
|
|
|
|
|
}
|
2025-02-05 08:29:52 +00:00
|
|
|
|
2025-02-07 07:57:10 +00:00
|
|
|
log.info("Pipeline", "Using ${linter.linter} with image ${linter.containerImage} as linter for ${component.name}")
|
2025-02-09 23:17:11 +00:00
|
|
|
env."${component.name}_linterContainerImage" = linter.containerImage
|
2025-02-07 07:57:10 +00:00
|
|
|
} else {
|
|
|
|
|
log.info("Pipeline", "Code linting is not enabled for ${component.name}, skipping...")
|
|
|
|
|
}
|
2025-02-05 08:29:52 +00:00
|
|
|
}
|
|
|
|
|
}
|
2025-02-09 23:03:47 +00:00
|
|
|
}},
|
2025-02-07 07:57:10 +00:00
|
|
|
// Code Linting
|
2025-02-09 23:03:47 +00:00
|
|
|
{stage("${component.name} :: Code Linting") {
|
2025-02-07 07:57:10 +00:00
|
|
|
podTemplate(
|
|
|
|
|
label: "code-linter-${component.name}",
|
2025-02-20 09:28:45 +00:00
|
|
|
yaml: """
|
|
|
|
|
apiVersion: v1
|
|
|
|
|
kind: Pod
|
|
|
|
|
spec:
|
|
|
|
|
affinity:
|
|
|
|
|
nodeAffinity:
|
|
|
|
|
requiredDuringSchedulingIgnoredDuringExecution:
|
|
|
|
|
nodeSelectorTerms:
|
|
|
|
|
- matchExpressions:
|
|
|
|
|
- key: "node-role.kubernetes.io/devops"
|
|
|
|
|
operator: In
|
|
|
|
|
values: ["true"]
|
|
|
|
|
tolerations:
|
|
|
|
|
- key: "node-role.kubernetes.io/devops"
|
|
|
|
|
operator: Equal
|
|
|
|
|
value: "true"
|
|
|
|
|
effect: "NoSchedule"
|
|
|
|
|
""",
|
2025-02-22 11:17:25 +00:00
|
|
|
yamlMergeStrategy: merge(),
|
2025-02-07 07:57:10 +00:00
|
|
|
containers: [
|
|
|
|
|
containerTemplate(
|
|
|
|
|
name: 'code-linter',
|
2025-02-09 23:17:11 +00:00
|
|
|
image: env."${component.name}_linterContainerImage",
|
2025-02-07 07:57:10 +00:00
|
|
|
ttyEnabled: true,
|
|
|
|
|
command: 'sleep',
|
|
|
|
|
args: 'infinity'
|
|
|
|
|
)
|
|
|
|
|
]
|
|
|
|
|
) {
|
|
|
|
|
node("code-linter-${component.name}") {
|
|
|
|
|
container('code-linter') {
|
|
|
|
|
script {
|
2025-02-22 12:33:26 +00:00
|
|
|
if (env.executeMode == "fully" || env.changedComponents.split(/\s+/).toList().contains(component.name)) {
|
2025-02-07 07:57:10 +00:00
|
|
|
if (component.lintEnabled != null && component.lintEnabled) {
|
|
|
|
|
log.info("Pipeline", "Code linting has enabled, linting code...")
|
|
|
|
|
|
|
|
|
|
def sourceFetcher = new SourceFetcher(this)
|
|
|
|
|
sourceFetcher.fetch(configurations)
|
|
|
|
|
|
|
|
|
|
def linterType = CodeLinterTypes.parse(component.linter)
|
2025-02-07 09:42:01 +00:00
|
|
|
def language = ServiceLanguage.parse(component.language)
|
2025-02-07 07:57:10 +00:00
|
|
|
|
2025-02-07 09:42:01 +00:00
|
|
|
def depManager = DependenciesManager.parse(component.dependenciesManager)
|
|
|
|
|
|
|
|
|
|
// resolving deps from cache
|
|
|
|
|
def dependenciesResolver = new DependenciesResolver(this, language, env.workroot + "/" + component.root + "/")
|
|
|
|
|
dependenciesResolver.useManager(depManager)
|
|
|
|
|
|
|
|
|
|
if (component.buildCacheEnabled) {
|
|
|
|
|
dependenciesResolver.enableCachingSupport()
|
|
|
|
|
} else {
|
|
|
|
|
dependenciesResolver.disableCachingSupport()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dependenciesResolver.resolve(component)
|
|
|
|
|
|
|
|
|
|
// lint codes
|
2025-02-07 09:31:27 +00:00
|
|
|
def codeLintExecutor = new CodeLintExecutor(this, env.workroot + "/" + component.root + "/", component.linterConfig, linterType, component)
|
2025-02-07 07:57:10 +00:00
|
|
|
codeLintExecutor.execute()
|
|
|
|
|
}
|
2025-02-05 08:29:52 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-02-09 23:03:47 +00:00
|
|
|
}}
|
2025-02-07 07:57:10 +00:00
|
|
|
])
|
|
|
|
|
}
|
2025-02-05 08:29:52 +00:00
|
|
|
|
2025-02-07 07:57:10 +00:00
|
|
|
if (component.sastEnabled != null && component.sastEnabled) {
|
|
|
|
|
stages.addAll([
|
|
|
|
|
// SAST Scanner Environment Preparation
|
2025-02-09 23:03:47 +00:00
|
|
|
{stage("${component.name} :: SAST Scanner Preparation") {
|
2025-02-07 07:57:10 +00:00
|
|
|
script {
|
2025-02-22 12:33:26 +00:00
|
|
|
if (env.executeMode == "fully" || env.changedComponents.split(/\s+/).toList().contains(component.name)) {
|
2025-02-07 07:57:10 +00:00
|
|
|
if (component.sastEnabled != null && component.sastEnabled) {
|
|
|
|
|
log.info("Pipeline", "SAST scanning has enabled, preparing scanner...")
|
2025-02-05 08:29:52 +00:00
|
|
|
|
2025-02-07 07:57:10 +00:00
|
|
|
if (sastScanner == null || sastScanner.isEmpty()) {
|
|
|
|
|
log.error("Pipeline", "Not set sastScanner for ${component.name}")
|
|
|
|
|
}
|
2025-02-05 08:29:52 +00:00
|
|
|
|
2025-02-07 07:57:10 +00:00
|
|
|
def sastScannerType = SASTScannerTypes.parse(component.sastScanner)
|
|
|
|
|
if (sastScannerType == null) {
|
|
|
|
|
log.error("Pipeline", "Unknown SAST scanner for ${component.name}, skipping SAST scanning")
|
|
|
|
|
} else if (sastScannerType.language != ServiceLanguage.parse(component.language)) {
|
|
|
|
|
log.error("Pipeline", "SAST scanner ${sastScannerType.scanner} is not supported for ${component.language}, skipping SAST scanning")
|
|
|
|
|
} else {
|
|
|
|
|
log.info("Pipeline", "Using ${sastScanner} as SAST scanner for ${component.name}")
|
2025-02-09 23:17:11 +00:00
|
|
|
env."${component.name}_sastScannerContainerImage" = sastScannerType.containerImage
|
2025-02-07 07:57:10 +00:00
|
|
|
}
|
2025-02-07 07:18:40 +00:00
|
|
|
}
|
2025-02-05 08:29:52 +00:00
|
|
|
}
|
|
|
|
|
}
|
2025-02-09 23:03:47 +00:00
|
|
|
}},
|
2025-02-07 07:57:10 +00:00
|
|
|
// SAST Scanning
|
2025-02-09 23:03:47 +00:00
|
|
|
{stage("${component.name} :: SAST Scanning") {
|
2025-02-07 07:57:10 +00:00
|
|
|
when {
|
|
|
|
|
expression {
|
2025-02-22 12:33:26 +00:00
|
|
|
return (env.executeMode == "fully" || env.changedComponents.split(/\s+/).toList().contains(component.name)) && env.sastScannerContainerImage != null && !env.sastScannerContainerImage.isEmpty()
|
2025-02-07 07:57:10 +00:00
|
|
|
}
|
2025-02-07 07:18:40 +00:00
|
|
|
}
|
2025-02-07 07:57:10 +00:00
|
|
|
podTemplate(
|
|
|
|
|
label: "sast-scanner-${component.name}",
|
2025-02-20 09:28:45 +00:00
|
|
|
yaml: """
|
|
|
|
|
apiVersion: v1
|
|
|
|
|
kind: Pod
|
|
|
|
|
spec:
|
|
|
|
|
affinity:
|
|
|
|
|
nodeAffinity:
|
|
|
|
|
requiredDuringSchedulingIgnoredDuringExecution:
|
|
|
|
|
nodeSelectorTerms:
|
|
|
|
|
- matchExpressions:
|
|
|
|
|
- key: "node-role.kubernetes.io/devops"
|
|
|
|
|
operator: In
|
|
|
|
|
values: ["true"]
|
|
|
|
|
tolerations:
|
|
|
|
|
- key: "node-role.kubernetes.io/devops"
|
|
|
|
|
operator: Equal
|
|
|
|
|
value: "true"
|
|
|
|
|
effect: "NoSchedule"
|
|
|
|
|
""",
|
2025-02-22 11:17:25 +00:00
|
|
|
yamlMergeStrategy: merge(),
|
2025-02-07 07:57:10 +00:00
|
|
|
containers: [
|
|
|
|
|
containerTemplate(
|
|
|
|
|
name: 'sast-scanner',
|
2025-02-09 23:17:11 +00:00
|
|
|
image: env."${component.name}_sastScannerContainerImage",
|
2025-02-07 07:57:10 +00:00
|
|
|
ttyEnabled: true,
|
|
|
|
|
command: 'sleep',
|
|
|
|
|
args: 'infinity'
|
|
|
|
|
)
|
|
|
|
|
]
|
|
|
|
|
) {
|
|
|
|
|
node("sast-scanner-${component.name}") {
|
|
|
|
|
container('sast-scanner') {
|
|
|
|
|
script {
|
2025-02-22 12:33:26 +00:00
|
|
|
if (env.executeMode == "fully" || env.changedComponents.split(/\s+/).toList().contains(component.name)) {
|
2025-02-07 07:57:10 +00:00
|
|
|
if (component.sastEnabled != null && component.sastEnabled) {
|
|
|
|
|
log.info("Pipeline", "SAST scanning has enabled, scanning code...")
|
|
|
|
|
|
|
|
|
|
def sourceFetcher = new SourceFetcher(this)
|
|
|
|
|
sourceFetcher.fetch(configurations)
|
|
|
|
|
|
|
|
|
|
def sastScannerType = SASTScannerTypes.parse(component.sastScanner)
|
|
|
|
|
|
|
|
|
|
def sastScanner = new SASTExecutor(this, env.workroot + "/" + component.root + "/", sastScannerType)
|
|
|
|
|
sastScanner.scan()
|
|
|
|
|
}
|
2025-02-07 07:18:40 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-02-09 23:03:47 +00:00
|
|
|
}}
|
2025-02-07 07:57:10 +00:00
|
|
|
])
|
|
|
|
|
}
|
2025-02-05 08:29:52 +00:00
|
|
|
|
2025-02-07 07:57:10 +00:00
|
|
|
if (component.semanticReleaseEnabled != null && component.semanticReleaseEnabled) {
|
|
|
|
|
stages.addAll([
|
|
|
|
|
// Semantic Releasing
|
2025-02-09 23:03:47 +00:00
|
|
|
{stage("${component.name} :: Semantic Releasing") {
|
2025-02-07 07:57:10 +00:00
|
|
|
podTemplate(
|
|
|
|
|
label: "semantic-releasing-${component.name}",
|
2025-02-20 09:28:45 +00:00
|
|
|
yaml: """
|
|
|
|
|
apiVersion: v1
|
|
|
|
|
kind: Pod
|
|
|
|
|
spec:
|
|
|
|
|
affinity:
|
|
|
|
|
nodeAffinity:
|
|
|
|
|
requiredDuringSchedulingIgnoredDuringExecution:
|
|
|
|
|
nodeSelectorTerms:
|
|
|
|
|
- matchExpressions:
|
|
|
|
|
- key: "node-role.kubernetes.io/devops"
|
|
|
|
|
operator: In
|
|
|
|
|
values: ["true"]
|
|
|
|
|
tolerations:
|
|
|
|
|
- key: "node-role.kubernetes.io/devops"
|
|
|
|
|
operator: Equal
|
|
|
|
|
value: "true"
|
|
|
|
|
effect: "NoSchedule"
|
|
|
|
|
""",
|
2025-02-22 11:17:25 +00:00
|
|
|
yamlMergeStrategy: merge(),
|
2025-02-07 07:57:10 +00:00
|
|
|
containers: [
|
|
|
|
|
containerTemplate(
|
|
|
|
|
name: 'semantic-releasing',
|
2025-02-07 10:26:19 +00:00
|
|
|
image: 'node:18-bullseye-slim',
|
2025-02-07 07:57:10 +00:00
|
|
|
ttyEnabled: true,
|
|
|
|
|
command: 'sleep',
|
|
|
|
|
args: 'infinity'
|
|
|
|
|
)
|
|
|
|
|
]
|
|
|
|
|
) {
|
|
|
|
|
node("semantic-releasing-${component.name}") {
|
|
|
|
|
container('semantic-releasing') {
|
|
|
|
|
script {
|
2025-02-22 12:33:26 +00:00
|
|
|
if (env.executeMode == "fully" || env.changedComponents.split(/\s+/).toList().contains(component.name)) {
|
2025-02-07 07:57:10 +00:00
|
|
|
if (component.semanticReleaseEnabled != null && component.semanticReleaseEnabled) {
|
|
|
|
|
log.info("Pipeline", "Semantic releasing has enabled, releasing...")
|
|
|
|
|
|
2025-02-09 23:35:11 +00:00
|
|
|
if (env.SEMANTIC_RELEASED != null && !env.SEMANTIC_RELEASED.isEmpty() && env.SEMANTIC_RELEASED) {
|
|
|
|
|
log.info("Pipeline", "Semantic release has been executed, skipping...")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-07 07:57:10 +00:00
|
|
|
def sourceFetcher = new SourceFetcher(this)
|
|
|
|
|
sourceFetcher.fetch(configurations)
|
|
|
|
|
|
2025-02-08 02:33:02 +00:00
|
|
|
def semanticReleasingExecutor = new SemanticReleasingExecutor(this, env.workroot)
|
2025-02-17 22:10:59 +00:00
|
|
|
semanticReleasingExecutor.release(configurations.serviceGitCredentialsId, configurations.serviceGitBranch)
|
2025-02-07 07:57:10 +00:00
|
|
|
}
|
2025-02-07 07:18:40 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-02-09 23:03:47 +00:00
|
|
|
}}
|
2025-02-07 07:57:10 +00:00
|
|
|
])
|
|
|
|
|
}
|
2025-02-05 08:29:52 +00:00
|
|
|
|
2025-02-07 07:57:10 +00:00
|
|
|
stages.addAll([
|
|
|
|
|
// Compilation & Packaging
|
2025-02-09 23:03:47 +00:00
|
|
|
{stage("${component.name} :: Compilation & Packaging") {
|
2025-02-07 07:18:40 +00:00
|
|
|
podTemplate(
|
|
|
|
|
label: "build-agent-${component.name}",
|
2025-02-20 09:28:45 +00:00
|
|
|
yaml: """
|
|
|
|
|
apiVersion: v1
|
|
|
|
|
kind: Pod
|
|
|
|
|
spec:
|
|
|
|
|
affinity:
|
|
|
|
|
nodeAffinity:
|
|
|
|
|
requiredDuringSchedulingIgnoredDuringExecution:
|
|
|
|
|
nodeSelectorTerms:
|
|
|
|
|
- matchExpressions:
|
|
|
|
|
- key: "node-role.kubernetes.io/devops"
|
|
|
|
|
operator: In
|
|
|
|
|
values: ["true"]
|
|
|
|
|
tolerations:
|
|
|
|
|
- key: "node-role.kubernetes.io/devops"
|
|
|
|
|
operator: Equal
|
|
|
|
|
value: "true"
|
|
|
|
|
effect: "NoSchedule"
|
|
|
|
|
""",
|
2025-02-22 11:17:25 +00:00
|
|
|
yamlMergeStrategy: merge(),
|
2025-02-07 07:18:40 +00:00
|
|
|
containers: [
|
|
|
|
|
containerTemplate(
|
|
|
|
|
name: 'build-agent',
|
2025-02-09 23:17:11 +00:00
|
|
|
image: env."${component.name}_buildAgentImage",
|
2025-02-07 07:18:40 +00:00
|
|
|
ttyEnabled: true,
|
|
|
|
|
command: 'sleep',
|
2025-02-17 12:16:15 +00:00
|
|
|
args: 'infinity',
|
2025-02-17 13:21:39 +00:00
|
|
|
resourceLimitCpu: "1",
|
2025-02-17 12:28:41 +00:00
|
|
|
resourceLimitMemory: "2Gi",
|
2025-02-17 13:21:39 +00:00
|
|
|
resourceRequestCpu: "0.5",
|
2025-02-17 13:13:15 +00:00
|
|
|
resourceRequestMemory: "1Gi"
|
2025-02-07 07:18:40 +00:00
|
|
|
)
|
|
|
|
|
]
|
|
|
|
|
) {
|
|
|
|
|
node("build-agent-${component.name}") {
|
|
|
|
|
container('build-agent') {
|
|
|
|
|
script {
|
2025-02-22 12:33:26 +00:00
|
|
|
if (env.executeMode == "fully" || env.changedComponents.split(/\s+/).toList().contains(component.name)) {
|
2025-02-09 23:17:11 +00:00
|
|
|
def buildAgentImage = env."${component.name}_buildAgentImage"
|
|
|
|
|
log.info("Pipeline", "Using ${buildAgentImage} as build agent image for compilation & packaging")
|
2025-02-07 07:18:40 +00:00
|
|
|
|
|
|
|
|
def sourceFetcher = new SourceFetcher(this)
|
|
|
|
|
sourceFetcher.fetch(configurations)
|
|
|
|
|
|
|
|
|
|
def language = ServiceLanguage.parse(component.language)
|
|
|
|
|
def depManager = DependenciesManager.parse(component.dependenciesManager)
|
|
|
|
|
|
|
|
|
|
def dependenciesResolver = new DependenciesResolver(this, language, env.workroot + "/" + component.root + "/")
|
|
|
|
|
dependenciesResolver.useManager(depManager)
|
|
|
|
|
if (component.buildCacheEnabled) {
|
|
|
|
|
dependenciesResolver.enableCachingSupport()
|
|
|
|
|
} else {
|
|
|
|
|
dependenciesResolver.disableCachingSupport()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dependenciesResolver.resolve(component)
|
2025-02-05 08:29:52 +00:00
|
|
|
|
2025-02-07 07:18:40 +00:00
|
|
|
dir(env.workroot + "/" + component.root) {
|
|
|
|
|
if (component.buildCommand != null && !component.buildCommand.isEmpty()) {
|
|
|
|
|
sh component.buildCommand
|
|
|
|
|
}
|
|
|
|
|
component.buildArtifacts.each { artifact ->
|
2025-02-08 03:47:29 +00:00
|
|
|
log.info("Pipeline", "Stashing artifact ${artifact} for ${component.name}...")
|
2025-02-09 22:43:33 +00:00
|
|
|
def artifactList = sh(script: "ls ${artifact} -al", returnStdout: true)
|
2025-02-09 22:00:20 +00:00
|
|
|
log.info("Pipeline", "Artifacts list: ${artifactList}")
|
2025-02-08 03:38:50 +00:00
|
|
|
def targetPathType = sh(
|
|
|
|
|
script: """
|
|
|
|
|
if [ -d "${artifact}" ]; then
|
|
|
|
|
echo "dir"
|
|
|
|
|
elif [ -f "${artifact}" ]; then
|
|
|
|
|
echo "file"
|
|
|
|
|
else
|
|
|
|
|
echo "unknown"
|
|
|
|
|
fi
|
|
|
|
|
""",
|
|
|
|
|
returnStdout: true
|
|
|
|
|
)
|
|
|
|
|
if (artifact == '.' || artifact == './') {
|
2025-02-09 22:43:57 +00:00
|
|
|
log.info("Pipeline", "Stashing root directory for ${component.name}...")
|
2025-02-09 22:43:33 +00:00
|
|
|
stash includes: "", name: "${component.name}-root"
|
2025-02-08 03:38:50 +00:00
|
|
|
} else if (targetPathType.trim() == "dir") {
|
|
|
|
|
stash includes: "${artifact}/**", name: "${component.name}-${artifact}"
|
|
|
|
|
} else {
|
|
|
|
|
stash includes: artifact, name: "${component.name}-${artifact}"
|
|
|
|
|
}
|
2025-02-07 07:18:40 +00:00
|
|
|
}
|
|
|
|
|
}
|
2025-02-07 07:57:10 +00:00
|
|
|
}
|
2025-02-07 07:18:40 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-02-09 23:03:47 +00:00
|
|
|
}},
|
2025-02-07 07:57:10 +00:00
|
|
|
// Image Builder Setup
|
2025-02-09 23:03:47 +00:00
|
|
|
{stage("${component.name} :: Image Builder Setup") {
|
2025-02-07 07:18:40 +00:00
|
|
|
script {
|
2025-02-22 12:33:26 +00:00
|
|
|
if (env.executeMode == "fully" || env.changedComponents.split(/\s+/).toList().contains(component.name)) {
|
2025-02-07 07:18:40 +00:00
|
|
|
log.info("Pipeline", "Ready to setup image builder for ${component.name}")
|
|
|
|
|
def imageBuilder
|
|
|
|
|
if (component.imageBuilder == null || component.imageBuilder.isEmpty()) {
|
|
|
|
|
log.info("Pipeline", "imageBuilder not set for ${component.name}, using kaniko as default image builder")
|
|
|
|
|
imageBuilder = ImageBuilderTypes.KANIKO
|
|
|
|
|
} else {
|
|
|
|
|
imageBuilder = ImageBuilderTypes.parse(component.imageBuilder)
|
|
|
|
|
if (imageBuilder == null) {
|
|
|
|
|
log.error("Pipeline", "Unknown image builder for ${component.name}, skipping image building")
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-02-05 08:29:52 +00:00
|
|
|
|
2025-02-09 23:17:11 +00:00
|
|
|
env."${component.name}_imageBuilderImage" = imageBuilder.image
|
2025-02-07 07:18:40 +00:00
|
|
|
log.info("Pipeline", "Using ${imageBuilder.builder} (image: ${imageBuilder.image}) as image builder for ${component.name}")
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-02-09 23:03:47 +00:00
|
|
|
}},
|
2025-02-17 10:44:13 +00:00
|
|
|
// Image Building & Publishing
|
|
|
|
|
{stage("${component.name} :: Image Building & Publishing") {
|
2025-02-07 07:18:40 +00:00
|
|
|
podTemplate(
|
|
|
|
|
label: "image-builder-${component.name}",
|
2025-02-20 09:28:45 +00:00
|
|
|
yaml: """
|
|
|
|
|
apiVersion: v1
|
|
|
|
|
kind: Pod
|
|
|
|
|
spec:
|
|
|
|
|
affinity:
|
|
|
|
|
nodeAffinity:
|
|
|
|
|
requiredDuringSchedulingIgnoredDuringExecution:
|
|
|
|
|
nodeSelectorTerms:
|
|
|
|
|
- matchExpressions:
|
|
|
|
|
- key: "node-role.kubernetes.io/devops"
|
|
|
|
|
operator: In
|
|
|
|
|
values: ["true"]
|
|
|
|
|
tolerations:
|
|
|
|
|
- key: "node-role.kubernetes.io/devops"
|
|
|
|
|
operator: Equal
|
|
|
|
|
value: "true"
|
|
|
|
|
effect: "NoSchedule"
|
|
|
|
|
""",
|
2025-02-22 11:17:25 +00:00
|
|
|
yamlMergeStrategy: merge(),
|
2025-02-07 07:18:40 +00:00
|
|
|
containers: [
|
|
|
|
|
containerTemplate(
|
|
|
|
|
name: 'image-builder',
|
2025-02-09 23:17:11 +00:00
|
|
|
image: env."${component.name}_imageBuilderImage",
|
2025-02-09 17:54:12 +00:00
|
|
|
privileged: true,
|
2025-02-07 07:18:40 +00:00
|
|
|
ttyEnabled: true,
|
|
|
|
|
command: 'sleep',
|
2025-02-09 18:01:34 +00:00
|
|
|
args: 'infinity'
|
2025-02-07 07:18:40 +00:00
|
|
|
)
|
2025-02-09 17:54:12 +00:00
|
|
|
],
|
|
|
|
|
volumes: [
|
|
|
|
|
hostPathVolume(hostPath: '/var/run/docker.sock', mountPath: '/var/run/docker.sock')
|
2025-02-07 07:18:40 +00:00
|
|
|
]
|
|
|
|
|
) {
|
|
|
|
|
node("image-builder-${component.name}") {
|
|
|
|
|
container('image-builder') {
|
|
|
|
|
script {
|
2025-02-22 12:33:26 +00:00
|
|
|
if (env.executeMode == "fully" || env.changedComponents.split(/\s+/).toList().contains(component.name)) {
|
2025-02-07 07:18:40 +00:00
|
|
|
def sourceFetcher = new SourceFetcher(this)
|
|
|
|
|
sourceFetcher.fetch(configurations)
|
2025-02-05 08:29:52 +00:00
|
|
|
|
2025-02-07 07:18:40 +00:00
|
|
|
dir(env.workroot + "/" + component.root) {
|
|
|
|
|
component.buildArtifacts.each { artifact ->
|
2025-02-08 03:38:50 +00:00
|
|
|
if (artifact == '.' || artifact == './') {
|
|
|
|
|
unstash "${component.name}-root"
|
|
|
|
|
} else {
|
|
|
|
|
unstash "${component.name}-${artifact}"
|
|
|
|
|
}
|
2025-02-07 07:18:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (component.dockerfile != null && !component.dockerfile.isEmpty()) {
|
|
|
|
|
log.error("Pipeline", "Component ${component.name} dockerfile not set!")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def imageBuilderType = ImageBuilderTypes.parse(component.imageBuilder)
|
|
|
|
|
if (imageBuilderType == null) {
|
|
|
|
|
log.error("Pipeline", "Unknown image builder for ${component.name}, skipping image building")
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-09 18:56:27 +00:00
|
|
|
def imageBuilder = new ImageBuilder(this,
|
|
|
|
|
env.workroot + "/" + component.root + "/",
|
|
|
|
|
component.imageBuildRoot,
|
|
|
|
|
component.dockerfilePath,
|
|
|
|
|
imageBuilderType
|
|
|
|
|
)
|
2025-02-07 07:18:40 +00:00
|
|
|
|
|
|
|
|
log.info("Pipeline", "Retrieve version of image from pervious stage...")
|
|
|
|
|
if (env.LATEST_VERSION == null || env.LATEST_VERSION.isEmpty()) {
|
|
|
|
|
log.warn("Pipeline", "LATEST_VERSION environment value not set, using 'snapshot-<BUILD_COMMIT_HASH>' as default version")
|
2025-02-17 11:51:49 +00:00
|
|
|
sh "git config --global --add safe.directory ${env.workroot}"
|
2025-02-07 07:18:40 +00:00
|
|
|
def commitHash = sh(script: 'git rev-parse HEAD', returnStdout: true).trim()
|
|
|
|
|
def shortCommitHash = commitHash.take(7)
|
|
|
|
|
env.LATEST_VERSION = "snapshot-${shortCommitHash}"
|
|
|
|
|
}
|
|
|
|
|
def version
|
2025-02-05 08:29:52 +00:00
|
|
|
|
2025-02-09 18:56:27 +00:00
|
|
|
imageBuilder.setManifestsOfImage(component.imageRegistry, component.imageRepository, component.imageName, env.LATEST_VERSION)
|
|
|
|
|
imageBuilder.useCredentials(component.registryCredentialsId)
|
|
|
|
|
imageBuilder.setArchitectures(component.imageReleaseArchitectures)
|
|
|
|
|
imageBuilder.build()
|
2025-02-07 07:18:40 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-02-17 10:44:13 +00:00
|
|
|
}},
|
|
|
|
|
{stage("${component.name} :: Argo Application Version Updating") {
|
2025-02-17 17:08:16 +00:00
|
|
|
podTemplate(
|
|
|
|
|
label: "argo-app-version-updater-${component.name}",
|
2025-02-20 09:28:45 +00:00
|
|
|
yaml: """
|
|
|
|
|
apiVersion: v1
|
|
|
|
|
kind: Pod
|
|
|
|
|
spec:
|
|
|
|
|
affinity:
|
|
|
|
|
nodeAffinity:
|
|
|
|
|
requiredDuringSchedulingIgnoredDuringExecution:
|
|
|
|
|
nodeSelectorTerms:
|
|
|
|
|
- matchExpressions:
|
|
|
|
|
- key: "node-role.kubernetes.io/devops"
|
|
|
|
|
operator: In
|
|
|
|
|
values: ["true"]
|
|
|
|
|
tolerations:
|
|
|
|
|
- key: "node-role.kubernetes.io/devops"
|
|
|
|
|
operator: Equal
|
|
|
|
|
value: "true"
|
|
|
|
|
effect: "NoSchedule"
|
|
|
|
|
""",
|
2025-02-22 11:17:25 +00:00
|
|
|
yamlMergeStrategy: merge(),
|
2025-02-17 17:08:16 +00:00
|
|
|
containers: [
|
|
|
|
|
containerTemplate(
|
|
|
|
|
name: "argo-app-version-updater",
|
|
|
|
|
image: "debian:12",
|
|
|
|
|
ttyEnabled: true,
|
|
|
|
|
command: 'sleep',
|
|
|
|
|
args: 'infinity'
|
|
|
|
|
)
|
|
|
|
|
]
|
|
|
|
|
) {
|
|
|
|
|
node("argo-app-version-updater-${component.name}") {
|
|
|
|
|
container("argo-app-version-updater") {
|
|
|
|
|
script {
|
2025-02-22 12:33:26 +00:00
|
|
|
if (env.executeMode == "fully" || env.changedComponents.split(/\s+/).toList().contains(component.name)) {
|
2025-02-17 17:08:16 +00:00
|
|
|
def argoApplicationVersionUpdater = new ArgoApplicationVersionUpdater(this, configurations)
|
|
|
|
|
argoApplicationVersionUpdater.update(configurations.environmentSlug, component)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-02-17 10:14:40 +00:00
|
|
|
}
|
|
|
|
|
}
|
2025-02-17 10:44:13 +00:00
|
|
|
}}
|
2025-02-07 07:57:10 +00:00
|
|
|
])
|
2025-02-09 21:19:12 +00:00
|
|
|
return {
|
2025-02-09 23:03:47 +00:00
|
|
|
stages.each { stageClosure ->
|
|
|
|
|
stageClosure()
|
2025-02-09 21:19:12 +00:00
|
|
|
}
|
|
|
|
|
}
|
2025-02-04 06:38:58 +00:00
|
|
|
}
|
|
|
|
|
|
2025-02-04 02:54:41 +00:00
|
|
|
def call(Closure closure) {
|
|
|
|
|
def configurations = [:]
|
|
|
|
|
closure.resolveStrategy = Closure.DELEGATE_FIRST
|
|
|
|
|
closure.delegate = configurations
|
|
|
|
|
closure()
|
2025-01-22 07:35:03 +00:00
|
|
|
|
2025-01-17 08:25:04 +00:00
|
|
|
pipeline {
|
|
|
|
|
agent any
|
|
|
|
|
options {
|
|
|
|
|
buildDiscarder(logRotator(numToKeepStr: '25'))
|
|
|
|
|
timeout(time: 30, unit: 'MINUTES')
|
2025-02-04 04:08:52 +00:00
|
|
|
parallelsAlwaysFailFast()
|
2025-01-17 08:25:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stages {
|
2025-02-07 07:18:40 +00:00
|
|
|
stage("Pipeline :: Commit Linting If Enabled") {
|
2025-02-04 04:11:42 +00:00
|
|
|
when {
|
|
|
|
|
expression {
|
|
|
|
|
return configurations.commitMessageLintEnabled != null && configurations.commitMessageLintEnabled
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-02-04 02:23:25 +00:00
|
|
|
agent {
|
|
|
|
|
kubernetes {
|
|
|
|
|
defaultContainer 'commit-message-linter'
|
|
|
|
|
yaml """
|
|
|
|
|
apiVersion: v1
|
|
|
|
|
kind: Pod
|
|
|
|
|
metadata:
|
|
|
|
|
labels:
|
|
|
|
|
freeleaps-devops-system/milestone: commit-message-linting
|
|
|
|
|
spec:
|
2025-02-20 09:28:45 +00:00
|
|
|
affinity:
|
|
|
|
|
nodeAffinity:
|
|
|
|
|
requiredDuringSchedulingIgnoredDuringExecution:
|
|
|
|
|
nodeSelectorTerms:
|
|
|
|
|
- matchExpressions:
|
|
|
|
|
- key: "node-role.kubernetes.io/devops"
|
|
|
|
|
operator: In
|
|
|
|
|
values: ["true"]
|
|
|
|
|
tolerations:
|
|
|
|
|
- key: "node-role.kubernetes.io/devops"
|
|
|
|
|
operator: Equal
|
|
|
|
|
value: "true"
|
|
|
|
|
effect: "NoSchedule"
|
2025-02-04 02:23:25 +00:00
|
|
|
containers:
|
|
|
|
|
- name: commit-message-linter
|
|
|
|
|
image: docker.io/commitlint/commitlint:master
|
|
|
|
|
command:
|
|
|
|
|
- cat
|
|
|
|
|
tty: true
|
|
|
|
|
volumeMounts:
|
|
|
|
|
- name: workspace
|
|
|
|
|
mountPath: /workspace
|
|
|
|
|
volumes:
|
|
|
|
|
- name: workspace
|
|
|
|
|
emptyDir: {}
|
|
|
|
|
"""
|
2025-01-17 08:25:04 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
steps {
|
2025-01-20 02:12:26 +00:00
|
|
|
script {
|
2025-02-04 04:11:42 +00:00
|
|
|
log.info("Pipeline","Commit message linting is enabled")
|
2025-02-04 05:07:52 +00:00
|
|
|
def sourceFetcher = new SourceFetcher(this)
|
2025-02-04 04:11:42 +00:00
|
|
|
sourceFetcher.fetch(configurations)
|
2025-02-04 02:23:25 +00:00
|
|
|
|
2025-02-04 04:11:42 +00:00
|
|
|
def linter = new CommitMessageLinter(this)
|
|
|
|
|
linter.lint(configurations)
|
2025-01-17 08:25:04 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-07 07:18:40 +00:00
|
|
|
stage("Pipeline :: Execute Mode Detection") {
|
2025-01-21 09:01:31 +00:00
|
|
|
steps {
|
|
|
|
|
script {
|
2025-02-04 02:23:25 +00:00
|
|
|
def executeMode = configurations.executeMode
|
|
|
|
|
if (executeMode == null || executeMode.isEmpty()) {
|
2025-02-04 04:03:30 +00:00
|
|
|
log.warn("Pipeline","Not set executeMode, using fully as default execute mode")
|
2025-02-04 02:23:25 +00:00
|
|
|
env.executeMode = "fully"
|
2025-02-04 04:11:42 +00:00
|
|
|
} else if (executeMode == 'on-demand' && configurations.serviceGitRepoType != 'monorepo') {
|
2025-02-04 04:03:30 +00:00
|
|
|
log.warn("Pipeline","serviceGirRepoType is not monorepo, on-demand mode is not supported, using fully mode")
|
2025-02-04 02:23:25 +00:00
|
|
|
env.executeMode = "fully"
|
|
|
|
|
} else {
|
2025-02-04 04:03:30 +00:00
|
|
|
log.info("Pipeline","Using ${executeMode} as execute mode")
|
2025-02-04 02:23:25 +00:00
|
|
|
env.executeMode = executeMode
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-01-21 09:01:31 +00:00
|
|
|
|
2025-02-07 07:18:40 +00:00
|
|
|
stage("Pipeline :: Code Changes Detection") {
|
2025-02-04 04:13:41 +00:00
|
|
|
when {
|
|
|
|
|
expression {
|
|
|
|
|
return env.executeMode == "on-demand"
|
2025-01-21 09:01:31 +00:00
|
|
|
}
|
2025-02-04 04:13:41 +00:00
|
|
|
}
|
2025-02-04 02:23:25 +00:00
|
|
|
|
2025-02-04 04:13:41 +00:00
|
|
|
steps {
|
2025-02-04 02:23:25 +00:00
|
|
|
script {
|
2025-02-22 12:38:49 +00:00
|
|
|
def sourceFetcher = new SourceFetcher(this)
|
2025-02-04 02:23:25 +00:00
|
|
|
sourceFetcher.fetch(configurations)
|
|
|
|
|
|
|
|
|
|
def changedComponentsDetector = new ChangedComponentsDetector(this)
|
2025-02-07 07:18:40 +00:00
|
|
|
def changedComponents = changedComponentsDetector.detect(env.workroot, configurations.components)
|
2025-02-04 02:23:25 +00:00
|
|
|
|
2025-02-04 04:03:30 +00:00
|
|
|
log.info("Pipeline","Changed components: ${changedComponents}")
|
2025-02-04 02:23:25 +00:00
|
|
|
env.changedComponents = changedComponents.join(' ')
|
|
|
|
|
}
|
2025-01-21 09:01:31 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-07 07:18:40 +00:00
|
|
|
stage("Pipeline :: Components Build (Dynamic Generated Stages)") {
|
2025-02-04 06:38:58 +00:00
|
|
|
steps {
|
2025-02-04 02:36:58 +00:00
|
|
|
script {
|
2025-02-22 12:45:11 +00:00
|
|
|
if (env.executeMode == "fully") {
|
2025-02-22 12:33:26 +00:00
|
|
|
configurations.components.each { component ->
|
|
|
|
|
log.info("Pipeline", "Executing generated stages for ${component.name}...")
|
|
|
|
|
generateComponentStages(component, configurations)()
|
|
|
|
|
}
|
2025-02-22 12:45:11 +00:00
|
|
|
} else if {
|
|
|
|
|
def changedComponents = env.changedComponents.split(/\s+/).toList()
|
|
|
|
|
configurations.components.each { component ->
|
|
|
|
|
if (changedComponents.contains(component.name)) {
|
|
|
|
|
log.info("Pipeline", "Executing generated stages for ${component.name}...")
|
|
|
|
|
generateComponentStages(component, configurations)()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
log.info("Pipeline", "No components changed, skipping...")
|
2025-02-09 23:35:11 +00:00
|
|
|
}
|
2025-01-21 09:01:31 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-17 08:25:04 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|