Skip to content

Commit 7902064

Browse files
Jaime Salas ZancadaJaime Salas Zancada
authored andcommitted
added construyendo pipelines reusables
1 parent e517753 commit 7902064

File tree

3 files changed

+338
-7
lines changed

3 files changed

+338
-7
lines changed

03-cd/01-jenkins/00-instalando-jenkins/start_jenkins.sh

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,19 @@ DATA_VOLUME=$4
66

77
# Reference: https://forums.docker.com/t/how-to-filter-docker-ps-by-exact-name/2880/3
88

9-
if [[ $(docker network ls --filter name=^/$NETWORK$) ]]; then
10-
echo 'hello'
9+
if [[ ! $(docker network ls --filter name=^/$NETWORK$) ]]; then
1110
docker network create jenkins
12-
echo 'network jenkins created'
11+
echo network jenkins ${$NETWORK}
1312
fi
1413

15-
if [[ $(docker volume ls --filter name=^/$CERTS_VOLUME$) ]]; then
14+
if [[ ! $(docker volume ls --filter name=^/$CERTS_VOLUME$) ]]; then
1615
docker volume create $CERTS_VOLUME
17-
echo network jenkins "$CERTS_VOLUME"
16+
echo jenkins certs "$CERTS_VOLUME"
1817
fi
1918

20-
if [[ $(docker volume ls --filter name=^/$CERTS_VOLUME$) ]]; then
19+
if [[ ! $(docker volume ls --filter name=^/$CERTS_VOLUME$) ]]; then
2120
docker volume create $DATA_VOLUME
22-
echo network jenkins "$DATA_VOLUME"
21+
echo jenkins data "$DATA_VOLUME"
2322
fi
2423

