From f007952648b08ceb25645873ca837ac7077b6cb1 Mon Sep 17 00:00:00 2001 From: Tristan Radisson Date: Wed, 16 Aug 2023 15:42:07 +0200 Subject: [PATCH] DROOLS-7533 Setup CI for Drools 8 (#86) --- .ci/jenkins/Jenkinsfile.deploy | 289 ++++++++++++++++++ .ci/jenkins/Jenkinsfile.promote | 182 +++++++++++ .ci/jenkins/Jenkinsfile.setup-branch | 142 +++++++++ .ci/jenkins/dsl/jobs.groovy | 238 +++++++++++++++ .ci/jenkins/dsl/test.sh | 34 +++ .github/workflows/pr-backporting.yml | 5 +- .github/workflows/pr-jenkins.yml | 24 ++ .../workflows/{pull_request.yml => pr.yml} | 31 +- .gitignore | 2 + 9 files changed, 932 insertions(+), 15 deletions(-) create mode 100644 .ci/jenkins/Jenkinsfile.deploy create mode 100644 .ci/jenkins/Jenkinsfile.promote create mode 100644 .ci/jenkins/Jenkinsfile.setup-branch create mode 100644 .ci/jenkins/dsl/jobs.groovy create mode 100755 .ci/jenkins/dsl/test.sh create mode 100644 .github/workflows/pr-jenkins.yml rename .github/workflows/{pull_request.yml => pr.yml} (58%) diff --git a/.ci/jenkins/Jenkinsfile.deploy b/.ci/jenkins/Jenkinsfile.deploy new file mode 100644 index 0000000..418e7c8 --- /dev/null +++ b/.ci/jenkins/Jenkinsfile.deploy @@ -0,0 +1,289 @@ +import org.jenkinsci.plugins.workflow.libs.Library +@Library('jenkins-pipeline-shared-libraries')_ + +import org.kie.jenkins.MavenCommand +import org.kie.jenkins.MavenStagingHelper + +deployProperties = [:] + +pipeline { + agent { + label 'kie-rhel8 && docker && kie-mem16g && !built-in' + } + + tools { + maven env.BUILD_MAVEN_TOOL + jdk env.BUILD_JDK_TOOL + } + + options { + timestamps() + timeout(time: 180, unit: 'MINUTES') + } + + environment { + DROOLS_CI_EMAIL_TO = credentials("${JENKINS_EMAIL_CREDS_ID}") + MAVEN_OPTS = '-Xms1024m -Xmx4g' + MAVEN_DEPLOY_LOCAL_DIR = "${WORKSPACE}/maven_deploy_dir" + } + + stages { + stage('Initialize') { + steps { + script { + cleanWs() + + if (params.DISPLAY_NAME) { + currentBuild.displayName = params.DISPLAY_NAME + } + + if (isRelease() || isCreatePr()) { + // Verify version is set + assert getProjectVersion() + + if (isRelease()) { + // Verify if on right release branch + assert getBuildBranch() == util.getReleaseBranchFromVersion(getProjectVersion()) + } + } + + dir(getRepoName()) { + checkoutRepo() + } + } + } + post { + success { + script { + setDeployPropertyIfNeeded('git.branch', getBuildBranch()) + setDeployPropertyIfNeeded('git.author', getGitAuthor()) + setDeployPropertyIfNeeded('project.version', getProjectVersion()) + setDeployPropertyIfNeeded('release', isRelease()) + } + } + } + } + stage('Prepare for PR') { + when { + expression { return isRelease() || isCreatePr() } + } + steps { + script { + dir(getRepoName()) { + if (githubscm.isBranchExist('origin',getPRBranch())) { + githubscm.removeRemoteBranch('origin', getPRBranch()) + } + githubscm.createBranch(getPRBranch()) + } + } + } + } + stage('Update project version') { + when { + expression { return getProjectVersion() } + } + steps { + script { + maven.mvnVersionsSet(getMavenCommand(), getProjectVersion(), !isRelease()) + } + } + } + stage('Build & Test') { + steps { + script { + getMavenCommand().withProperty('maven.test.failure.ignore', true).skipTests(params.SKIP_TESTS).run('clean install') + } + } + post { + always { + script { + saveReports() + util.archiveConsoleLog() + } + } + } + } + stage('Deploy locally') { + steps { + script { + runMavenDeploy(true) + } + } + } + stage('Stage artifacts') { + when { + expression { return shouldStageArtifacts() } + } + steps { + script { + // Stage release artifacts + runMavenStage() + } + } + } + stage('Create PR') { + when { + expression { return isRelease() || isCreatePr() } + } + steps { + script { + dir(getRepoName()) { + if (githubscm.isThereAnyChanges()) { + commitAndCreatePR() + } else { + println '[WARN] no changes to commit' + } + } + } + } + post { + success { + script { + setDeployPropertyIfNeeded("${getRepoName()}.pr.source.uri", "https://github.com/${getGitAuthor()}/${getRepoName()}") + setDeployPropertyIfNeeded("${getRepoName()}.pr.source.ref", getPRBranch()) + setDeployPropertyIfNeeded("${getRepoName()}.pr.target.uri", "https://github.com/${getGitAuthor()}/${getRepoName()}") + setDeployPropertyIfNeeded("${getRepoName()}.pr.target.ref", getBuildBranch()) + } + } + } + } + } + post { + always { + script { + def propertiesStr = deployProperties.collect { entry -> "${entry.key}=${entry.value}" }.join('\n') + writeFile(text: propertiesStr, file: PROPERTIES_FILE_NAME) + archiveArtifacts(artifacts: PROPERTIES_FILE_NAME) + } + } + unsuccessful { + sendNotification() + } + cleanup { + script { + util.cleanNode('docker') + } + } + } +} + +void saveReports() { + junit testResults: '**/target/surefire-reports/**/*.xml, **/target/failsafe-reports/**/*.xml, **/target/invoker-reports/**/TEST-*.xml', allowEmptyResults: true +} + +void checkoutRepo() { + deleteDir() + checkout(githubscm.resolveRepository(getRepoName(), getGitAuthor(), getBuildBranch(), false)) + // need to manually checkout branch since on a detached branch after checkout command + sh "git checkout ${getBuildBranch()}" +} + +void commitAndCreatePR() { + def commitMsg = "[${getBuildBranch()}] Update version to ${getProjectVersion()}" + def prBody = "Generated by build ${BUILD_TAG}: ${BUILD_URL}.\nPlease do not merge, it should be merged automatically." + + githubscm.commitChanges(commitMsg, { + githubscm.findAndStageNotIgnoredFiles('pom.xml') + githubscm.findAndStageNotIgnoredFiles('antora.yml') + }) + githubscm.pushObject('origin', getPRBranch(), getGitAuthorCredsID()) + deployProperties["${getRepoName()}.pr.link"] = githubscm.createPRWithLabels(commitMsg, prBody, getBuildBranch(), ['skip-ci'] as String[], getGitAuthorCredsID()) +} + +void sendNotification() { + if (params.SEND_NOTIFICATION) { + mailer.sendMarkdownTestSummaryNotification('Deploy', "[${getBuildBranch()}] KIE jpmml integration", [env.DROOLS_CI_EMAIL_TO]) + } else { + echo 'No notification sent per configuration' + } +} + +boolean shouldStageArtifacts() { + return isRelease() +} + +boolean shouldDeployToRepository() { + return env.MAVEN_DEPLOY_REPOSITORY || getGitAuthor() == 'kiegroup' +} + +boolean isRelease() { + return env.RELEASE ? env.RELEASE.toBoolean() : false +} + +boolean isCreatePr() { + return params.CREATE_PR +} + +String getRepoName() { + return env.REPO_NAME +} + +String getGitAuthor() { + // GIT_AUTHOR can be env or param + return "${GIT_AUTHOR}" +} + +String getBuildBranch() { + return params.BUILD_BRANCH_NAME +} + +String getProjectVersion() { + return params.PROJECT_VERSION +} + +String getPRBranch() { + return params.DROOLS_PR_BRANCH +} + +String getGitAuthorCredsID() { + return env.AUTHOR_CREDS_ID +} + +void setDeployPropertyIfNeeded(String key, def value) { + if (value) { + deployProperties[key] = value + } +} + +MavenCommand getMavenCommand(String directory = '') { + directory = directory ?: getRepoName() + def mvnCmd = new MavenCommand(this, ['-fae', '-ntp']) + .withSettingsXmlId(env.MAVEN_SETTINGS_CONFIG_FILE_ID) + .inDirectory(directory) + if (!isStream8()) { // Workaround as enforcer rules may not be fixed on other streams + mvnCmd.withProperty('enforcer.skip') + } + return mvnCmd +} + +void runMavenDeploy(boolean localDeployment = false) { + mvnCmd = getMavenCommand() + + if(localDeployment) { + mvnCmd.withLocalDeployFolder(getLocalDeploymentFolder()) + } else if (env.MAVEN_DEPLOY_REPOSITORY) { + mvnCmd.withDeployRepository(env.MAVEN_DEPLOY_REPOSITORY) + } + + mvnCmd.skipTests(true).run('clean deploy') +} + +void runMavenStage() { + MavenStagingHelper stagingHelper = getStagingHelper() + deployProperties.putAll(stagingHelper.stageLocalArtifacts(env.NEXUS_STAGING_PROFILE_ID, getLocalDeploymentFolder())) + stagingHelper.promoteStagingRepository(env.NEXUS_BUILD_PROMOTION_PROFILE_ID) +} + +MavenStagingHelper getStagingHelper() { + return new MavenStagingHelper(this, getMavenCommand()) + .withNexusReleaseUrl(env.NEXUS_RELEASE_URL) + .withNexusReleaseRepositoryId(env.NEXUS_RELEASE_REPOSITORY_ID) +} + +String getLocalDeploymentFolder() { + return "${env.MAVEN_DEPLOY_LOCAL_DIR}/${getRepoName()}" +} + +boolean isStream8() { + return env.DROOLS_STREAM == '8' +} \ No newline at end of file diff --git a/.ci/jenkins/Jenkinsfile.promote b/.ci/jenkins/Jenkinsfile.promote new file mode 100644 index 0000000..cf61780 --- /dev/null +++ b/.ci/jenkins/Jenkinsfile.promote @@ -0,0 +1,182 @@ +import org.jenkinsci.plugins.workflow.libs.Library +@Library('jenkins-pipeline-shared-libraries')_ + +deployProperties = [:] + +pipeline { + agent { + label 'rhel8 && !built-in' + } + + tools { + maven env.BUILD_MAVEN_TOOL + jdk env.BUILD_JDK_TOOL + } + + options { + timestamps() + timeout(time: 180, unit: 'MINUTES') + } + + environment { + DROOLS_CI_EMAIL_TO = credentials("${JENKINS_EMAIL_CREDS_ID}") + } + + stages { + stage('Initialization') { + steps { + script { + cleanWs() + + if (params.DISPLAY_NAME != '') { + currentBuild.displayName = params.DISPLAY_NAME + } + + readDeployProperties() + + assert getProjectVersion() + assert getBuildBranch() == util.getReleaseBranchFromVersion(getProjectVersion()) + } + } + } + stage('Merge deploy PR and tag') { + steps { + script { + dir(getRepoName()) { + checkoutRepo() + mergeAndPush(getDeployPrLink()) + tagLatest() + } + } + } + } + + stage('Create release') { + steps { + script { + dir(getRepoName()) { + checkoutRepo() + if(githubscm.isReleaseExist(getGitTag(), getGitAuthorCredsID())) { + githubscm.deleteRelease(getGitTag(), getGitAuthorCredsID()) + } + githubscm.createReleaseWithGeneratedReleaseNotes(getGitTag(), getBuildBranch(), githubscm.getPreviousTagFromVersion(getGitTag()), getGitAuthorCredsID()) + githubscm.updateReleaseBody(getGitTag(), getGitAuthorCredsID()) + } + } + } + } + } + post { + unsuccessful { + sendNotification() + } + cleanup { + script { + util.cleanNode('docker') + } + } + } +} + +void sendNotification() { + if (params.SEND_NOTIFICATION) { + mailer.sendMarkdownTestSummaryNotification('Promote', "[${getBuildBranch()}] KIE jpmml integration", [env.DROOLS_CI_EMAIL_TO]) + } else { + echo 'No notification sent per configuration' + } +} + +////////////////////////////////////////////////////////////////////////////// +// Deployment properties +////////////////////////////////////////////////////////////////////////////// + +void readDeployProperties() { + String deployUrl = params.DEPLOY_BUILD_URL + if (deployUrl != '') { + if (!deployUrl.endsWith('/')) { + deployUrl += '/' + } + sh "wget ${deployUrl}artifact/${PROPERTIES_FILE_NAME} -O ${PROPERTIES_FILE_NAME}" + deployProperties = readProperties file: PROPERTIES_FILE_NAME + // echo all properties + echo deployProperties.collect { entry -> "${entry.key}=${entry.value}" }.join('\n') + } +} + +boolean hasDeployProperty(String key) { + return deployProperties[key] != null +} + +String getDeployProperty(String key) { + if (hasDeployProperty(key)) { + return deployProperties[key] + } + return '' +} + +String getParamOrDeployProperty(String paramKey, String deployPropertyKey) { + if (params[paramKey] != '') { + return params[paramKey] + } + return getDeployProperty(deployPropertyKey) +} + +////////////////////////////////////////////////////////////////////////////// +// Getter / Setter +////////////////////////////////////////////////////////////////////////////// + +String getRepoName() { + return env.REPO_NAME +} + +String getProjectVersion() { + return getParamOrDeployProperty('PROJECT_VERSION', 'project.version') +} + +String getGitTag() { + return params.GIT_TAG != '' ? params.GIT_TAG : getProjectVersion() +} + +String getBuildBranch() { + return params.BUILD_BRANCH_NAME +} + +String getGitAuthor() { + return env.GIT_AUTHOR +} + +String getGitAuthorCredsID() { + return env.AUTHOR_CREDS_ID +} + +String getDeployPrLink() { + return getDeployProperty("${getRepoName()}.pr.link") +} + +////////////////////////////////////////////////////////////////////////////// +// Git +////////////////////////////////////////////////////////////////////////////// + +void checkoutRepo() { + deleteDir() + checkout(githubscm.resolveRepository(getRepoName(), getGitAuthor(), getBuildBranch(), false)) + // need to manually checkout branch since on a detached branch after checkout command + sh "git checkout ${getBuildBranch()}" +} + +void mergeAndPush(String prLink) { + if (prLink) { + githubscm.mergePR(prLink, getGitAuthorCredsID()) + githubscm.pushObject('origin', getBuildBranch(), getGitAuthorCredsID()) + } +} + +void tagLatest() { + if (getGitTag()) { + githubscm.tagLocalAndRemoteRepository('origin', getGitTag(), getGitAuthorCredsID(), env.BUILD_TAG, true) + } +} + +boolean isStream8() { + return env.DROOLS_STREAM == '8' +} diff --git a/.ci/jenkins/Jenkinsfile.setup-branch b/.ci/jenkins/Jenkinsfile.setup-branch new file mode 100644 index 0000000..f4a6175 --- /dev/null +++ b/.ci/jenkins/Jenkinsfile.setup-branch @@ -0,0 +1,142 @@ +import org.jenkinsci.plugins.workflow.libs.Library +@Library('jenkins-pipeline-shared-libraries')_ + +import org.kie.jenkins.MavenCommand + +pipeline { + agent { + label 'kie-rhel8 && !built-in' + } + + tools { + maven env.BUILD_MAVEN_TOOL + jdk env.BUILD_JDK_TOOL + } + + options { + timestamps() + timeout(time: 60, unit: 'MINUTES') + } + + environment { + DROOLS_CI_EMAIL_TO = credentials("${JENKINS_EMAIL_CREDS_ID}") + MAVEN_OPTS = '-Xms1024m -Xmx4g' + } + + stages { + stage('Initialize') { + steps { + script { + cleanWs() + + if (params.DISPLAY_NAME) { + currentBuild.displayName = params.DISPLAY_NAME + } + dir(getRepoName()) { + checkoutRepo(getRepoName(), getBuildBranch()) + } + } + } + } + stage('Update project version') { + steps { + script { + dir(getRepoName()) { + maven.mvnVersionsUpdateParentAndChildModules(getMavenCommand(), getDroolsVersion(), !isRelease()) + } + } + } + } + stage('Update branch') { + steps { + script { + dir(getRepoName()) { + if (githubscm.isThereAnyChanges()) { + def commitMsg = "Update version to ${getDroolsVersion()}" + + githubscm.commitChanges(commitMsg, { + githubscm.findAndStageNotIgnoredFiles('pom.xml') + githubscm.findAndStageNotIgnoredFiles('antora.yml') + }) + githubscm.pushObject('origin', getBuildBranch(), getGitAuthorCredsId()) + } else { + println '[WARN] no changes to commit' + } + } + } + } + } + } + post { + unsuccessful { + sendNotification() + } + cleanup { + script { + util.cleanNode('docker') + } + } + } +} + +void sendNotification() { + if (params.SEND_NOTIFICATION) { + mailer.sendMarkdownTestSummaryNotification('Setup branch', "[${getBuildBranch()}] KIE jpmml integration", [env.DROOLS_CI_EMAIL_TO]) + } else { + echo 'No notification sent per configuration' + } +} + +void checkoutRepo(String repository, String branch) { + checkout(githubscm.resolveRepository(repository, getGitAuthor(), branch, false)) + // need to manually checkout branch since on a detached branch after checkout command + sh "git checkout ${branch}" +} + +String getRepoName() { + return env.REPO_NAME +} + +String getGitAuthor() { + // GIT_AUTHOR can be env or param + return "${GIT_AUTHOR}" +} + +String getBuildBranch() { + return params.BUILD_BRANCH_NAME +} + +String getDroolsVersion() { + return params.DROOLS_VERSION +} + +String getGitAuthorCredsId() { + return env.AUTHOR_CREDS_ID +} + +MavenCommand getMavenCommand() { + return new MavenCommand(this, ['-fae', '-ntp']) + .withSettingsXmlId(env.MAVEN_SETTINGS_CONFIG_FILE_ID) +} + +boolean isMainBranch() { + return env.IS_MAIN_BRANCH ? env.IS_MAIN_BRANCH.toBoolean() : false +} + +String commitAndCreatePR(String commitMsg, String localBranch, String targetBranch) { + def prBody = "Generated by build ${BUILD_TAG}: ${BUILD_URL}" + githubscm.commitChanges(commitMsg) + githubscm.pushObject('origin', localBranch, getGitAuthorCredsId()) + return githubscm.createPR(commitMsg, prBody, targetBranch, getGitAuthorCredsId()) +} + +void mergeAndPush(String prLink, String targetBranch) { + if (prLink?.trim()) { + githubscm.mergePR(prLink, getGitAuthorCredsId()) + githubscm.pushObject('origin', targetBranch, getGitAuthorCredsId()) + } +} + +boolean isStream8() { + return env.DROOLS_STREAM == '8' +} diff --git a/.ci/jenkins/dsl/jobs.groovy b/.ci/jenkins/dsl/jobs.groovy new file mode 100644 index 0000000..8631303 --- /dev/null +++ b/.ci/jenkins/dsl/jobs.groovy @@ -0,0 +1,238 @@ +/* +* This file is describing all the Jenkins jobs in the DSL format (see https://plugins.jenkins.io/job-dsl/) +* needed by the Kogito pipelines. +* +* The main part of Jenkins job generation is defined into the https://github.com/kiegroup/kogito-pipelines repository. +* +* This file is making use of shared libraries defined in +* https://github.com/kiegroup/kogito-pipelines/tree/main/dsl/seed/src/main/groovy/org/kie/jenkins/jobdsl. +*/ + +import org.kie.jenkins.jobdsl.model.JenkinsFolder +import org.kie.jenkins.jobdsl.model.JobType +import org.kie.jenkins.jobdsl.utils.EnvUtils +import org.kie.jenkins.jobdsl.utils.JobParamsUtils +import org.kie.jenkins.jobdsl.KogitoJobTemplate +import org.kie.jenkins.jobdsl.KogitoJobUtils +import org.kie.jenkins.jobdsl.Utils + +jenkins_path = '.ci/jenkins' + +String getStream() { + String gitMainBranch = "${GIT_MAIN_BRANCH}" + if (gitMainBranch == 'main') { + return '8' + } else { + return gitMainBranch.split("\\.")[0] + } +} + +Map getMultijobPRConfig(JenkinsFolder jobFolder) { + def jobConfig = [ + parallel: true, + buildchain: true, + jobs : [ + [ + id: 'kie-jpmml-integration', + primary: true, + env : [ + // Sonarcloud analysis only on main branch + // As we have only Community edition + ENABLE_SONARCLOUD: EnvUtils.isDefaultEnvironment(this, jobFolder.getEnvironmentName()) && Utils.isMainBranch(this), + ] + ] + ] + ] + + // TODO to enable once Quarkus 3 migration is needed + // For Quarkus 3, run only kie-jpmml-integration PR check... for now + // if (EnvUtils.hasEnvironmentId(this, jobFolder.getEnvironmentName(), 'quarkus3')) { + // jobConfig.jobs.retainAll { it.id == 'kie-jpmml-integration' } + // } + + return jobConfig +} + +// PR checks +KogitoJobUtils.createAllEnvironmentsPerRepoPRJobs(this) { jobFolder -> getMultijobPRConfig(jobFolder) } + +// Init branch +createSetupBranchJob() + +// Nightly jobs +KogitoJobUtils.createNightlyBuildChainBuildAndDeployJobForCurrentRepo(this, '', true) + +// Environment nightlies +setupSpecificBuildChainNightlyJob('native') +setupSpecificBuildChainNightlyJob('sonarcloud') + +// Jobs with integration branch +setupQuarkusIntegrationJob('quarkus-main') +setupQuarkusIntegrationJob('quarkus-branch') +setupQuarkusIntegrationJob('quarkus-lts') +setupQuarkusIntegrationJob('native-lts') +// Quarkus 3 nightly is exported to Kogito pipelines for easier integration + +// Release jobs +setupDeployJob(JobType.RELEASE) +setupPromoteJob(JobType.RELEASE) + +// TODO to enable once Quarkus 3 migration is needed +// Quarkus 3 +// if (EnvUtils.isEnvironmentEnabled(this, 'quarkus-3')) { +// setupPrQuarkus3RewriteJob() +// setupStandaloneQuarkus3RewriteJob() +// } + +///////////////////////////////////////////////////////////////// +// Methods +///////////////////////////////////////////////////////////////// + +void setupQuarkusIntegrationJob(String envName, Closure defaultJobParamsGetter = JobParamsUtils.DEFAULT_PARAMS_GETTER) { + KogitoJobUtils.createNightlyBuildChainIntegrationJob(this, envName, Utils.getRepoName(this), true, defaultJobParamsGetter) +} + +void setupSpecificBuildChainNightlyJob(String envName, Closure defaultJobParamsGetter = JobParamsUtils.DEFAULT_PARAMS_GETTER) { + KogitoJobUtils.createNightlyBuildChainBuildAndTestJobForCurrentRepo(this, envName, true, defaultJobParamsGetter) +} + +void createSetupBranchJob() { + def jobParams = JobParamsUtils.getBasicJobParams(this, 'kie-jpmml-integration', JobType.SETUP_BRANCH, "${jenkins_path}/Jenkinsfile.setup-branch", 'KIE jpmml integration Setup branch') + JobParamsUtils.setupJobParamsDefaultMavenConfiguration(this, jobParams) + jobParams.env.putAll([ + JENKINS_EMAIL_CREDS_ID: "${JENKINS_EMAIL_CREDS_ID}", + + GIT_AUTHOR: "${GIT_AUTHOR_NAME}", + AUTHOR_CREDS_ID: "${GIT_AUTHOR_CREDENTIALS_ID}", + + MAVEN_SETTINGS_CONFIG_FILE_ID: "${MAVEN_SETTINGS_FILE_ID}", + + IS_MAIN_BRANCH: "${Utils.isMainBranch(this)}", + DROOLS_STREAM: getStream(), + ]) + KogitoJobTemplate.createPipelineJob(this, jobParams)?.with { + parameters { + stringParam('DISPLAY_NAME', '', 'Setup a specific build display name') + + stringParam('BUILD_BRANCH_NAME', "${GIT_BRANCH}", 'Set the Git branch to checkout') + + stringParam('DROOLS_VERSION', '', 'Drools version to set.') + + booleanParam('SEND_NOTIFICATION', false, 'In case you want the pipeline to send a notification on CI channel for this run.') + } + } +} + +void setupDeployJob(JobType jobType) { + def jobParams = JobParamsUtils.getBasicJobParams(this, 'kie-jpmml-integration-deploy', jobType, "${jenkins_path}/Jenkinsfile.deploy", 'KIE jpmml integration Deploy') + JobParamsUtils.setupJobParamsDefaultMavenConfiguration(this, jobParams) + jobParams.env.putAll([ + PROPERTIES_FILE_NAME: 'deployment.properties', + JENKINS_EMAIL_CREDS_ID: "${JENKINS_EMAIL_CREDS_ID}", + + GIT_AUTHOR: "${GIT_AUTHOR_NAME}", + AUTHOR_CREDS_ID: "${GIT_AUTHOR_CREDENTIALS_ID}", + GITHUB_TOKEN_CREDS_ID: "${GIT_AUTHOR_TOKEN_CREDENTIALS_ID}", + + MAVEN_SETTINGS_CONFIG_FILE_ID: "${MAVEN_SETTINGS_FILE_ID}", + MAVEN_DEPENDENCIES_REPOSITORY: "${MAVEN_ARTIFACTS_REPOSITORY}", + MAVEN_DEPLOY_REPOSITORY: "${MAVEN_ARTIFACTS_UPLOAD_REPOSITORY_URL}", + MAVEN_REPO_CREDS_ID: "${MAVEN_ARTIFACTS_UPLOAD_REPOSITORY_CREDS_ID}", + + DROOLS_STREAM: getStream(), + ]) + if (jobType == JobType.RELEASE) { + jobParams.env.putAll([ + NEXUS_RELEASE_URL: "${MAVEN_NEXUS_RELEASE_URL}", + NEXUS_RELEASE_REPOSITORY_ID: "${MAVEN_NEXUS_RELEASE_REPOSITORY}", + NEXUS_STAGING_PROFILE_ID: "${MAVEN_NEXUS_STAGING_PROFILE_ID}", + NEXUS_BUILD_PROMOTION_PROFILE_ID: "${MAVEN_NEXUS_BUILD_PROMOTION_PROFILE_ID}", + ]) + } + KogitoJobTemplate.createPipelineJob(this, jobParams)?.with { + parameters { + stringParam('DISPLAY_NAME', '', 'Setup a specific build display name') + + stringParam('BUILD_BRANCH_NAME', "${GIT_BRANCH}", 'Set the Git branch to checkout') + + booleanParam('SKIP_TESTS', false, 'Skip tests') + + booleanParam('CREATE_PR', false, 'Should we create a PR with the changes ?') + stringParam('PROJECT_VERSION', '', 'Optional if not RELEASE. If RELEASE, cannot be empty.') + stringParam('DROOLS_PR_BRANCH', '', 'PR branch name') + + booleanParam('SEND_NOTIFICATION', false, 'In case you want the pipeline to send a notification on CI channel for this run.') + } + } +} + +void setupPromoteJob(JobType jobType) { + def jobParams = JobParamsUtils.getBasicJobParams(this, 'kie-jpmml-integration-promote', jobType, "${jenkins_path}/Jenkinsfile.promote", 'KIE jpmml integration Promote') + JobParamsUtils.setupJobParamsDefaultMavenConfiguration(this, jobParams) + jobParams.env.putAll([ + PROPERTIES_FILE_NAME: 'deployment.properties', + JENKINS_EMAIL_CREDS_ID: "${JENKINS_EMAIL_CREDS_ID}", + + GIT_AUTHOR: "${GIT_AUTHOR_NAME}", + AUTHOR_CREDS_ID: "${GIT_AUTHOR_CREDENTIALS_ID}", + GITHUB_TOKEN_CREDS_ID: "${GIT_AUTHOR_TOKEN_CREDENTIALS_ID}", + + MAVEN_SETTINGS_CONFIG_FILE_ID: "${MAVEN_SETTINGS_FILE_ID}", + MAVEN_DEPENDENCIES_REPOSITORY: "${MAVEN_ARTIFACTS_REPOSITORY}", + MAVEN_DEPLOY_REPOSITORY: "${MAVEN_ARTIFACTS_REPOSITORY}", + + DROOLS_STREAM: getStream(), + ]) + KogitoJobTemplate.createPipelineJob(this, jobParams)?.with { + parameters { + stringParam('DISPLAY_NAME', '', 'Setup a specific build display name') + stringParam('BUILD_BRANCH_NAME', "${GIT_BRANCH}", 'Set the Git branch to checkout') + // Deploy job url to retrieve deployment.properties + stringParam('DEPLOY_BUILD_URL', '', 'URL to jenkins deploy build to retrieve the `deployment.properties` file. If base parameters are defined, they will override the `deployment.properties` information') + // Release information which can override `deployment.properties` + stringParam('PROJECT_VERSION', '', 'Override `deployment.properties`. Optional if not RELEASE. If RELEASE, cannot be empty.') + stringParam('GIT_TAG', '', 'Git tag to set, if different from PROJECT_VERSION') + booleanParam('SEND_NOTIFICATION', false, 'In case you want the pipeline to send a notification on CI channel for this run.') + } + } +} + +// TODO to enable once Quarkus 3 migration is needed +void setupPrQuarkus3RewriteJob() { + def jobParams = JobParamsUtils.getBasicJobParamsWithEnv(this, 'kie-jpmml-integration.rewrite', JobType.PULL_REQUEST, 'quarkus-3', "${jenkins_path}/Jenkinsfile.quarkus-3.rewrite.pr", 'KIE jpmml integration Quarkus 3 rewrite patch regeneration') + JobParamsUtils.setupJobParamsDefaultMavenConfiguration(this, jobParams) + jobParams.jenkinsfile = "${jenkins_path}/Jenkinsfile.quarkus-3.rewrite.pr" + jobParams.pr.putAll([ + run_only_for_branches: [ "${GIT_BRANCH}" ], + disable_status_message_error: true, + disable_status_message_failure: true, + trigger_phrase: '.*[j|J]enkins,?.*(rewrite|write) [Q|q]uarkus-3.*', + trigger_phrase_only: true, + commitContext: 'Quarkus 3 rewrite', + ]) + jobParams.env.putAll([ + AUTHOR_CREDS_ID: "${GIT_AUTHOR_CREDENTIALS_ID}", + MAVEN_SETTINGS_CONFIG_FILE_ID: "${MAVEN_SETTINGS_FILE_ID}", + ]) + KogitoJobTemplate.createPRJob(this, jobParams) +} + +void setupStandaloneQuarkus3RewriteJob() { + def jobParams = JobParamsUtils.getBasicJobParams(this, 'kie-jpmml-integration.quarkus-3.rewrite', JobType.TOOLS, "${jenkins_path}/Jenkinsfile.quarkus-3.rewrite.standalone", 'KIE jpmml integration Quarkus 3 rewrite patch regeneration') + JobParamsUtils.setupJobParamsDefaultMavenConfiguration(this, jobParams) + jobParams.env.putAll(EnvUtils.getEnvironmentEnvVars(this, 'quarkus-3')) + jobParams.env.putAll([ + AUTHOR_CREDS_ID: "${GIT_AUTHOR_CREDENTIALS_ID}", + JENKINS_EMAIL_CREDS_ID: "${JENKINS_EMAIL_CREDS_ID}", + MAVEN_SETTINGS_CONFIG_FILE_ID: "${MAVEN_SETTINGS_FILE_ID}", + ]) + KogitoJobTemplate.createPipelineJob(this, jobParams)?.with { + parameters { + stringParam('DISPLAY_NAME', '', 'Setup a specific build display name') + stringParam('GIT_AUTHOR', "${GIT_AUTHOR_NAME}", 'Set the Git author to checkout') + stringParam('BUILD_BRANCH_NAME', "${GIT_BRANCH}", 'Set the Git branch to checkout') + booleanParam('IS_PR_SOURCE_BRANCH', false, 'Set to true if you are launching the job for a PR source branch') + booleanParam('SEND_NOTIFICATION', false, 'In case you want the pipeline to send a notification on CI channel for this run.') + } + } +} \ No newline at end of file diff --git a/.ci/jenkins/dsl/test.sh b/.ci/jenkins/dsl/test.sh new file mode 100755 index 0000000..054bc9b --- /dev/null +++ b/.ci/jenkins/dsl/test.sh @@ -0,0 +1,34 @@ +#!/bin/bash -e + +# Used to retrieve current git author, to set correctly the main config file repo +GIT_SERVER='github.com' + +git_url=$(git remote -v | grep origin | awk -F' ' '{print $2}' | head -n 1) +if [ -z "${git_url}" ]; then + echo "Script must be executed in a Git repository for this script to run correctly" + exit 1 +fi +echo "git_url = ${git_url}" + +git_server_url= +if [[ "${git_url}" = https://* ]]; then + git_server_url="https://${GIT_SERVER}/" +elif [[ "${git_url}" = git@* ]]; then + git_server_url="git@${GIT_SERVER}:" +else + echo "Unknown protocol for url ${git_url}" + exit 1 +fi + +git_author="$(echo ${git_url} | awk -F"${git_server_url}" '{print $2}' | awk -F. '{print $1}' | awk -F/ '{print $1}')" + +export DSL_DEFAULT_MAIN_CONFIG_FILE_REPO="${git_author}"/drools +export DSL_DEFAULT_FALLBACK_MAIN_CONFIG_FILE_REPO=kiegroup/drools +export DSL_DEFAULT_MAIN_CONFIG_FILE_PATH=.ci/jenkins/config/main.yaml +export DSL_DEFAULT_BRANCH_CONFIG_FILE_REPO="${git_author}"/drools + +file=$(mktemp) +# For more usage of the script, use ./test.sh -h +curl -o ${file} https://raw.githubusercontent.com/kiegroup/kogito-pipelines/main/dsl/seed/scripts/seed_test.sh +chmod u+x ${file} +${file} $@ \ No newline at end of file diff --git a/.github/workflows/pr-backporting.yml b/.github/workflows/pr-backporting.yml index 8d6e515..62b31d5 100644 --- a/.github/workflows/pr-backporting.yml +++ b/.github/workflows/pr-backporting.yml @@ -3,9 +3,6 @@ name: Pull Request Backporting on: pull_request_target: types: [closed, labeled] - branches: - - main - env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -32,7 +29,7 @@ jobs: strategy: matrix: target-branch: ${{ fromJSON(needs.compute-targets.outputs.target-branches) }} - fail-fast: true + fail-fast: false env: REVIEWERS: ${{ toJSON(github.event.pull_request.requested_reviewers) }} steps: diff --git a/.github/workflows/pr-jenkins.yml b/.github/workflows/pr-jenkins.yml new file mode 100644 index 0000000..4d6af63 --- /dev/null +++ b/.github/workflows/pr-jenkins.yml @@ -0,0 +1,24 @@ +# This workflow will build a Java project with Maven +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven +name: Jenkins Tests +on: + pull_request: + paths: + - '.ci/jenkins/**' + - '.github/workflows/jenkins-tests-PR.yml' + +jobs: + dsl-tests: + concurrency: + group: ${{ github.repository.name }}_dsl_tests-${{ github.head_ref }} + cancel-in-progress: true + runs-on: ubuntu-latest + name: DSL + steps: + - name: DSL tests + uses: kiegroup/kie-ci/.ci/actions/dsl-tests@main + with: + project: kie-jpmml-integration + main-config-file-repo: kiegroup/drools + main-config-file-path: .ci/jenkins/config/main.yaml + branch-config-file-repo: kiegroup/drools diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pr.yml similarity index 58% rename from .github/workflows/pull_request.yml rename to .github/workflows/pr.yml index fdc694f..556619a 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pr.yml @@ -1,28 +1,35 @@ -name: Build Chain +name: KIE jpmml integration on: pull_request: types: [opened, synchronize, reopened, ready_for_review] paths-ignore: - - 'LICENSE*' - - '.gitignore' - - '*.md' + - 'LICENSE' + - '**/.gitignore' + - '**.md' + - '**.adoc' - '*.txt' + - 'docsimg/**' + - '.ci/jenkins/**' jobs: - build-chain: + kie-jpmml-integration-build: concurrency: - group: pull_request-${{ github.head_ref }}-${{ matrix.os }}-${{ matrix.java-version }} + group: pr-kie-jpmml-integration-build_${{ matrix.os }}_${{ matrix.java-version }}_${{ matrix.maven-version }}_${{ github.head_ref }} cancel-in-progress: true + timeout-minutes: 120 strategy: matrix: - os: [ubuntu-latest, windows-latest] - java-version: [8, 11] - maven-version: ['3.8.1'] + os: [ubuntu-latest] # TODO do we want windows here ? + java-version: [11] + maven-version: ['3.8.7'] fail-fast: false runs-on: ${{ matrix.os }} - name: ${{ matrix.os }} - Java ${{ matrix.java-version }} - Maven + name: ${{ matrix.os }} / Java-${{ matrix.java-version }} / Maven-${{ matrix.maven-version }} steps: + - name: Clean Disk Space + uses: kiegroup/kie-ci/.ci/actions/ubuntu-disk-space@main + if: ${{ matrix.os == 'ubuntu-latest' }} - name: Support long paths if: ${{ matrix.os == 'windows-latest' }} uses: kiegroup/kie-ci/.ci/actions/long-paths@main @@ -35,9 +42,11 @@ jobs: - name: Build Chain uses: kiegroup/kie-ci/.ci/actions/build-chain@main with: - definition-file: https://raw.githubusercontent.com/${GROUP:kiegroup}/droolsjbpm-build-bootstrap/${BRANCH:main}/.ci/pull-request-config.yaml + definition-file: https://raw.githubusercontent.com/${GROUP:kiegroup}/drools/${BRANCH:main}/.ci/buildchain-config.yaml annotations-prefix: ${{ runner.os }}-${{ matrix.java-version }}/${{ matrix.maven-version }} github-token: "${{ secrets.GITHUB_TOKEN }}" - name: Surefire Report uses: kiegroup/kie-ci/.ci/actions/surefire-report@main if: ${{ always() }} + with: + report_paths: '**/*-reports/TEST-*.xml' diff --git a/.gitignore b/.gitignore index 49d18e7..d36b772 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ bin # Eclipse, Netbeans and IntelliJ files /.* !.gitignore +!.ci +!.github /nbproject /*.ipr /*.iws