-
Notifications
You must be signed in to change notification settings - Fork 218
396 lines (332 loc) · 20.3 KB
/
test-jenkins.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
# This workflow is used to test the docker-compose files for the default, maven, python, and node directories.
name: docker-compose files test
on:
push:
branches:
- '*' # The workflow will run on push events on all branches.
jobs:
# This job builds and tests the docker-compose files for the maven, python, and node directories.
build-and-test:
strategy:
matrix:
dir: [maven, python, node] # The directories to be tested.
runs-on: ubuntu-latest # The type of machine to run the job on.
timeout-minutes: 30
# Set environment variables for the github username for using the forked repo for tutorials (currently using mine)
env:
GITHUB_USERNAME: gounthar # Used to be ${{ github.repository_owner }}, but the jenkins-docs repository does not have a Jenkinsfile.
DOCKERHUB_USERNAME: ${{ github.repository_owner }}
IMAGE_PREFIX: ghcr.io
BRANCH_SUFFIX: clean-up
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch all history for all branches and tags.
# Set the repository URL based on the directory specified in the matrix.
- name: Set Sample Tutorial Repository URL
run: |
if [[ "${{ matrix.dir }}" == "maven" ]]; then
# The line is storing the URL of the GitHub repository for the simple-java-maven-app in an environment variable named PARTIAL_REPO_URL.
# The ${GITHUB_USERNAME} is a placeholder that will be replaced with the value of the GITHUB_USERNAME environment variable, which is set to the owner of the repository.
echo "PARTIAL_REPO_URL=${GITHUB_USERNAME}/simple-java-maven-app" >> $GITHUB_ENV
elif [[ "${{ matrix.dir }}" == "python" ]]; then
echo "PARTIAL_REPO_URL=${GITHUB_USERNAME}/simple-python-pyinstaller-app" >> $GITHUB_ENV
elif [[ "${{ matrix.dir }}" == "node" ]]; then
echo "PARTIAL_REPO_URL=${GITHUB_USERNAME}/simple-node-js-react-npm-app" >> $GITHUB_ENV
fi
echo "GITHUB_ENV is $GITHUB_ENV"
echo "REPO_URL is $REPO_URL"
shell: bash
- name: Extract current branch name
shell: bash
run: |
BRANCH_NAME=$(echo ${GITHUB_REF#refs/heads/} | sed -e 's#/#-#g')
if [[ "$BRANCH_NAME" == "main" ]]; then BRANCH_NAME=""; fi
echo "BRANCH=$BRANCH_NAME" >> $GITHUB_ENV
id: extract_branch
- name: Extract the current branch name and set the BRANCH environment variable
shell: bash
run: |
BRANCH_NAME=$(echo ${GITHUB_REF#refs/heads/} | sed -e 's#/#-#g')
if [[ "$BRANCH_NAME" == "main" ]]; then BRANCH_NAME=""; fi
echo "BRANCH=$BRANCH_NAME" >> $GITHUB_ENV
- name: Print Sample Tutorial REPO_URL
run: echo "The repository URL is ${{ env.PARTIAL_REPO_URL }}"
# Create a config.xml file in the dockerfiles/jobs directory to add the test job to the instance.
- name: Create config.xml for the Sample Tutorial job
env:
BRANCH_SUFFIX: ${{ env.BRANCH }}
# Full repo URL
REPO_URL: "https://github.com/${{ env.PARTIAL_REPO_URL }}.git"
run: |
# adding test job to the tutorial with REPO_URL
# The XML content is a Jenkins job configuration in XML format.
# It defines a pipeline job that checks out the specified repository and runs the Jenkinsfile in it.
XML_CONTENT=$(cat <<EOL
<?xml version='1.1' encoding='UTF-8'?>
<flow-definition plugin="[email protected]_f">
<actions>
<org.jenkinsci.plugins.pipeline.modeldefinition.actions.DeclarativeJobAction plugin="[email protected]_d1928a_40"/>
<org.jenkinsci.plugins.pipeline.modeldefinition.actions.DeclarativeJobPropertyTrackerAction plugin="[email protected]_d1928a_40">
<jobProperties/>
<triggers/>
<parameters/>
<options/>
</org.jenkinsci.plugins.pipeline.modeldefinition.actions.DeclarativeJobPropertyTrackerAction>
</actions>
<description></description>
<keepDependencies>false</keepDependencies>
<properties/>
<definition class="org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition" plugin="[email protected]_c6240b_">
<scm class="hudson.plugins.git.GitSCM" plugin="[email protected]">
<configVersion>2</configVersion>
<userRemoteConfigs>
<hudson.plugins.git.UserRemoteConfig>
<url>${REPO_URL}</url>
</hudson.plugins.git.UserRemoteConfig>
</userRemoteConfigs>
<branches>
<hudson.plugins.git.BranchSpec>
<name>*/master</name>
</hudson.plugins.git.BranchSpec>
</branches>
<doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations>
<submoduleCfg class="empty-list"/>
<extensions/>
</scm>
<scriptPath>Jenkinsfile</scriptPath>
<lightweight>true</lightweight>
</definition>
<triggers/>
<disabled>false</disabled>
</flow-definition>
EOL
)
echo "pwd is $(pwd)"
echo "$XML_CONTENT" > ./config.xml
echo "checking files below"
tree .
# Check if any files in the specified directory have changed and run docker-compose up with the directory as an argument if there are changes.
- name: checking files & running the docker compose up with ${{ matrix.dir }} argument
run: |
if [ $(git diff --name-only HEAD^ HEAD | uniq | grep -c "${{ matrix.dir }}") -ne 0 ]; then
echo "Changed directories are $(git diff --name-only HEAD^ HEAD | uniq)"
docker compose -f build-docker-compose.yaml --profile ${{ matrix.dir }} up -d --build # Run docker-compose up with the directory as an argument.
else
echo "No Internal examples were modified"
echo 'NO_CHANGES=true' >> $GITHUB_ENV
fi
# Wait for services to be ready if there were changes in the specified directory.
- name: Waiting for services to be ready
if: env.NO_CHANGES != 'true'
run: |
# After the curl request, the output is piped to the awk command. It is used to search for the message
# "Please wait while Jenkins is getting ready to work" in the curl output.
# If the message is found, awk exits with a non-zero status (1), and the loop continues.
# If the message is not found, the loop exits, and the "Jenkins is running" message is displayed.
timeout 60 bash -c 'until curl -s -f http://127.0.0.1:8080/login > /dev/null; do sleep 5; done' && echo "Jenkins is running" || echo "Jenkins is not running"
echo "Jenkins is ready"
JENKINS_VERSION=$(curl -s -I -k http://admin:[email protected]:8080 | grep -i '^X-Jenkins:' | awk '{print $2}')
echo "Jenkins version is: $JENKINS_VERSION"
# Test The stack
- name: Run curl command to test the stack
if: env.NO_CHANGES != 'true'
run: |
# The following steps are used to test the Jenkins stack.
# It includes steps to install dependencies, create a token for the admin user, launch a job, wait for the job to start running,
# wait for the job to complete, and check the job status.
# If the job fails, it gives the console output of why it failed and exits with a non-zero status to fail the step and stop the workflow.
# If the job succeeds, it prints "Job succeeded".
# The detailed steps are documented in the comments within the code block.
set -x
# Installing dependencies
# To check the version of Jenkins, load the top page or any .../api/* page and check for the X-Jenkins response header. This contains the version number of Jenkins, like "1.404" This is also a good way to check if an URL is a Jenkins URL.
JENKINS_VERSION=$(curl -s -I -k http://admin:[email protected]:8080 | grep -i '^X-Jenkins:' | awk '{print $2}')
echo "Jenkins version is: $JENKINS_VERSION"
# Before launching a job, we need to create a token for the admin user
CRUMB=$(curl -s -k http://admin:[email protected]:8080/crumbIssuer/api/xml?xpath=concat\(//crumbRequestField,%22:%22,//crumb\) -c cookies.txt)
echo "CRUMB was found."
TOKEN=$(curl -s -k 'http://admin:[email protected]:8080/user/admin/descriptorByName/jenkins.security.ApiTokenProperty/generateNewToken' --data 'newTokenName=kb-token' -b cookies.txt -H $CRUMB | jq -r '.data.tokenValue')
echo "TOKEN was found."
# Creating the Job from the config.xml file
curl -X POST -H "Content-Type: text/xml" --user admin:$TOKEN --data-binary @config.xml http://127.0.0.1:8080/createItem?name=${{ matrix.dir }}
# Let's set the JOB_NAME it's same as the running tutorial (i.e. maven, python, node)
JOB_NAME="${{ matrix.dir }}"
echo "Launching a job whose name is $JOB_NAME (unencoded)"
# Encode the JOB_NAME to replace spaces, open parentheses, and closing parentheses with their corresponding URL-encoded values.
# This is necessary when using the JOB_NAME in a URL or any other context where special characters need to be encoded.
# Spaces are replaced with "%20", open parentheses with "%28", and closing parentheses with "%29".
# The encoded result is stored in the JOB_NAME_ENCODED variable. This step was useful with using (simple demo job)
JOB_NAME_ENCODED=$(echo "$JOB_NAME" | awk '{ gsub(/ /, "%20"); gsub(/\(/, "%28"); gsub(/\)/, "%29"); print }')
echo "JOB_NAME_ENCODED is $JOB_NAME_ENCODED"
# Checking the present job, debug step, checks if the test job is present.
JOB_PRESENT=$(curl -u admin:$TOKEN http://127.0.0.1:8080/api/json?tree=jobs%5Bname%5D)
echo "JOB_PRESENT is $JOB_PRESENT"
# Starting the job, TOKEN has been set in the previous step
curl -X POST -u admin:$TOKEN 127.0.0.1:8080/job/$JOB_NAME_ENCODED/build
# Wait for the job to start running
sleep 10
echo "Waiting for the job to start running..."
BUILD_NUMBER="null"
# While loop checks if BUILD__NUMBER is empty or null, breaks otherwise
while [[ -z $BUILD_NUMBER || $BUILD_NUMBER == "null" ]]; do
# Retrieve build info from Jenkins API using cURL
BUILD_INFO=$(curl -s -k http://admin:[email protected]:8080/job/$JOB_NAME_ENCODED/api/json)
echo "Retrieved build info: $BUILD_INFO"
# Extract the build number from the JSON response using jq
BUILD_NUMBER=$(echo $BUILD_INFO | jq -r '.lastBuild.number')
# Check if the build is in progress
BUILD_IN_PROGRESS=$(echo $BUILD_INFO | jq -r '.lastBuild.building')
echo "Build number: $BUILD_NUMBER"
echo "Build in progress: $BUILD_IN_PROGRESS"
# If the build number is not empty and the build is in progress, break out of the loop
if [[ -n $BUILD_NUMBER && $BUILD_IN_PROGRESS == "true" ]]; then
break
fi
# Sleep for 5 seconds before checking the build status again
sleep 15 # Adjust the sleep duration as needed
done
echo "This is BUILD__NUMBER $BUILD_NUMBER"
# Delay before retrieving build information
sleep 15
if [[ -z $BUILD_NUMBER ]]; then
# If the build number is empty or "null", it means the job has never run
echo "Job has never run"
else
# If the build number is not empty, the job has started and the build number is displayed
echo "Job started. Build number: $BUILD_NUMBER"
fi
# Wait for the job to complete
echo "Waiting for the job to complete..."
while true; do
# Retrieve the build status and whether the build is in progress
BUILD_STATUS=$(curl -s -k http://admin:[email protected]:8080/job/$JOB_NAME_ENCODED/$BUILD_NUMBER/api/json | jq -r '.result')
BUILD_IN_PROGRESS=$(curl -s -k http://admin:[email protected]:8080/job/$JOB_NAME_ENCODED/$BUILD_NUMBER/api/json | jq -r '.building')
echo "Build status: $BUILD_STATUS"
echo "Build in progress: $BUILD_IN_PROGRESS"
# If the build status is not "null", it means the build has been completed
if [[ $BUILD_STATUS != "null" ]]; then
break
fi
# Below step is for the node tutorial only, in which we need to give input (click PROCEED) in order to complete the pipeline
curl -s -k -X POST -u admin:$TOKEN http://127.0.0.1:8080/job/$JOB_NAME_ENCODED/$BUILD_NUMBER/input/PROCEED/proceedEmpty
sleep 5 # Adjust the sleep duration as needed
done
# Checks BUILD_STATUS to see if job succeeded or failed and if failed gives console output of why it failed and exit
if [[ $BUILD_STATUS == "SUCCESS" ]]; then
echo "Job succeeded"
else
echo "Job failed"
echo "below is the console output"
echo "====================="
curl -s -k -u admin:$TOKEN http://127.0.0.1:8080/job/$JOB_NAME/$BUILD_NUMBER/console
exit 1 # Exit with a non-zero status to fail the step and stop the workflow
fi
- name: Teardown
if: env.NO_CHANGES != 'true'
run: docker compose down
build-and-test-default:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up and start Docker Compose
run: |
docker compose --profile default up -d
echo "Docker Compose started"
- name: Waiting for services to be ready
run: |
# After the curl request, the output is piped to the awk command. It is used to search for the message
# "Please wait while Jenkins is getting ready to work" in the curl output.
# If the message is found, awk exits with a non-zero status (1), and the loop continues.
# If the message is not found, the loop exits, and the "Jenkins is running" message is displayed.
timeout 60 bash -c 'until curl -s -f http://127.0.0.1:8080/login > /dev/null; do sleep 5; done' && echo "Jenkins is running" || echo "Jenkins is not running"
echo "Jenkins is ready"
JENKINS_VERSION=$(curl -s -I -k http://admin:[email protected]:8080 | grep -i '^X-Jenkins:' | awk '{print $2}')
echo "Jenkins version is: $JENKINS_VERSION"
- name: Run curl command to test the stack
run: |
set -x
# Installing dependencies
# To check Sthe version of Jenkins, load the top page or any .../api/* page and check for the X-Jenkins response header. This contains the version number of Jenkins, like "1.404" This is also a good way to check if an URL is a Jenkins URL.
JENKINS_VERSION=$(curl -s -I -k http://admin:[email protected]:8080 | grep -i '^X-Jenkins:' | awk '{print $2}')
echo "Jenkins version is: $JENKINS_VERSION"
# Before launching a job, we need to create a token for the admin user
CRUMB=$(curl -s -k http://admin:[email protected]:8080/crumbIssuer/api/xml?xpath=concat\(//crumbRequestField,%22:%22,//crumb\) -c cookies.txt)
echo "CRUMB was found."
TOKEN=$(curl -s -k 'http://admin:[email protected]:8080/user/admin/descriptorByName/jenkins.security.ApiTokenProperty/generateNewToken' --data 'newTokenName=kb-token' -b cookies.txt -H $CRUMB | jq -r '.data.tokenValue')
echo "TOKEN was found."
# Let's set the JOB_NAME it's same as the running tutorial (i.e. maven, python, node)
echo "Launching a job"
JOB_NAME="%28simple%29%20demo%20job"
# Encode the JOB_NAME to replace spaces, open parentheses, and closing parentheses with their corresponding URL-encoded values.
# This is necessary when using the JOB_NAME in a URL or any other context where special characters need to be encoded.
# Spaces are replaced with "%20", open parentheses with "%28", and closing parentheses with "%29".
# The encoded result is stored in the JOB_NAME_ENCODED variable. This step was usefull with using (simple demo job)
JOB_NAME_ENCODED=$(echo "$JOB_NAME" | awk '{ gsub(/ /, "%20"); gsub(/\(/, "%28"); gsub(/\)/, "%29"); print }')
echo "JOB_NAME_ENCODED is $JOB_NAME_ENCODED"
# Checking the present job, debug step, checks if the test job is present.
JOB_PRESENT=$(curl -u admin:$TOKEN http://127.0.0.1:8080/api/json?tree=jobs%5Bname%5D)
echo "JOB_PRESENT is $JOB_PRESENT"
#Staring the job, TOKEN has been set in previous step
curl -X POST -u admin:$TOKEN 127.0.0.1:8080/job/$JOB_NAME_ENCODED/build
# Wait for the job to start running
sleep 10
echo "Waiting for the job to start running..."
BUILD_NUMBER="null"
# While loop checks if BUILD__NUMBER is empty or null, breaks otherwise
while [[ -z $BUILD_NUMBER || $BUILD_NUMBER == "null" ]]; do
# Retrieve build info from Jenkins API using cURL
BUILD_INFO=$(curl -s -k http://admin:[email protected]:8080/job/$JOB_NAME_ENCODED/api/json)
echo "Retrieved build info: $BUILD_INFO"
# Extract the build number from the JSON response using jq
BUILD_NUMBER=$(echo $BUILD_INFO | jq -r '.lastBuild.number')
# Check if the build is in progress
BUILD_IN_PROGRESS=$(echo $BUILD_INFO | jq -r '.lastBuild.building')
echo "Build number: $BUILD_NUMBER"
echo "Build in progress: $BUILD_IN_PROGRESS"
# If the build number is not empty and the build is in progress, break out of the loop
if [[ -n $BUILD_NUMBER && $BUILD_IN_PROGRESS == "true" ]]; then
break
fi
# Sleep for 5 seconds before checking the build status again
sleep 15 # Adjust the sleep duration as needed
done
echo "This is BUILD__NUMBER $BUILD_NUMBER"
# Delay before retrieving build information
sleep 15
if [[ -z $BUILD_NUMBER ]]; then
# If the build number is empty or "null", it means the job has never run
echo "Job has never run"
else
# If the build number is not empty, the job has started and the build number is displayed
echo "Job started. Build number: $BUILD_NUMBER"
fi
# Wait for the job to complete
echo "Waiting for the job to complete..."
while true; do
# Retrieve the build status and whether the build is in progress
BUILD_STATUS=$(curl -s -k http://admin:[email protected]:8080/job/$JOB_NAME_ENCODED/$BUILD_NUMBER/api/json | jq -r '.result')
BUILD_IN_PROGRESS=$(curl -s -k http://admin:[email protected]:8080/job/$JOB_NAME_ENCODED/$BUILD_NUMBER/api/json | jq -r '.building')
echo "Build status: $BUILD_STATUS"
echo "Build in progress: $BUILD_IN_PROGRESS"
# If the build status is not "null", it means the build has been completed
if [[ $BUILD_STATUS != "null" ]]; then
break
fi
sleep 5 # Adjust the sleep duration as needed
done
# Checks BUILD_STATUS to see if job succeeded or failed and if failed gives console output of why it failed and exit
if [[ $BUILD_STATUS == "SUCCESS" ]]; then
echo "Job succeeded"
else
echo "Job failed"
echo "below is the console output"
echo "====================="
curl -s -k -u admin:$TOKEN http://127.0.0.1:8080/job/$JOB_NAME/$BUILD_NUMBER/console
exit 1 # Exit with a non-zero status to fail the step and stop the workflow
fi
- name: Teardown
run: |
docker compose down