2524
# StartDocker in Docker into jenkins network
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
# Demo 2
2+
3+
Usando librerías compartidas `https://github.com/Lemoncode/bootcamp-jenkins-library.git`.
4+
5+
Crear un nuevo repo en GiThub, clonar en local, y crear el siguiente _directorio/fichero_ en el raíz `./vars/auditTools.groovy`
6+
7+
```groovy
8+
def call() { // 2
9+
node { // 1
10+
sh '''
11+
git version
12+
docker version
13+
node --version
14+
npm version
15+
'''
16+
}
17+
}
18+
```
19+
20+
* Para que este disponible como parte de una librería compartida tendremos que hacer 3 cosas:
21+
1. El código tiene que estar envuelto en un bloque _node_
22+
2. El nombre del método tiene que ser _call_. Ese es el nombre por defecto que _Jenkins_ espera cunado invoque un de los `custom steps`
23+
3. El nombre del fichero `auditTools.groovy`, coincidirá cone el nombre del paso que qeremos utilizar.
24+
25+
Push changes
26+
27+
## Pre-reqs
28+
29+
Ejecutar Jenkins en [Docker](https://www.docker.com/products/docker-desktop):
30+
31+
```bash
32+
$ ./start_jenkins.sh <jenkins-network> <jenkins-image> <jenkins-volume-certs> <jenkins-volume-data>
33+
```
34+
35+
## 2.1 Usando una librería compartida
36+
37+
Crear un nuevo repositorio de git `jenkins-pipeline-demo-library`
38+
39+
- Reminder - `auditTools` function from [1.3 Jenkinsfile](../demo1/1.3/Jenkinsfile)
40+
- Moved shared library in [auditTools.groovy](../shared-library/vars/auditTools.groovy)
41+
- Published to https://github.com/Lemoncode/bootcamp-jenkins-library.git
42+
43+
Hemos movido el código de `audit tools` a su propio _script file_.
44+
45+
46+
> Notar que todos los scripts se encuentran dentro del mismo directorio _vars_, y ese es otro requisito. Así que para encontrar estos pasos _custom_ que son parte de la librería tienen que estar en este directorio,
47+
48+
> Usado en [2.1 Jenkinsfile](./01/demo2/2.1/Jenkinsfile)
49+
50+
* Crear `01/demo2/2.1/Jenkinsfile`.
51+
52+
> Debemos apuntar al reppositorio correcto
53+
54+
```groovy
55+
library identifier: 'bootcamp-jenkins-library@main',
56+
retriever: modernSCM([$class: 'GitSCMSource', remote: 'https://github.com/Lemoncode/bootcamp-jenkins-library.git']) // [1]
57+
58+
pipeline {
59+
agent any
60+
stages {
61+
stage('Audit tools') {
62+
steps {
63+
auditTools() // [2]
64+
}
65+
}
66+
}
67+
}
68+
```
69+
70+
1. Así es como referencíamos la librería. La primera parte es el _identifier_, que es el nombre del proyecto y la rama del código funete en _GitHub_. Después Jenkins necesita saber como puede recuperar ese código, eso es lo que hace el bloque _retriever_.
71+
72+
2. Para ejecutarlo necesitamos el nombre del script.
73+
74+
- Copy item, `demo2-1` from `demo1-1`
75+
- Path to Jenkinsfile `01/demo2/2.1/Jenkinsfile`
76+
- Open in Blue Ocean
77+
- Run
78+
- Check pipeline log - fetches library
79+
80+
## 2.2 Errores en las liberías
81+
82+
> Crear auditTools2.groovy en el library repo
83+
84+
```groovy
85+
def call(Map config) {
86+
node {
87+
echo ${config.message}
88+
sh '''
89+
git version
90+
docker version
91+
node --version
92+
npm version
93+
'''
94+
}
95+
}
96+
```
97+
98+
Una de las cosas a tener en cuenta es el versionado, que puede ser peligroso.
99+
100+
- Copy item, `demo2-2` from `demo2-1`
101+
- Path to Jenkinsfile `01/demo2/2.2/Jenkinsfile`
102+
- Open in Blue Ocean
103+
- Run - fails
104+
- Check pipeline log
105+
106+
> Walk through the [2.2 Jenkinsfile](./01/demo2/2.2/Jenkinsfile)
107+
108+
```groovy
109+
library identifier: 'jenkins-pipeline-demo-library@main',
110+
retriever: modernSCM([$class: 'GitSCMSource', remote: 'https://github.com/Lemoncode/bootcamp-jenkins-library.git'])
111+
112+
pipeline {
113+
agent any
114+
stages {
115+
stage('Audit tools') {
116+
steps {
117+
auditTools2 message: 'This is demo 2' // The reason because is not working it's because echoing a message need double quotes
118+
}
119+
}
120+
}
121+
}
122+
```
123+
124+
- Check library method [auditTools2.groovy](../shared-library/vars/auditTools2.groovy)
125+
- Fix quotes & push GitHub repo > `echo "${config.message}"`
126+
- Build again - passes, no change to code or pipeline
127+
128+
## 2.3 Shared libraries en una Build completa
129+
130+
> Crear getVersionSuffix.groovy en el library repo
131+
132+
```groovy
133+
def call(Map config) { // [1]
134+
node {
135+
if (config.isReleaseCandidate) { // [2]
136+
return config.rcNumber // [3]
137+
} else {
138+
return config.rcNumber + '+ci' + env.BUILD_NUMBER
139+
}
140+
}
141+
}
142+
```
143+
144+
La manera en la que podemos llamar a este script
145+
146+
```groovy
147+
VERSION_SUFFIX = getVersionSuffix rcNumber: env.VERSION_RC, isReleaseCandidate: params.RC
148+
```
149+
150+
1. La manera en la que funcionan los parámetros es que el método toma este objeto map llamado _config_ que puede tener muchos pares clave valor.
151+
2. Dentro está buscando una clave que sea _isReleaseCandidate_, este es un _boolean_, que la `pipeline` alimetará.
152+
3. También espera la clave _rcNumber_
153+
154+
155+
Crear `01/demo2/2.3/Jenkinsfile`, comenzando desde `01/demo1/1.3/Jenkinsfile`
156+
157+
```groovy
158+
library identifier: 'jenkins-pipeline-demo-library@main',
159+
retriever: modernSCM([$class: 'GitSCMSource', remote: 'https://github.com/Lemoncode/bootcamp-jenkins-library.git'])
160+
161+
pipeline {
162+
agent any
163+
parameters {
164+
booleanParam(name: 'RC', defaultValue: false, description: 'Is this a Release Candidate?')
165+
}
166+
environment {
167+
VERSION = sh([ script: 'cd ./01/src && npm run env | grep "npm_package_version"', returnStdout: true ]).trim()
168+
VERSION_RC = "rc.2"
169+
}
170+
stages {
171+
stage('Audit tools') {
172+
steps {
173+
auditTools()
174+
}
175+
}
176+
stage('Build') {
177+
environment {
178+
VERSION_SUFFIX = getVersionSuffix rcNumber: env.VERSION_RC, isRealeaseCandidate: params.RC
179+
}
180+
steps {
181+
dir('./01/src') {
182+
echo "Building version ${VERSION} with suffix: ${VERSION_SUFFIX}"
183+
sh '''
184+
npm install
185+
npm run build
186+
'''
187+
}
188+
}
189+
}
190+
stage('Unit Test') {
191+
steps {
192+
dir('./01/src') {
193+
sh 'npm test'
194+
}
195+
}
196+
}
197+
stage('Publish') {
198+
when {
199+
expression { return params.RC }
200+
}
201+
steps {
202+
archiveArtifacts('01/src/app/')
203+
}
204+
}
205+
}
206+
}
207+
```
208+
209+
- Compare 1.3 Jenkinsfile and [2.3 Jenkinsfile](./01/demo2/2.3/Jenkinsfile)
210+
- Copy item, `demo2-3` from `demo2-1`
211+
- Path to Jenkinsfile `01/demo2/2.3/Jenkinsfile`
212+
- Build now
213+
- Run
214+
215+
> Alternative - folder and global libraries
216+
217+
- New item, folder, `01`
218+
- Expand _Pipeline libraries_; implicit load but untrusted
219+
220+
- _Manage Jenkins_ ... _Configure System_
221+
- Expand _Global Pipeline libraries_; implicit load and trusted
222+
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# Demo 3
2+
3+
Development workflow para pipelines y librerías compartidas.
4+
5+
## Pre-reqs
6+
7+
Ejecutar Jenkins en [Docker](https://www.docker.com/products/docker-desktop):
8+
9+
```bash
10+
$ ./start_jenkins.sh <jenkins-image> <jenkins-newtwork> <jenkins-volume-certs> <jenkins-volume-data>
11+
```
12+
13+
## 3.1 Jenkinsfile Linter
14+
15+
* Crear `01/demo3/Jenkinsfile`
16+
17+
```groovy
18+
library identifier: 'jenkins-pipeline-demo-library@main',
19+
retriever: modernSCM([$class: 'GitSCMSource', remote: 'https://github.com/Lemoncode/bootcamp-jenkins-library.git'])
20+
21+
pipeline {
22+
agent any
23+
parameters {
24+
booleanParam(name: 'RC', defaultValue: false, description: 'Is this a Release Candidate?')
25+
}
26+
environment {
27+
VERSION = sh([ script: 'cd ./01/src && npm run env | grep "npm_package_version"', returnStdout: true ]).trim()
28+
VERSION_RC = "rc.2"
29+
}
30+
stages {
31+
stage('Audit tools') {
32+
steps {
33+
auditTools()
34+
}
35+
}
36+
stage('Build') {
37+
environment {
38+
VERSION_SUFFIX = getVersionSuffix rcNumber: env.VERSION_RC, isRealeaseCandidate: params.RC
39+
}
40+
steps {
41+
dir('./01/src') {
42+
echo "Building version ${VERSION} with suffix: ${VERSION_SUFFIX}"
43+
sh '''
44+
npm install
45+
npm run build
46+
'''
47+
}
48+
}
49+
}
50+
stage('Unit Test') {
51+
steps {
52+
dir('./01/src') {
53+
sh 'npm test'
54+
}
55+
}
56+
}
57+
stage('Publish') {
58+
when {
59+
expression { return params.RC }
60+
}
61+
steps {
62+
archiveArtifacts('01/src/app/')
63+
}
64+
}
65+
}
66+
}
67+
```
68+
69+
Jenkins API para validar la sintaxis de la pipeline
70+
71+
72+
Nos movemos en el terminal al directorio que contiene el Jenkinsfile al que queremos hacer `lint`, en este caso [Jenkinsfile](jenkins-pipeline-demos/01/demo3/). Esto no comprueba que la pipeline 'compila', tan sólo comprueba la sintaxis. Existe una extensión paar VSCode, `Jenkins Pipeline Linter Conector`.
73+
74+
> Referencia: https://sandrocirulli.net/how-to-validate-a-jenkinsfile/
75+
76+
```
77+
curl --user lemoncode:lemoncode -X POST -F "jenkinsfile=<./Jenkinsfile" http://localhost:8080/pipeline-model-converter/validate
78+
```
79+
80+
Si ahora metemos un error:
81+
82+
```bash
83+
Jaimes-MacBook-Pro:demo3 jaimesalaszancada$ curl --user lemoncode:lemoncode -X POST -F "jenkinsfile=<./Jenkinsfile" http://localhost:8080/pipeline-model-converter/validate
84+
Errors encountered validating Jenkinsfile:
85+
WorkflowScript: 10: expecting ''', found '\n' @ line 10, column 34.
86+
VERSION = '0.1.0"
87+
```
88+
89+
> Usually need a crumb for CRSF protection
90+
91+
- Catches syntax errors
92+
- Try quote mismatch
93+
- Missing brackets for call
94+
- Doesn't catch missing methods
95+
96+
> VS Code linter integration
97+
98+
- _Extensions_ - search `Jenkinsfile`
99+
- Select _Jenkins Pipeline Linter Connector_
100+
- _F1_ in Jenkinsfile
101+
102+
## 3.2 Pipeline Replay & Restart
103+
104+
- Open `demo2-2` build 1
105+
- _Restart from stage_ uses original lib
106+
* Uses exactly the same code and resources, this is useful for CI server connectivity issues.
107+
- _Replay_ allows edit
108+
* This is useful if you want to repeat your build without changing your `Jenkinsfile` on source control. Obviously when we have fix any trouble that cause the failed we have to go back and change then the `Jenkinsfile`
109+
- Edited replay scripts are preserved in restart
110+

0 commit comments

Comments
 (0)