1
+ node("docker-ubuntu20-xlarge") {
2
+ properties([
3
+ pipelineTriggers([
4
+ cron('H 0 * * *')
5
+ ])
6
+ ])
7
+ try {
8
+ stage('Setup Environment and Tools') {
9
+ def goRoot = tool name: 'go-1.23.9', type: 'go'
10
+ withEnv(["GOROOT=${goRoot}", "PATH+GO=${goRoot}/bin"]) {
11
+ withCredentials([string(credentialsId: 'repo21-url', variable: 'REPO21_URL')]) {
12
+ echo "${REPO21_URL}"
13
+ def repo21Name = "${REPO21_URL}".substring(8, "${REPO21_URL}".length())
14
+ env.REPO_NAME_21 = "$repo21Name"
15
+ }
16
+ def architectures = [
17
+ [pkg: 'jfrog-cli-windows-amd64', goos: 'windows', goarch: 'amd64', fileExtension: '.exe', chocoImage: '${REPO_NAME_21}/jfrog-docker/linuturk/mono-choco'],
18
+ [pkg: 'jfrog-cli-linux-386', goos: 'linux', goarch: '386', fileExtension: '', debianImage: '${REPO_NAME_21}/jfrog-docker/i386/ubuntu:20.04', debianArch: 'i386'],
19
+ [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'],
20
+ [pkg: 'jfrog-cli-linux-arm64', goos: 'linux', goarch: 'arm64', fileExtension: ''],
21
+ [pkg: 'jfrog-cli-linux-arm', goos: 'linux', goarch: 'arm', fileExtension: ''],
22
+ [pkg: 'jfrog-cli-mac-386', goos: 'darwin', goarch: 'amd64', fileExtension: ''],
23
+ [pkg: 'jfrog-cli-mac-arm64', goos: 'darwin', goarch: 'arm64', fileExtension: ''],
24
+ [pkg: 'jfrog-cli-linux-s390x', goos: 'linux', goarch: 's390x', fileExtension: ''],
25
+ [pkg: 'jfrog-cli-linux-ppc64', goos: 'linux', goarch: 'ppc64', fileExtension: ''],
26
+ [pkg: 'jfrog-cli-linux-ppc64le', goos: 'linux', goarch: 'ppc64le', fileExtension: '']
27
+ ]
28
+ identifier = 'v2'
29
+ cliExecutableName = 'jfrog'
30
+ devBranch = "dev"
31
+ devRepo = "https://github.com/jfrog/jfrog-cli.git"
32
+ buildStatus = 'SUCCESS'
33
+ repo = 'jfrog-cli'
34
+ env.CI = true
35
+ env.JFROG_CLI_LOG_LEVEL = "DEBUG"
36
+ dir('temp') {
37
+ sh "cat /etc/lsb-release"
38
+ cliWorkspace = pwd()
39
+ sh "echo cliWorkspace=$cliWorkspace"
40
+ builderDir = "${cliExecutableName}-builder/"
41
+ sh "mkdir $builderDir"
42
+ builderPath = "${cliWorkspace}/${builderDir}${cliExecutableName}"
43
+ jfrogCliRepoDir = "${cliWorkspace}/${repo}/"
44
+ repoDeployName = env.CLI_DEV_REPO_DEPLOY_NAME
45
+ repoResolveName = env.CLI_DEV_REPO_RESOLVE_NAME
46
+ repoDeployId = env.REPO_DEPLOY_ID
47
+ repoResolveId = env.REPO_RESOLVE_ID
48
+ artifactoryNameToUpload = env.REPO_FOR_CLI_DEV_UPLOAD
49
+ project = env.PROJECT
50
+ slackChannelName = env.SLACK_CHANNEL_FOR_CLI_DEV_BUILD_NOTIFICATION
51
+ buildNumber = env.BUILD_NUMBER
52
+ buildName = "jfrog-cli-dev-build"
53
+ stage('Clone Source Repo') {
54
+ try {
55
+ dir("${cliWorkspace}") {
56
+ sh "git clone ${devRepo}"
57
+ dir("${repo}") {
58
+ sh "git checkout ${devBranch}"
59
+ }
60
+ }
61
+ }
62
+ catch (e) {
63
+ notifyFailure('Clone Source Repo', e)
64
+ throw e
65
+ }
66
+ }
67
+ stage('Build JFrog CLI') {
68
+ try {
69
+ sh 'go version'
70
+ dir("$jfrogCliRepoDir") {
71
+ sh "build/build.sh $cliExecutableName"
72
+ }
73
+ sh "mv $jfrogCliRepoDir/$cliExecutableName $builderDir"
74
+ version = getCliVersion(builderPath)
75
+ print "CLI version: $version"
76
+ version = getCLINextVersion(version) + "-beta"
77
+ print "Next CLI version: $version"
78
+ }
79
+ catch (e) {
80
+ notifyFailure('Build JFrog CLI', e)
81
+ throw e
82
+ }
83
+ }
84
+ stage('Setting JF-Config') {
85
+ try {
86
+ setJfConfigure()
87
+ }
88
+ catch (e) {
89
+ notifyFailure('Setting JF-Config', e)
90
+ throw e
91
+ }
92
+ }
93
+ stage('jf build and upload binaries phase') {
94
+ try {
95
+ buildAndUploadBinaryAndBuildInfo(architectures)
96
+ }
97
+ catch (e) {
98
+ notifyFailure('jf build and upload binaries phase', e)
99
+ throw e
100
+ }
101
+ }
102
+ }
103
+ }
104
+ }
105
+ } catch (e) {
106
+ echo "ERROR: Pipeline failed with exception: ${e}"
107
+ buildStatus = 'FAILURE'
108
+ throw e
109
+ }
110
+ finally {
111
+ stage('Send Notifications') {
112
+ message = ''
113
+ if (buildStatus == 'SUCCESS') {
114
+ message = "Dev Build Jenkins Pipeline for Jfrog-CLI has successfully completed.\n<${env.BUILD_URL}|View Build>"
115
+ slackSend(channel: "#${slackChannelName}", message: message, color: 'good')
116
+ } else {
117
+ message = """@here Dev Build Jenkins Pipeline has a problem.
118
+ *Status* : *${buildStatus}*.
119
+ *Build* : <${env.BUILD_URL}|${env.JOB_NAME} #${env.BUILD_NUMBER}>
120
+ """
121
+ slackSend(channel: "#${slackChannelName}", message: message, color: 'danger')
122
+ }
123
+ echo "Final notification message would be: \n${message}"
124
+ }
125
+ }
126
+ }
127
+
128
+ def notifyFailure(String stageName, error) {
129
+ def message = """@here :x: *Build FAILED!*
130
+ *Job:* `${env.JOB_NAME}` #${env.BUILD_NUMBER}
131
+ *Failed Stage:* `${stageName}`
132
+ *Error:* `${error.message.trim()}`
133
+ *<${env.BUILD_URL}|Open Build Log>*"""
134
+ echo "Sending failure notification for stage: ${stageName}"
135
+ slackSend(
136
+ channel: "#${slackChannelName}",
137
+ color: 'danger',
138
+ message: message
139
+ )
140
+ }
141
+
142
+ def setJfConfigure() {
143
+ sh """#!/bin/bash
144
+ $builderPath go-config --repo-deploy ${repoDeployName} --repo-resolve ${repoResolveName} --server-id-deploy ${repoDeployId} --server-id-resolve ${repoResolveId}
145
+ """
146
+ }
147
+
148
+ def getCLINextVersion(String currentVersion) {
149
+ if (currentVersion.startsWith('v')) {
150
+ currentVersion = currentVersion.substring(1)
151
+ }
152
+ def parts = currentVersion.split('\\.')
153
+ if (parts.size() != 3) {
154
+ error("Invalid version format. Expected MAJOR.MINOR.PATCH, but got: ${currentVersion}")
155
+ }
156
+ def major = parts[0].toInteger()
157
+ def minor = parts[1].toInteger()
158
+ def patch = parts[2].toInteger()
159
+ minor++
160
+ patch = 0
161
+ def nextVersion = "${major}.${minor}.${patch}"
162
+ return nextVersion
163
+ }
164
+
165
+ def getCliVersion(exePath) {
166
+ version = sh(script: "$exePath -v | tr -d 'jfrog version' | tr -d '\n'", returnStdout: true)
167
+ return version
168
+ }
169
+
170
+ def buildAndUploadBinaryAndBuildInfo(architectures) {
171
+ configRepo21()
172
+ try {
173
+ makeBuildInfo()
174
+ uploadCliBinary(architectures)
175
+ uploadAndScanBuildInfo()
176
+ } finally {
177
+ cleanupRepo21()
178
+ }
179
+ }
180
+
181
+ def configRepo21() {
182
+ withCredentials([
183
+ // jfrog-ignore
184
+ usernamePassword(credentialsId: 'repo21', usernameVariable: 'REPO21_USER', passwordVariable: 'REPO21_PASSWORD'),
185
+ string(credentialsId: 'repo21-url', variable: 'REPO21_URL')
186
+ ]) {
187
+ sh """#!/bin/bash
188
+ $builderPath c add repo21 --url=$REPO21_URL --user=$REPO21_USER --password=$REPO21_PASSWORD --overwrite
189
+ $builderPath c use repo21
190
+ """
191
+ }
192
+ }
193
+
194
+ def cleanupRepo21() {
195
+ sh """#!/bin/bash
196
+ $builderPath c rm repo21
197
+ """
198
+ }
199
+
200
+ def uploadCliBinary(architectures) {
201
+ for (int i = 0; i < architectures.size(); i++) {
202
+ def currentBuild = architectures[i]
203
+ try {
204
+ stage("Build and upload ${currentBuild.pkg}") {
205
+ buildAndUpload(currentBuild.goos, currentBuild.goarch, currentBuild.pkg, currentBuild.fileExtension)
206
+ }
207
+ }
208
+ catch (e) {
209
+ notifyFailure('Build and upload ${currentBuild.pkg}', e)
210
+ throw e
211
+ }
212
+ }
213
+ }
214
+
215
+ def uploadBinaryToJfrogRepo21(pkg, fileName) {
216
+ sh """#!/bin/bash
217
+ set -e
218
+ $builderPath rt u ${jfrogCliRepoDir}/${fileName} ${artifactoryNameToUpload}/dev/$identifier/$version/$pkg/ --build-name=${buildName} --build-number=${buildNumber} --project=${project} --fail-no-op --flat
219
+ echo Uploaded the binary here: ${artifactoryNameToUpload}/dev/$identifier/$version/$pkg/
220
+ """
221
+ }
222
+
223
+ def makeBuildInfo() {
224
+ sh """#!/bin/bash
225
+ cd ${jfrogCliRepoDir}
226
+ $builderPath go build --build-name="${buildName}" --build-number="${buildNumber}" --project="${project}"
227
+ """
228
+ }
229
+
230
+ def uploadAndScanBuildInfo() {
231
+ try {
232
+ stage('Upload Build-Info') {
233
+ sh """#!/bin/bash
234
+ $builderPath rt build-publish "${buildName}" "${buildNumber}" --project=${project}
235
+ """
236
+ }
237
+ } catch (e) {
238
+ notifyFailure('Upload Build-Info', e)
239
+ throw e
240
+ }
241
+ try {
242
+ stage('Scanning Build-Info') {
243
+ sh """#!/bin/bash
244
+ $builderPath build-scan "${buildName}" "${buildNumber}" --project ${project}
245
+ """
246
+ }
247
+ }
248
+ catch (e) {
249
+ notifyFailure('Scanning Build-Info', e)
250
+ throw e
251
+ }
252
+ try {
253
+ stage("Scanning Binaries and artifacts under watch ecosystem-watch") {
254
+ sh "$builderPath scan '${jfrogCliRepoDir}' --watches 'ecosystem-watch'"
255
+ }
256
+ }
257
+ catch (e) {
258
+ notifyFailure('Scanning Binaries and artifacts under watch ecosystem-watch', e)
259
+ throw e
260
+ }
261
+ }
262
+
263
+ def build(goos, goarch, pkg, fileName) {
264
+ dir("${jfrogCliRepoDir}") {
265
+ sh "pwd"
266
+ env.GOOS = "$goos"
267
+ env.GOARCH = "$goarch"
268
+ sh "build/build.sh $fileName"
269
+ }
270
+ }
271
+
272
+ def buildAndUpload(goos, goarch, pkg, fileExtension) {
273
+ def extension = fileExtension == null ? '': fileExtension
274
+ def fileName = "$cliExecutableName$fileExtension"
275
+ build(goos, goarch, pkg, fileName)
276
+ uploadBinaryToJfrogRepo21(pkg, fileName)
277
+ sh "rm $jfrogCliRepoDir/$fileName"
278
+ }
0 commit comments