diff --git a/Jenkinsfile-dev-build b/Jenkinsfile-dev-build new file mode 100644 index 000000000..b4536588f --- /dev/null +++ b/Jenkinsfile-dev-build @@ -0,0 +1,278 @@ +node("docker-ubuntu20-xlarge") { + properties([ + pipelineTriggers([ + cron('H 0 * * *') + ]) + ]) + try { + stage('Setup Environment and Tools') { + def goRoot = tool name: 'go-1.23.9', type: 'go' + withEnv(["GOROOT=${goRoot}", "PATH+GO=${goRoot}/bin"]) { + withCredentials([string(credentialsId: 'repo21-url', variable: 'REPO21_URL')]) { + echo "${REPO21_URL}" + def repo21Name = "${REPO21_URL}".substring(8, "${REPO21_URL}".length()) + env.REPO_NAME_21 = "$repo21Name" + } + def architectures = [ + [pkg: 'jfrog-cli-windows-amd64', goos: 'windows', goarch: 'amd64', fileExtension: '.exe', chocoImage: '${REPO_NAME_21}/jfrog-docker/linuturk/mono-choco'], + [pkg: 'jfrog-cli-linux-386', goos: 'linux', goarch: '386', fileExtension: '', debianImage: '${REPO_NAME_21}/jfrog-docker/i386/ubuntu:20.04', debianArch: 'i386'], + [pkg: 'jfrog-cli-linux-amd64', goos: 'linux', goarch: 'amd64', fileExtension: '', debianImage: '${REPO_NAME_21}/jfrog-docker/ubuntu:20.04', debianArch: 'x86_64', rpmImage: 'almalinux:8.10'], + [pkg: 'jfrog-cli-linux-arm64', goos: 'linux', goarch: 'arm64', fileExtension: ''], + [pkg: 'jfrog-cli-linux-arm', goos: 'linux', goarch: 'arm', fileExtension: ''], + [pkg: 'jfrog-cli-mac-386', goos: 'darwin', goarch: 'amd64', fileExtension: ''], + [pkg: 'jfrog-cli-mac-arm64', goos: 'darwin', goarch: 'arm64', fileExtension: ''], + [pkg: 'jfrog-cli-linux-s390x', goos: 'linux', goarch: 's390x', fileExtension: ''], + [pkg: 'jfrog-cli-linux-ppc64', goos: 'linux', goarch: 'ppc64', fileExtension: ''], + [pkg: 'jfrog-cli-linux-ppc64le', goos: 'linux', goarch: 'ppc64le', fileExtension: ''] + ] + identifier = 'v2' + cliExecutableName = 'jfrog' + devBranch = "dev" + devRepo = "https://github.com/jfrog/jfrog-cli.git" + buildStatus = 'SUCCESS' + repo = 'jfrog-cli' + env.CI = true + env.JFROG_CLI_LOG_LEVEL = "DEBUG" + dir('temp') { + sh "cat /etc/lsb-release" + cliWorkspace = pwd() + sh "echo cliWorkspace=$cliWorkspace" + builderDir = "${cliExecutableName}-builder/" + sh "mkdir $builderDir" + builderPath = "${cliWorkspace}/${builderDir}${cliExecutableName}" + jfrogCliRepoDir = "${cliWorkspace}/${repo}/" + repoDeployName = env.CLI_DEV_REPO_DEPLOY_NAME + repoResolveName = env.CLI_DEV_REPO_RESOLVE_NAME + repoDeployId = env.REPO_DEPLOY_ID + repoResolveId = env.REPO_RESOLVE_ID + artifactoryNameToUpload = env.REPO_FOR_CLI_DEV_UPLOAD + project = env.PROJECT + slackChannelName = env.SLACK_CHANNEL_FOR_CLI_DEV_BUILD_NOTIFICATION + buildNumber = env.BUILD_NUMBER + buildName = "jfrog-cli-dev-build" + stage('Clone Source Repo') { + try { + dir("${cliWorkspace}") { + sh "git clone ${devRepo}" + dir("${repo}") { + sh "git checkout ${devBranch}" + } + } + } + catch (e) { + notifyFailure('Clone Source Repo', e) + throw e + } + } + stage('Build JFrog CLI') { + try { + sh 'go version' + dir("$jfrogCliRepoDir") { + sh "build/build.sh $cliExecutableName" + } + sh "mv $jfrogCliRepoDir/$cliExecutableName $builderDir" + version = getCliVersion(builderPath) + print "CLI version: $version" + version = getCLINextVersion(version) + "-beta" + print "Next CLI version: $version" + } + catch (e) { + notifyFailure('Build JFrog CLI', e) + throw e + } + } + stage('Setting JF-Config') { + try { + setJfConfigure() + } + catch (e) { + notifyFailure('Setting JF-Config', e) + throw e + } + } + stage('jf build and upload binaries phase') { + try { + buildAndUploadBinaryAndBuildInfo(architectures) + } + catch (e) { + notifyFailure('jf build and upload binaries phase', e) + throw e + } + } + } + } + } + } catch (e) { + echo "ERROR: Pipeline failed with exception: ${e}" + buildStatus = 'FAILURE' + throw e + } + finally { + stage('Send Notifications') { + message = '' + if (buildStatus == 'SUCCESS') { + message = "Dev Build Jenkins Pipeline for Jfrog-CLI has successfully completed.\n<${env.BUILD_URL}|View Build>" + slackSend(channel: "#${slackChannelName}", message: message, color: 'good') + } else { + message = """@here Dev Build Jenkins Pipeline has a problem. + *Status* : *${buildStatus}*. + *Build* : <${env.BUILD_URL}|${env.JOB_NAME} #${env.BUILD_NUMBER}> + """ + slackSend(channel: "#${slackChannelName}", message: message, color: 'danger') + } + echo "Final notification message would be: \n${message}" + } + } +} + +def notifyFailure(String stageName, error) { + def message = """@here :x: *Build FAILED!* + *Job:* `${env.JOB_NAME}` #${env.BUILD_NUMBER} + *Failed Stage:* `${stageName}` + *Error:* `${error.message.trim()}` + *<${env.BUILD_URL}|Open Build Log>*""" + echo "Sending failure notification for stage: ${stageName}" + slackSend( + channel: "#${slackChannelName}", + color: 'danger', + message: message + ) +} + +def setJfConfigure() { + sh """#!/bin/bash + $builderPath go-config --repo-deploy ${repoDeployName} --repo-resolve ${repoResolveName} --server-id-deploy ${repoDeployId} --server-id-resolve ${repoResolveId} + """ +} + +def getCLINextVersion(String currentVersion) { + if (currentVersion.startsWith('v')) { + currentVersion = currentVersion.substring(1) + } + def parts = currentVersion.split('\\.') + if (parts.size() != 3) { + error("Invalid version format. Expected MAJOR.MINOR.PATCH, but got: ${currentVersion}") + } + def major = parts[0].toInteger() + def minor = parts[1].toInteger() + def patch = parts[2].toInteger() + minor++ + patch = 0 + def nextVersion = "${major}.${minor}.${patch}" + return nextVersion +} + +def getCliVersion(exePath) { + version = sh(script: "$exePath -v | tr -d 'jfrog version' | tr -d '\n'", returnStdout: true) + return version +} + +def buildAndUploadBinaryAndBuildInfo(architectures) { + configRepo21() + try { + makeBuildInfo() + uploadCliBinary(architectures) + uploadAndScanBuildInfo() + } finally { + cleanupRepo21() + } +} + +def configRepo21() { + withCredentials([ + // jfrog-ignore + usernamePassword(credentialsId: 'repo21', usernameVariable: 'REPO21_USER', passwordVariable: 'REPO21_PASSWORD'), + string(credentialsId: 'repo21-url', variable: 'REPO21_URL') + ]) { + sh """#!/bin/bash + $builderPath c add repo21 --url=$REPO21_URL --user=$REPO21_USER --password=$REPO21_PASSWORD --overwrite + $builderPath c use repo21 + """ + } +} + +def cleanupRepo21() { + sh """#!/bin/bash + $builderPath c rm repo21 + """ +} + +def uploadCliBinary(architectures) { + for (int i = 0; i < architectures.size(); i++) { + def currentBuild = architectures[i] + try { + stage("Build and upload ${currentBuild.pkg}") { + buildAndUpload(currentBuild.goos, currentBuild.goarch, currentBuild.pkg, currentBuild.fileExtension) + } + } + catch (e) { + notifyFailure('Build and upload ${currentBuild.pkg}', e) + throw e + } + } +} + +def uploadBinaryToJfrogRepo21(pkg, fileName) { + sh """#!/bin/bash + set -e + $builderPath rt u ${jfrogCliRepoDir}/${fileName} ${artifactoryNameToUpload}/dev/$identifier/$version/$pkg/ --build-name=${buildName} --build-number=${buildNumber} --project=${project} --fail-no-op --flat + echo Uploaded the binary here: ${artifactoryNameToUpload}/dev/$identifier/$version/$pkg/ + """ +} + +def makeBuildInfo() { + sh """#!/bin/bash + cd ${jfrogCliRepoDir} + $builderPath go build --build-name="${buildName}" --build-number="${buildNumber}" --project="${project}" + """ +} + +def uploadAndScanBuildInfo() { + try { + stage('Upload Build-Info') { + sh """#!/bin/bash + $builderPath rt build-publish "${buildName}" "${buildNumber}" --project=${project} + """ + } + } catch (e) { + notifyFailure('Upload Build-Info', e) + throw e + } + try { + stage('Scanning Build-Info') { + sh """#!/bin/bash + $builderPath build-scan "${buildName}" "${buildNumber}" --project ${project} + """ + } + } + catch (e) { + notifyFailure('Scanning Build-Info', e) + throw e + } + try { + stage("Scanning Binaries and artifacts under watch ecosystem-watch") { + sh "$builderPath scan '${jfrogCliRepoDir}' --watches 'ecosystem-watch'" + } + } + catch (e) { + notifyFailure('Scanning Binaries and artifacts under watch ecosystem-watch', e) + throw e + } +} + +def build(goos, goarch, pkg, fileName) { + dir("${jfrogCliRepoDir}") { + sh "pwd" + env.GOOS = "$goos" + env.GOARCH = "$goarch" + sh "build/build.sh $fileName" + } +} + +def buildAndUpload(goos, goarch, pkg, fileExtension) { + def extension = fileExtension == null ? '': fileExtension + def fileName = "$cliExecutableName$fileExtension" + build(goos, goarch, pkg, fileName) + uploadBinaryToJfrogRepo21(pkg, fileName) + sh "rm $jfrogCliRepoDir/$fileName" +} \ No newline at end of file