Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BXMSPROD-2019] Productized branch creation #967

Merged
merged 7 commits into from
Jun 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .ci/jenkins/Jenkinsfile.setup-branch
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ pipeline {

// Launch the nightly to deploy all artifacts from the branch
stage('Launch the nightly') {
when {
return params.DEPLOY_ARTIFACTS
}
steps {
script {
def buildParams = getDefaultBuildParams()
Expand Down
1 change: 1 addition & 0 deletions .ci/jenkins/dsl/jobs.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ void createSetupBranchJob() {
parameters {
stringParam('KOGITO_VERSION', '', 'Kogito version')
stringParam('DROOLS_VERSION', '', 'Drools version')
booleanParam('DEPLOY_ARTIFACTS', true, 'Deploy artifacts')
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions dsl/config/branch.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ git:
buildchain_config:
git:
repository: kogito-pipelines
file_path: .ci/pull-request-config.yaml
maven:
settings_file_id: kogito_release_settings
nexus:
Expand Down Expand Up @@ -140,3 +141,4 @@ jenkins:
default_tools:
jdk: kie-jdk11
maven: kie-maven-3.8.7
jobs_definition_file: .ci/jenkins/dsl/jobs.groovy
195 changes: 178 additions & 17 deletions dsl/seed/jenkinsfiles/Jenkinsfile.prod.prepare
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import java.util.regex.Pattern

// parameters
// 1. <prj>_RELEASE_BRANCH
// 2. QUARKUS_VERSION
// 3. ADDITIONAL_BUILD_MAVEN_OPTS
// 2. <prj>_UPDATE_VERSION (this includes also dependencies)
// 3. QUARKUS_VERSION
// 4. DOWNGRADE_QUARKUS_PR_BRANCH
// 5. ADDITIONAL_BUILD_MAVEN_OPTS
// 6. PROJECTS_TO_REMOVE_FROM_PR_CHECKS

seedConfig = [:]
mainBranchConfig = [:]
Expand Down Expand Up @@ -133,6 +136,38 @@ pipeline{
sh "rm -f ${branchConfigFilePath}"
writeYaml file: "${branchConfigFilePath}", data: branchConfig, overwrite: true

// update build-chain configuration
// comment out projects we are not interested in from the buildchain-config.yaml
def projectToRemoveFromBCPRChecks = getProjectsToRemoveFromBuildChainConfig()

if (projectToRemoveFromBCPRChecks) {
// update build-chain config
def buildChainConfigFilePath = readMainBranchConfig().buildchain_config.git.file_path
def buildChainConfig = readYaml file: buildChainConfigFilePath

def builds = buildChainConfig.build.findAll { build ->
!projectToRemoveFromBCPRChecks.contains(build.project)
}
buildChainConfig.build = builds

echo "Write build-chain configuration => ${buildChainConfig}"
sh "rm -f ${buildChainConfigFilePath}"
writeYaml file: "${buildChainConfigFilePath}", data: buildChainConfig, overwrite: true

// update build-chain project dependencies
def buildChainConfigDependenciesFilePath = buildChainConfigFilePath.substring(0, buildChainConfigFilePath.lastIndexOf('/') + 1) + "${buildChainConfig.dependencies}"
def buildChainConfigDependencies = readYaml file: buildChainConfigDependenciesFilePath

def deps = buildChainConfigDependencies.dependencies.findAll { dep ->
!projectToRemoveFromBCPRChecks.contains(dep.project)
}
buildChainConfigDependencies.dependencies = deps

echo "Write build-chain dependencies configuration => ${buildChainConfigDependencies}"
sh "rm -f ${buildChainConfigDependenciesFilePath}"
writeYaml file: "${buildChainConfigDependenciesFilePath}", data: buildChainConfigDependencies, overwrite: true
}

pushIfChanged(prodBranch, getMainBranchConfigFileGitAuthorCredentialsId(), "Setup DSL branch config after productized branch creation", "Branch config on ${prodBranch} has been updated with correct configuration")
}
}
Expand All @@ -146,27 +181,124 @@ pipeline{
// - disable GHA jobs no more needed by commenting out workflows
// - enable productized profile (-Dproductized) on GHA PR checks workflows
// - ensure that fullProfile is not enabled on .ci/jenkins/dsl/jobs.groovy, if so remove it
stage("Update prod branch for all projects to be productized"){
steps{
script {
def prodRepositories = getProdRepositoriesToBranch()
prodRepositories.each { repoConfig ->
String repository = repoConfig.name
String repoAuthor = repoConfig.author?.name ?: readMainBranchConfig().git.author.name
String repoCredsId = repoConfig.author?.credentials_id ?: readMainBranchConfig().git.author.credentials_id

String jobsGroovyPath = getJobDefinitionFilePath()

dir(repository) {
deleteDir()
// here productized branches should have been already created on repos to be productized
checkout(githubscm.resolveRepository(repository, repoAuthor, getProductizedBranchFromRepository(repository), false, repoCredsId))

getOrCreateGitBranch(repoConfig.branch, getRepositoryAuthorCredsId())

if (fileExists("${jobsGroovyPath}")) {
// def jobsGroovy = readFile file: jobsGroovyPath
// remove fullProfile
sh "sed -i 's/, addFullProfileJobParamsGetter)/)/g' ${jobsGroovyPath}"
// TODO: disable pr checks in getMultijobPRConfig, get them from params
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be the last remaining part to implement, disable PR checks from jobs.groovy file.
I would do that in a separate PR as I need to re-think a bit what is the best way to handle it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to redo the way the PR checks are generated in those repositories, to make it more dynamic, based on:

  • build-chain-config
  • or a file in .ci folder (name to be considered)

we can discuss about that if you want

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree as at the moment to disable them we should manipulate the file and it could be tricky to fully automate, furthermore changes on the file could also easily break the automation as it would be. So I agree on rethink how to setup those jobs.

} else {
echo "[WARN] Unable to find jobs.groovy for '${repository}' at '${jobsGroovyPath}'"
}


// TODO iterate over PR workflows
// - comment out if not needed (get these from param?)
// - if PR check is needed, keep it and add -Dproductized
}
}
}
}
}

// 3. update the projects version in order to avoid any kind of conflicts with already existing and deployed artifacts

stage("Update projects version"){
when {
expression { return getProjectUpdateVersionKeys().findAll{ it.value != '' } }
}
steps{
script {
println "Updating projects versions"

String jobName = "${getEcosystemProductizedBranch()}/setup-branch/0-setup-branch"
List jobParams = []
jobParams.add(booleanParam(name: 'DEPLOY_ARTIFACTS', value: false))
// here we could have a variable number of params
getProjectUpdateVersionKeys().each{ p ->
jobParams.add(stringParam(name: p.key.replace('_UPDATE', ''), value: p.value))
}

// stage("Update prod branch for all projects to be productized"){
// steps{
// script {
// // TODO: implement
// }
// }
// }
echo "Build ./${jobName} with parameters ${jobParams}"
if (!isDryRun()) {
def job = build(job: "./${jobName}", parameters: jobParams, wait: true, propagate: false)
if (job.result != 'SUCCESS') {
unstable("Update projects version on repositories was not successful")
}
}
}
}
}

// 3. call update quarkus job in order to downgrade quarkus to LTS version (version provided as parameter QUARKUS_VERSION)
// 4. call update quarkus job in order to downgrade quarkus to LTS version (version provided as parameter QUARKUS_VERSION)
// this will:
// - downgrade quarkus, there already exists a job doing this
// - apply patches from .ci/environments/quarkus-lts on the same PR

// stage('Downgrade quarkus to LTS version'){
// steps{
// script {
// // TODO: implement
// }
// }
// }
stage('Downgrade quarkus to LTS version'){
when {
expression { return params.QUARKUS_VERSION }
}
steps{
script {
println "Launch update quarkus all"

String jobName = "${getEcosystemProductizedBranch()}/tools/update-quarkus-all"
String quarkusDowngradePrBranch = getQuarkusDowngradePrBranch()
List jobParams = []
jobParams.add(stringParam(name: 'NEW_VERSION', value: getQuarkusVersion()))
jobParams.add(stringParam(name: 'PR_BRANCH', value: quarkusDowngradePrBranch))

echo "Build ./${jobName} with parameters ${jobParams}"
if (!isDryRun()) {
def job = build(job: "./${jobName}", parameters: jobParams, wait: true, propagate: false)

if (job.result == 'SUCCESS') {
def prodRepositories = getProdRepositoriesToBranch()
prodRepositories.each { repoConfig ->
String repoAuthor = repoConfig.author?.name ?: readMainBranchConfig().git.author.name
String repoCredsId = repoConfig.author?.credentials_id ?: readMainBranchConfig().git.author.credentials_id
String repository = repoConfig.name
String baseBranch = repoConfig.branch ?: 'main'

dir(repository) {
deleteDir()
checkout(githubscm.resolveRepository(repository, repoAuthor, baseBranch, false, repoCredsId))

// if quarkusDowngradePrBranch has been created by update-quarkus-all job, checkout it
if (checkoutGitBranchIfExists(quarkusDowngradePrBranch, repoCredsId)) {
// thefollowing script takes care of applying all patches needed when downgrading to Quarkus LTS
// i.e., it will apply all patches found under .ci/environments/quarkus-lts/patches
sh '.ci/environments/update.sh quarkus-lts'

pushIfChanged(quarkusDowngradePrBranch, repoCredsId, "Applied patches after Quarkus downgrade to ${getQuarkusVersion()}", "Quarkus LTS patches on ${quarkusDowngradePrBranch} have been applied")
}
}
}
} else {
unstable("Update Quarkus on repositories was not successful")
}
}
}
}
}
}
post{
unsuccessful {
Expand Down Expand Up @@ -203,10 +335,18 @@ String getProdBranchSuffixParameterKey(String projectName) {
return params."${key}"
}

def getProjectUpdateVersionKeys() {
return params.findAll{ it.key.contains('_UPDATE_VERSION') }
}

String getQuarkusVersion() {
return params.QUARKUS_VERSION
}

String getQuarkusDowngradePrBranch() {
return params.DOWNGRADE_QUARKUS_PR_BRANCH ?: "${getEcosystemProductizedBranch()}-${getQuarkusVersion()}-downgrade"
}

Boolean isDryRun() {
return params.DRY_RUN
}
Expand All @@ -216,6 +356,10 @@ def getAdditionalDefaultBuildMavenOpts() {
return params.ADDITIONAL_BUILD_MAVEN_OPTS ?: ''
}

def getProjectsToRemoveFromBuildChainConfig() {
return params.PROJECTS_TO_REMOVE_FROM_PR_CHECKS.split(',') as List ?: []
}

// Retrieve seed configuration

String checkoutMainSeedConfigFileRepo() {
Expand Down Expand Up @@ -275,6 +419,9 @@ String getRepoNameCamelCase(String repo) {
return words.collect { it.isEmpty() ? it : it.substring(0, 1).toUpperCase() + it.substring(1).toLowerCase() }.join(' ')
}

String getJobDefinitionFilePath() {
return readMainBranchConfig().jenkins?.jobs_definition_file ?: '.ci/jenkins/dsl/jobs.groovy'
}

// Retrieve impacted projects

Expand Down Expand Up @@ -421,6 +568,20 @@ void getOrCreateGitBranch(String branch, String credentialsId) {
}
}

// If the provided branch exists, checkout it and return true, otherwise return false and skip checkout.
boolean checkoutGitBranchIfExists(String branch, String credentialsId) {
sh 'git fetch origin'
String branchRemoteResult = sh(script: "git ls-remote origin ${branch} | wc -l", returnStdout: true).trim()
if (Integer.parseInt(branchRemoteResult) > 0) {
echo "Branch ${branch} exist. Checking out !"
sh "git checkout ${branch}"
return true
}

echo "Branch ${branch} does not exist... skipping checkout"
return false
}

def pushIfChanged(String branch, String credentialsId, String commitMsg, String notificationMsg) {
if (githubscm.isThereAnyChanges()) {
sh 'git diff'
Expand Down
9 changes: 9 additions & 0 deletions dsl/seed/jobs/root_jobs.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,19 @@ if (communityReleaseBranches) {
PRODUCTIZED_PROJECTS.split(',').each { projectName ->
choiceParam("${projectName}_RELEASE_BRANCH".toUpperCase(), communityReleaseBranches, "${Utils.getRepoNameCamelCase(projectName)} community branch to which to create the productized branch from")
stringParam("${projectName}_PROD_BRANCH_SUFFIX".toUpperCase(), 'prod', "${Utils.getRepoNameCamelCase(projectName)} productized branch suffix")
stringParam("${projectName}_UPDATE_VERSION".toUpperCase(), '', "${Utils.getRepoNameCamelCase(projectName)} dependency version which this will depend on")
}

if (DEPENDENCY_PROJECTS) {
DEPENDENCY_PROJECTS.split(',').each { projectName ->
stringParam("${projectName}_UPDATE_VERSION".toUpperCase(), '', "${Utils.getRepoNameCamelCase(projectName)} dependency version which this will depend on")
}
}

stringParam('QUARKUS_VERSION', '', 'Quarkus version to which to update all productized branches, usually latest LTS version')
stringParam('DOWNGRADE_QUARKUS_PR_BRANCH', '', 'Which PR branch name to use for Quarkus downgrade? If none given, a name will be generated automatically.')
stringParam('ADDITIONAL_BUILD_MAVEN_OPTS', '', 'Additional default maven opts for jenkins jobs, e.g., -Ddata-index-ephemeral.image=quay.io/kiegroup/kogito-data-index-ephemeral')
stringParam('PROJECTS_TO_REMOVE_FROM_PR_CHECKS', '', 'Comma-separated list of projects (<owner>/<repo>) to be removed/disabled from build chain pull request config')

booleanParam('DRY_RUN', false, 'If enabled no changes will be applied to remote branches')
}
Expand Down