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
|
|
|
|
|
import com.freeleaps.devops.enums.DependenciesManager
|
2025-01-22 08:07:46 +00:00
|
|
|
import com.freeleaps.devops.enums.ServiceLanguage
|
2025-02-04 02:23:25 +00:00
|
|
|
import com.freeleaps.devops.CommitMessageLinter
|
|
|
|
|
import com.freeleaps.devops.ChangedComponentsDetector
|
2025-01-17 08:25:04 +00:00
|
|
|
|
2025-02-04 06:59:41 +00:00
|
|
|
def generateComponentStages(component, configurations) {
|
2025-02-04 06:42:41 +00:00
|
|
|
return [
|
2025-02-04 06:59:41 +00:00
|
|
|
stage("${component.name} :: Build Agent Setup") {
|
|
|
|
|
script {
|
|
|
|
|
if (env.executeMode == "fully" || env.changedComponents.contains(component.name)) {
|
|
|
|
|
def buildAgentImage = component.buildAgentImage
|
|
|
|
|
if (buildAgentImage == null || buildAgentImage.isEmpty()) {
|
|
|
|
|
log.warn("Pipeline", "Not set buildAgentImage for ${component.name}, using default build agent image")
|
|
|
|
|
|
2025-02-04 07:34:54 +00:00
|
|
|
def language = ServiceLanguage.parse(component.language)
|
2025-02-04 06:59:41 +00:00
|
|
|
switch(language) {
|
|
|
|
|
case ServiceLanguage.PYTHON:
|
2025-02-04 07:33:07 +00:00
|
|
|
buildAgentImage = "docker.io/python:3.10-slim-buster"
|
2025-02-04 06:59:41 +00:00
|
|
|
break
|
|
|
|
|
case ServiceLanguage.JS:
|
2025-02-04 07:33:07 +00:00
|
|
|
buildAgentImage = "docker.io/node:lts-alpine"
|
2025-02-04 06:59:41 +00:00
|
|
|
break
|
|
|
|
|
default:
|
|
|
|
|
error("Unknown service language")
|
2025-02-04 06:38:58 +00:00
|
|
|
}
|
|
|
|
|
}
|
2025-02-04 06:59:41 +00:00
|
|
|
log.info("Pipeline", "Using ${buildAgentImage} as build agent image for ${component.name}")
|
|
|
|
|
env.buildAgentImage = buildAgentImage
|
2025-02-04 06:38:58 +00:00
|
|
|
}
|
2025-02-04 06:59:41 +00:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
stage("${component.name} :: Dependencies Resolving") {
|
|
|
|
|
podTemplate(
|
|
|
|
|
label: "dep-resolver-${component.name}",
|
|
|
|
|
containers: [
|
|
|
|
|
containerTemplate(
|
|
|
|
|
name: 'dep-resolver',
|
|
|
|
|
image: env.buildAgentImage,
|
|
|
|
|
ttyEnabled: true,
|
|
|
|
|
command: 'sleep',
|
|
|
|
|
args: 'infinity'
|
|
|
|
|
)
|
|
|
|
|
]
|
|
|
|
|
) {
|
|
|
|
|
node("dep-resolver-${component.name}") {
|
2025-02-04 07:22:59 +00:00
|
|
|
script {
|
2025-02-04 07:25:40 +00:00
|
|
|
if (env.executeMode == "fully" || env.changedComponents.contains(component.name)) {
|
|
|
|
|
log.info("Pipeline", "Using ${env.buildAgentImage} as build agent image for dependencies resolving")
|
|
|
|
|
def sourceFetcher = new SourceFetcher(this)
|
|
|
|
|
sourceFetcher.fetch(configurations)
|
2025-02-04 07:22:59 +00:00
|
|
|
|
2025-02-04 07:25:40 +00:00
|
|
|
def language = ServiceLanguage.parse(component.language)
|
|
|
|
|
def depManager = DependenciesManager.parse(component.dependenciesManager)
|
2025-02-04 07:22:59 +00:00
|
|
|
|
2025-02-04 07:25:40 +00:00
|
|
|
def dependenciesResolver = new DependenciesResolver(this, language, env.workspace + "/" + component.root + "/")
|
|
|
|
|
dependenciesResolver.useManager(depManager)
|
|
|
|
|
|
|
|
|
|
if (component.buildCacheEnabled) {
|
|
|
|
|
dependenciesResolver.enableCachingSupport()
|
|
|
|
|
} else {
|
|
|
|
|
dependenciesResolver.disableCachingSupport()
|
2025-02-04 07:16:36 +00:00
|
|
|
}
|
2025-02-04 07:25:40 +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-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-04 02:23:25 +00:00
|
|
|
stage("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:
|
|
|
|
|
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-04 02:23:25 +00:00
|
|
|
stage("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-04 02:23:25 +00:00
|
|
|
stage("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 {
|
|
|
|
|
sourceFetcher.fetch(configurations)
|
|
|
|
|
|
|
|
|
|
def changedComponentsDetector = new ChangedComponentsDetector(this)
|
|
|
|
|
def changedComponents = changedComponentsDetector.detect(env.workspace, configurations.components)
|
|
|
|
|
|
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-04 02:36:58 +00:00
|
|
|
stage("Components Build (Dynamic Generated Stages)") {
|
2025-02-04 04:18:24 +00:00
|
|
|
when {
|
|
|
|
|
expression {
|
|
|
|
|
return env.executeMode == "fully" || env.changedComponents.size() > 0
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-02-04 06:38:58 +00:00
|
|
|
steps {
|
2025-02-04 02:36:58 +00:00
|
|
|
script {
|
|
|
|
|
configurations.components.each { component ->
|
2025-02-04 06:59:41 +00:00
|
|
|
def generatedStages = generateComponentStages(component, configurations)
|
2025-02-04 06:50:08 +00:00
|
|
|
generatedStages.each { stage ->
|
|
|
|
|
stage(stage)
|
|
|
|
|
}
|
2025-02-04 02:23:25 +00:00
|
|
|
}
|
2025-01-21 09:01:31 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-17 08:25:04 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|