├── .gitignore
├── README.md
├── cd
├── gogs.yaml
├── nexus.yaml
├── reports-repo.yaml
└── sonarqube.yaml
├── config
├── gogs-configmap.yaml
├── gogs-init-taskrun.yaml
├── maven-settings-configmap.yaml
└── pipeline-pvc.yaml
├── demo.sh
├── docs
├── images
│ ├── pipeline-diagram-dev.svg
│ ├── pipeline-diagram-stage.svg
│ ├── pipeline-viz.png
│ ├── pipelines.png
│ └── projects.svg
├── pipeline-diagram-dev.drawio
├── pipeline-diagram-stage.drawio
└── projects.drawio
├── pipelines
├── pipeline-deploy-dev.yaml
└── pipeline-deploy-stage.yaml
├── runs
├── pipeline-deploy-dev-run.yaml
└── pipeline-deploy-stage-run.yaml
├── tasks
├── dependency-report-task.yaml
├── deploy-app-task.yaml
├── gatling-task.yaml
├── mvn-task.yaml
└── s2i-java-11-task.yaml
└── triggers
├── eventlistener.yaml
├── gogs-triggerbinding.yaml
└── triggertemplate.yaml
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | tmp/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | > For a CI/CD demo using Tekton Pipelines and Argo CD on OpenShift refer to:
3 | > https://github.com/siamaksade/openshift-cicd-demo
4 |
5 | # CI/CD Demo with Tekton Pipelines
6 |
7 | This repo is CI/CD demo using [Tekton](http://www.tekton.dev) pipelines on OpenShift which builds and deploys the [Spring PetClinic](https://github.com/spring-projects/spring-petclinic) sample Spring Boot application. This demo creates:
8 | * 3 namespaces for CI/CD, DEV and STAGE projects
9 | * 2 Tekton pipelines for deploying application to DEV and promoting to STAGE environments
10 | * Gogs git server (username/password: `gogs`/`gogs`)
11 | * Sonatype Nexus (username/password: `admin`/`admin123`)
12 | * SonarQube (username/password: `admin`/`admin`)
13 | * Report repository for test and project generated reports
14 | * Imports [Spring PetClinic](https://github.com/spring-projects/spring-petclinic) repository into Gogs git server
15 | * Adds a webhook to `spring-petclinic` repository in Gogs to start the Tekton pipeline
16 |
17 |
18 |
19 |
20 |
21 | ## Deploy DEV Pipeline
22 |
23 | On every push to the `spring-petclinic` git repository on Gogs git server, the following steps are executed within the DEV pipeline:
24 |
25 | 1. Code is cloned from Gogs git server and the unit-tests are run
26 | 1. Unit tests are executed and in parallel the code is analyzed by SonarQube for anti-patterns, and a dependency report is generated
27 | 1. Application is packaged as a JAR and released to Sonatype Nexus snapshot repository
28 | 1. A container image is built in DEV environment using S2I, and pushed to OpenShift internal registry, and tagged with `spring-petclinic:[branch]-[commit-sha]` and `spring-petclinic:latest`
29 | 1. Kubernetes manifests and performance tests configurations are cloned from Git repository
30 | 1. Application is deployed into the DEV environment using `kustomize`, the DEV manifests from Git, and the application `[branch]-[commit-sha]` image tag built in previous steps
31 | 1. Integrations tests and Gatling performance tests are executed in parallel against the DEV environment and the results are uploaded to the report server
32 |
33 | 
34 |
35 | ## Deploy STAGE Pipeline
36 |
37 | The STAGE deploy pipeline requires the image tag that you want to deploy into STAGE environment. The following steps take place within the STAGE pipeline:
38 | 1. Kubernetes manifests are cloned from Git repository
39 | 1. Application is deployed into the STAGE environment using `kustomize`, the STAGE manifests from Git, and the application `[branch]-[commit-sha]` image tag built in previous steps. Alternatively you can deploy the `latest` tag of the application image for demo purposes.
40 | 1. In parallel, tests are cloned from Git repository
41 | 1. Tests are executed against the staging environment
42 |
43 | 
44 |
45 |
46 | # Deploy
47 |
48 | 1. Get an OpenShift cluster via https://try.openshift.com
49 | 1. Install OpenShift Pipelines Operator
50 | 1. Download [OpenShift CLI](https://mirror.openshift.com/pub/openshift-v4/clients/ocp/latest/) and [Tekton CLI](https://github.com/tektoncd/cli/releases)
51 | 1. Deploy the demo
52 |
53 | ```
54 | $ oc new-project demo
55 | $ git clone https://github.com/siamaksade/tekton-cd-demo
56 | $ demo.sh install
57 | ```
58 |
59 | 1. Start the deploy pipeline by making a change in the `spring-petclinic` Git repository on Gogs, or run the following:
60 |
61 | ```
62 | $ demo.sh start
63 | ```
64 |
65 | 1. Check pipeline run logs
66 |
67 | ```
68 | $ tkn pipeline logs petclinic-deploy-dev -n NAMESPACE
69 | ```
70 |
71 | 
72 |
73 | 
74 |
75 |
76 | # Troubleshooting
77 |
78 | ## Why am I getting `unable to recognize "tasks/task.yaml": no matches for kind "Task" in version "tekton.dev/v1beta1"` errors?
79 |
80 | You might have just installed the OpenShift Pipelines operator on the cluster and the operator has not finished installing Tekton on the cluster yet. Wait a few minutes for the operator to finish and then install the demo.
81 |
--------------------------------------------------------------------------------
/cd/gogs.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: apps/v1
3 | kind: Deployment
4 | metadata:
5 | name: gogs-postgresql
6 | annotations:
7 | image.openshift.io/triggers: >-
8 | [{"from":{"kind":"ImageStreamTag","name":"postgresql:latest", "namespace":"openshift"},"fieldPath":"spec.template.spec.containers[?(@.name==\"postgresql\")].image"}]
9 | labels:
10 | app: gogs
11 | app.kubernetes.io/component: database
12 | app.kubernetes.io/instance: gogs
13 | app.kubernetes.io/name: gogs-postgresql
14 | app.kubernetes.io/part-of: gogs
15 | spec:
16 | replicas: 1
17 | selector:
18 | matchLabels:
19 | app: gogs
20 | name: gogs-postgresql
21 | template:
22 | metadata:
23 | labels:
24 | app: gogs
25 | name: gogs-postgresql
26 | spec:
27 | containers:
28 | - name: postgresql
29 | imagePullPolicy: Always
30 | image: postgresql:latest
31 | env:
32 | - name: POSTGRESQL_USER
33 | value: gogs
34 | - name: POSTGRESQL_PASSWORD
35 | value: gogs
36 | - name: POSTGRESQL_DATABASE
37 | value: gogs
38 | - name: POSTGRESQL_MAX_CONNECTIONS
39 | value: "100"
40 | - name: POSTGRESQL_SHARED_BUFFERS
41 | value: 12MB
42 | - name: POSTGRESQL_ADMIN_PASSWORD
43 | value: gogs
44 | ports:
45 | - containerPort: 5432
46 | livenessProbe:
47 | initialDelaySeconds: 30
48 | tcpSocket:
49 | port: 5432
50 | timeoutSeconds: 1
51 | failureThreshold: 10
52 | periodSeconds: 20
53 | readinessProbe:
54 | exec:
55 | command:
56 | - /bin/sh
57 | - -i
58 | - -c
59 | - psql -h 127.0.0.1 -U ${POSTGRESQL_USER} -q -d ${POSTGRESQL_DATABASE} -c 'SELECT 1'
60 | resources:
61 | limits:
62 | memory: 512Mi
63 | volumeMounts:
64 | - mountPath: /var/lib/pgsql/data
65 | name: gogs-postgres-data
66 | volumes:
67 | - name: gogs-postgres-data
68 | persistentVolumeClaim:
69 | claimName: gogs-postgres-data
70 | ---
71 | kind: Service
72 | apiVersion: v1
73 | metadata:
74 | name: gogs-postgresql
75 | labels:
76 | app: gogs
77 | spec:
78 | ports:
79 | - name: postgresql
80 | port: 5432
81 | targetPort: 5432
82 | selector:
83 | name: gogs-postgresql
84 | app: gogs
85 | ---
86 | apiVersion: apps/v1
87 | kind: Deployment
88 | metadata:
89 | name: gogs
90 | labels:
91 | app: gogs
92 | app.kubernetes.io/component: gogs
93 | app.kubernetes.io/instance: gogs
94 | app.kubernetes.io/name: gogs
95 | app.kubernetes.io/part-of: gogs
96 | spec:
97 | replicas: 1
98 | selector:
99 | matchLabels:
100 | app: gogs
101 | name: gogs
102 | template:
103 | metadata:
104 | labels:
105 | app: gogs
106 | name: gogs
107 | spec:
108 | containers:
109 | - name: gogs
110 | imagePullPolicy: Always
111 | image: quay.io/siamaksade/gogs:stable
112 | ports:
113 | - containerPort: 3000
114 | protocol: TCP
115 | volumeMounts:
116 | - name: gogs-data
117 | mountPath: /opt/gogs/data
118 | - name: gogs-config
119 | mountPath: /etc/gogs/conf
120 | readinessProbe:
121 | httpGet:
122 | path: /
123 | port: 3000
124 | scheme: HTTP
125 | initialDelaySeconds: 40
126 | timeoutSeconds: 1
127 | periodSeconds: 20
128 | successThreshold: 1
129 | failureThreshold: 10
130 | livenessProbe:
131 | httpGet:
132 | path: /
133 | port: 3000
134 | scheme: HTTP
135 | initialDelaySeconds: 40
136 | timeoutSeconds: 1
137 | periodSeconds: 10
138 | successThreshold: 1
139 | failureThreshold: 10
140 | volumes:
141 | - name: gogs-data
142 | persistentVolumeClaim:
143 | claimName: gogs-data
144 | - name: gogs-config
145 | configMap:
146 | name: gogs-config
147 | items:
148 | - key: app.ini
149 | path: app.ini
150 | ---
151 | kind: Service
152 | apiVersion: v1
153 | metadata:
154 | labels:
155 | app: gogs
156 | name: gogs
157 | spec:
158 | ports:
159 | - name: 3000-tcp
160 | port: 3000
161 | protocol: TCP
162 | targetPort: 3000
163 | selector:
164 | app: gogs
165 | name: gogs
166 | type: ClusterIP
167 | ---
168 | kind: Route
169 | apiVersion: v1
170 | id: gogs-http
171 | metadata:
172 | labels:
173 | app: gogs
174 | name: gogs
175 | spec:
176 | to:
177 | name: gogs
178 | ---
179 | kind: PersistentVolumeClaim
180 | apiVersion: v1
181 | metadata:
182 | name: gogs-data
183 | labels:
184 | app: gogs
185 | spec:
186 | accessModes:
187 | - ReadWriteOnce
188 | resources:
189 | requests:
190 | storage: 1Gi
191 | ---
192 | kind: PersistentVolumeClaim
193 | apiVersion: v1
194 | metadata:
195 | name: gogs-postgres-data
196 | labels:
197 | app: gogs
198 | spec:
199 | accessModes:
200 | - ReadWriteOnce
201 | resources:
202 | requests:
203 | storage: 1Gi
--------------------------------------------------------------------------------
/cd/nexus.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: apps/v1
3 | kind: Deployment
4 | metadata:
5 | labels:
6 | app: nexus
7 | app.kubernetes.io/instance: nexus
8 | app.kubernetes.io/name: nexus
9 | app.kubernetes.io/part-of: nexus
10 | name: nexus
11 | spec:
12 | replicas: 1
13 | selector:
14 | matchLabels:
15 | app: nexus
16 | template:
17 | metadata:
18 | labels:
19 | app: nexus
20 | spec:
21 | containers:
22 | - name: nexus
23 | image: quay.io/siamaksade/nexus3:3.16.2
24 | env:
25 | - name: CONTEXT_PATH
26 | value: /
27 | imagePullPolicy: IfNotPresent
28 | ports:
29 | - containerPort: 8081
30 | protocol: TCP
31 | livenessProbe:
32 | exec:
33 | command:
34 | - echo
35 | - ok
36 | failureThreshold: 3
37 | initialDelaySeconds: 30
38 | periodSeconds: 10
39 | successThreshold: 1
40 | timeoutSeconds: 1
41 | readinessProbe:
42 | failureThreshold: 3
43 | httpGet:
44 | path: /
45 | port: 8081
46 | scheme: HTTP
47 | initialDelaySeconds: 30
48 | periodSeconds: 10
49 | successThreshold: 1
50 | timeoutSeconds: 1
51 | resources:
52 | limits:
53 | memory: 4Gi
54 | cpu: 2
55 | requests:
56 | memory: 512Mi
57 | cpu: 200m
58 | terminationMessagePath: /dev/termination-log
59 | volumeMounts:
60 | - mountPath: /nexus-data
61 | name: nexus-data
62 | volumes:
63 | - name: nexus-data
64 | persistentVolumeClaim:
65 | claimName: nexus-pv
66 | ---
67 | apiVersion: v1
68 | kind: Service
69 | metadata:
70 | labels:
71 | app: nexus
72 | name: nexus
73 | spec:
74 | ports:
75 | - name: 8081-tcp
76 | port: 8081
77 | protocol: TCP
78 | targetPort: 8081
79 | selector:
80 | app: nexus
81 | sessionAffinity: None
82 | type: ClusterIP
83 | ---
84 | apiVersion: v1
85 | kind: Route
86 | metadata:
87 | labels:
88 | app: nexus
89 | name: nexus
90 | spec:
91 | port:
92 | targetPort: 8081-tcp
93 | to:
94 | kind: Service
95 | name: nexus
96 | weight: 100
97 | ---
98 | apiVersion: v1
99 | kind: PersistentVolumeClaim
100 | metadata:
101 | labels:
102 | app: nexus
103 | name: nexus-pv
104 | spec:
105 | accessModes:
106 | - ReadWriteOnce
107 | resources:
108 | requests:
109 | storage: 5Gi
--------------------------------------------------------------------------------
/cd/reports-repo.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: apps/v1
3 | kind: Deployment
4 | metadata:
5 | labels:
6 | app: reports-repo
7 | app.kubernetes.io/instance: reports-repo
8 | app.kubernetes.io/name: reports-repo
9 | app.kubernetes.io/part-of: reports-repo
10 | name: reports-repo
11 | spec:
12 | replicas: 1
13 | selector:
14 | matchLabels:
15 | app: reports-repo
16 | deployment: reports-repo
17 | template:
18 | metadata:
19 | labels:
20 | app: reports-repo
21 | deployment: reports-repo
22 | spec:
23 | containers:
24 | - name: uploader
25 | image: quay.io/chmouel/go-simple-uploader:latest
26 | imagePullPolicy: IfNotPresent
27 | env:
28 | - name: UPLOADER_PORT
29 | value: "9000"
30 | - name: UPLOADER_DIRECTORY
31 | value: "/fileuploads"
32 | volumeMounts:
33 | - mountPath: /fileuploads
34 | name: staticfiles
35 | - image: quay.io/siamaksade/nginx:latest
36 | name: nginx
37 | ports:
38 | - containerPort: 8080
39 | protocol: TCP
40 | volumeMounts:
41 | - mountPath: /etc/nginx/conf.d/
42 | name: nginx-conf
43 | - mountPath: /fileuploads
44 | name: staticfiles
45 | volumes:
46 | - name: nexus-data
47 | persistentVolumeClaim:
48 | claimName: nexus-pv
49 | volumes:
50 | - configMap:
51 | defaultMode: 420
52 | name: reports-repo-nginx-conf
53 | name: nginx-conf
54 | - name: staticfiles
55 | persistentVolumeClaim:
56 | claimName: reports-repo-pv
57 | ---
58 | apiVersion: v1
59 | kind: ConfigMap
60 | metadata:
61 | name: reports-repo-nginx-conf
62 | data:
63 | htpasswd: |
64 | reports:$apr1$MHzwWLP6$P/dRWWfgBe4J8wfId78v71
65 | nginx.conf: "types {\n text/plain yaml yml;\n}\n\nserver {\n listen 8080
66 | default_server;\n gzip on;\n\n\tlocation /upload {\n\t\tsatisfy any;\n\t\tauth_basic
67 | \"Welcome to the Jungle!\"; #For Basic Auth\n \tauth_basic_user_file conf.d/htpasswd;
68 | \ #For Basic Auth\n\t\tdeny all;\n\n\t\tproxy_set_header Host $host;\n\t\tproxy_set_header
69 | \ X-Real-IP $remote_addr;\n\t\tproxy_set_header X-Forwarded-Proto https;\n\t\tproxy_set_header
70 | \ X-Forwarded-For $remote_addr;\n\t\tproxy_set_header X-Forwarded-Host $remote_addr;\n\n\t\tproxy_pass
71 | http://localhost:9000;\n\t}\n\n\tlocation /private {\n\t\troot /fileuploads;\n\n\t\tsatisfy
72 | any;\n\t\tauth_basic \"Welcome to the Jungle!\"; #For Basic Auth\n \tauth_basic_user_file
73 | conf.d/htpasswd; #For Basic Auth\n\t\tdeny all;\n\n\t autoindex
74 | on;\n\t autoindex_exact_size off;\n\t autoindex_localtime on;\n\t}\n\n\tlocation
75 | / {\n\t\troot /fileuploads;\n\t autoindex on;\n\t autoindex_exact_size off;\n\t
76 | \ autoindex_localtime on;\n\t}\n}\n"
77 | ---
78 | apiVersion: v1
79 | kind: Service
80 | metadata:
81 | labels:
82 | app: reports-repo
83 | name: reports-repo
84 | spec:
85 | ports:
86 | - name: 8080-tcp
87 | port: 8080
88 | protocol: TCP
89 | targetPort: 8080
90 | selector:
91 | app: reports-repo
92 | deployment: reports-repo
93 | ---
94 | apiVersion: v1
95 | kind: Route
96 | metadata:
97 | labels:
98 | app: reports-repo
99 | name: reports-repo
100 | spec:
101 | port:
102 | targetPort: 8080-tcp
103 | to:
104 | kind: Service
105 | name: reports-repo
106 | weight: 100
107 | ---
108 | apiVersion: v1
109 | kind: PersistentVolumeClaim
110 | metadata:
111 | labels:
112 | app: reports-repo
113 | name: reports-repo-pv
114 | spec:
115 | accessModes:
116 | - ReadWriteOnce
117 | resources:
118 | requests:
119 | storage: 5Gi
--------------------------------------------------------------------------------
/cd/sonarqube.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: apps/v1
3 | kind: Deployment
4 | metadata:
5 | name: sonarqube
6 | labels:
7 | app: sonarqube
8 | app.kubernetes.io/component: sonarqube
9 | app.kubernetes.io/instance: sonarqube
10 | app.kubernetes.io/name: sonarqube
11 | app.kubernetes.io/part-of: sonarqube
12 | spec:
13 | replicas: 1
14 | selector:
15 | matchLabels:
16 | app: sonarqube
17 | name: sonarqube
18 | template:
19 | metadata:
20 | labels:
21 | app: sonarqube
22 | name: sonarqube
23 | spec:
24 | containers:
25 | - name: sonarqube
26 | imagePullPolicy: Always
27 | image: quay.io/siamaksade/sonarqube:8.3-community
28 | ports:
29 | - containerPort: 9000
30 | protocol: TCP
31 | volumeMounts:
32 | - mountPath: /opt/sq/temp
33 | name: sonarqube-temp
34 | - mountPath: /opt/sq/conf
35 | name: sonarqube-conf
36 | - mountPath: /opt/sq/data
37 | name: sonarqube-data
38 | - mountPath: /opt/sq/extensions
39 | name: sonarqube-extensions
40 | - mountPath: /opt/sq/logs
41 | name: sonarqube-logs
42 | livenessProbe:
43 | failureThreshold: 10
44 | httpGet:
45 | path: /
46 | port: 9000
47 | scheme: HTTP
48 | initialDelaySeconds: 45
49 | periodSeconds: 10
50 | successThreshold: 1
51 | timeoutSeconds: 1
52 | readinessProbe:
53 | failureThreshold: 10
54 | httpGet:
55 | path: /
56 | port: 9000
57 | scheme: HTTP
58 | initialDelaySeconds: 10
59 | periodSeconds: 10
60 | successThreshold: 1
61 | timeoutSeconds: 1
62 | resources:
63 | limits:
64 | cpu: "1"
65 | memory: 4Gi
66 | requests:
67 | cpu: 200m
68 | memory: 512Mi
69 | volumes:
70 | - name: sonarqube-temp
71 | emptyDir: {}
72 | - name: sonarqube-conf
73 | emptyDir: {}
74 | - name: sonarqube-data
75 | emptyDir: {}
76 | - name: sonarqube-extensions
77 | emptyDir: {}
78 | - name: sonarqube-logs
79 | emptyDir: {}
80 | ---
81 | apiVersion: v1
82 | kind: Route
83 | metadata:
84 | labels:
85 | app: sonarqube
86 | name: sonarqube
87 | spec:
88 | port:
89 | targetPort: 9000-tcp
90 | tls:
91 | termination: edge
92 | to:
93 | kind: Service
94 | name: sonarqube
95 | weight: 100
96 | wildcardPolicy: None
97 | ---
98 | apiVersion: v1
99 | kind: Service
100 | metadata:
101 | labels:
102 | app: sonarqube
103 | name: sonarqube
104 | spec:
105 | ports:
106 | - name: 9000-tcp
107 | port: 9000
108 | protocol: TCP
109 | targetPort: 9000
110 | selector:
111 | app: sonarqube
112 | name: sonarqube
113 | type: ClusterIP
--------------------------------------------------------------------------------
/config/gogs-configmap.yaml:
--------------------------------------------------------------------------------
1 | kind: ConfigMap
2 | apiVersion: v1
3 | metadata:
4 | name: gogs-config
5 | labels:
6 | app: gogs
7 | data:
8 | app.ini: |
9 | RUN_MODE = prod
10 | RUN_USER = gogs
11 |
12 | [database]
13 | DB_TYPE = postgres
14 | HOST = gogs-postgresql:5432
15 | NAME = gogs
16 | USER = gogs
17 | PASSWD = gogs
18 |
19 | [repository]
20 | ROOT = /opt/gogs/data/repositories
21 |
22 | [server]
23 | ROOT_URL=http://@HOSTNAME
24 | SSH_DOMAIN=@HOSTNAME
25 |
26 | [security]
27 | INSTALL_LOCK = true
28 |
29 | [service]
30 | ENABLE_CAPTCHA = false
31 |
32 | [webhook]
33 | SKIP_TLS_VERIFY = true
--------------------------------------------------------------------------------
/config/gogs-init-taskrun.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: tekton.dev/v1beta1
2 | kind: TaskRun
3 | metadata:
4 | generateName: init-gogs-
5 | spec:
6 | taskSpec:
7 | params:
8 | - name: GOGS_USER
9 | type: string
10 | description: Gogs admin username
11 | default: gogs
12 | - name: GOGS_PASSWORD
13 | type: string
14 | description: Gogs admin password
15 | default: gogs
16 | stepTemplate:
17 | env:
18 | - name: NAMESPACE
19 | valueFrom:
20 | fieldRef:
21 | fieldPath: metadata.namespace
22 | steps:
23 | - name: init-gogs
24 | image: quay.io/siamaksade/python-oc
25 | script: |
26 | #!/usr/bin/env python3
27 |
28 | import os
29 | import requests
30 |
31 | gogs_user = "$(params.GOGS_USER)"
32 | gogs_pwd = "$(params.GOGS_PASSWORD)"
33 | webhookURL = "http://" + os.popen('oc get route webhook -o template --template="{{.spec.host}}"').read()
34 | gogsURL = "http://" + os.popen('oc get svc gogs -o template --template="{{.spec.clusterIP}}"').read() + ":3000"
35 |
36 | # create admin user
37 | data_user = {
38 | 'user_name': gogs_user,
39 | 'password': gogs_pwd,
40 | 'retype': gogs_pwd,
41 | 'email': 'admin@gogs.com'
42 | }
43 |
44 | resp = requests.post(url = gogsURL + "/user/sign_up", data = data_user)
45 |
46 | if resp.status_code != 200:
47 | print("Error creating Gogs admin (status code: {})".format(resp.status_code))
48 | print(resp.content)
49 | else:
50 | print("Created admin user {}:{}".format(gogs_user, gogs_pwd))
51 |
52 | # create git repo spring-petclinic
53 | data_repo = '{"clone_addr": "https://github.com/siamaksade/spring-petclinic", "uid": 1, "repo_name": "spring-petclinic"}'
54 | headers = {'Content-Type': 'application/json'}
55 | resp = requests.post(url = gogsURL + "/api/v1/repos/migrate", headers = headers, auth = (gogs_user, gogs_pwd), data = data_repo)
56 |
57 | if resp.status_code != 200 and resp.status_code != 201:
58 | print("Error creating git repo (status code: {})".format(resp.status_code))
59 | print(resp.content)
60 | else:
61 | print("Created git repo spring-petclinic")
62 |
63 | # configure webhook on spring-petclinic
64 | data_webhook = '{"type": "gogs", "config": { "url": "' + webhookURL + '", "content_type": "json"}, "events": ["push"], "active": true}'
65 | headers = {'Content-Type': 'application/json'}
66 | resp = requests.post(url = gogsURL + "/api/v1/repos/" + gogs_user + "/spring-petclinic/hooks",
67 | headers = headers,
68 | auth = (gogs_user, gogs_pwd),
69 | data = data_webhook)
70 |
71 | if resp.status_code != 200 and resp.status_code != 201:
72 | print("Error configuring the webhook (status code: {})".format(resp.status_code))
73 | print(resp.content)
74 | else:
75 | print("Configured webhook: " + webhookURL)
76 |
77 | # create git repo spring-petclinic-config
78 | data_repo = '{"clone_addr": "https://github.com/siamaksade/spring-petclinic-config.git", "uid": 1, "repo_name": "spring-petclinic-config"}'
79 | headers = {'Content-Type': 'application/json'}
80 | resp = requests.post(url = gogsURL + "/api/v1/repos/migrate", headers = headers, auth = (gogs_user, gogs_pwd), data = data_repo)
81 |
82 | if resp.status_code != 200 and resp.status_code != 201:
83 | print("Error creating git repo (status code: {})".format(resp.status_code))
84 | print(resp.content)
85 | else:
86 | print("Created git repo spring-petclinic-config")
87 |
88 | # configure webhook on spring-petclinic-config
89 | data_webhook = '{"type": "gogs", "config": { "url": "' + webhookURL + '", "content_type": "json"}, "events": ["push"], "active": true}'
90 | headers = {'Content-Type': 'application/json'}
91 | resp = requests.post(url = gogsURL + "/api/v1/repos/" + gogs_user + "/spring-petclinic-config/hooks",
92 | headers = headers,
93 | auth = (gogs_user, gogs_pwd),
94 | data = data_webhook)
95 |
96 | if resp.status_code != 200 and resp.status_code != 201:
97 | print("Error configuring the webhook (status code: {})".format(resp.status_code))
98 | print(resp.content)
99 | else:
100 | print("Configured webhook: " + webhookURL)
101 |
102 | # create git repo spring-petclinic-gatling
103 | data_repo = '{"clone_addr": "https://github.com/siamaksade/spring-petclinic-gatling", "uid": 1, "repo_name": "spring-petclinic-gatling"}'
104 | headers = {'Content-Type': 'application/json'}
105 | resp = requests.post(url = gogsURL + "/api/v1/repos/migrate", headers = headers, auth = (gogs_user, gogs_pwd), data = data_repo)
106 |
107 | if resp.status_code != 200 and resp.status_code != 201:
108 | print("Error creating git repo (status code: {})".format(resp.status_code))
109 | print(resp.content)
110 | else:
111 | print("Created git repo spring-petclinic-gatling")
112 |
113 |
--------------------------------------------------------------------------------
/config/maven-settings-configmap.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: ConfigMap
3 | metadata:
4 | name: maven-settings
5 | data:
6 | settings.xml: |
7 |
8 |
9 |
10 |
11 | nexus
12 | admin
13 | admin123
14 |
15 |
16 |
17 |
18 | nexus
19 | nexus
20 | http://nexus:8081/repository/maven-public/
21 | *
22 |
23 |
24 |
--------------------------------------------------------------------------------
/config/pipeline-pvc.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: v1
3 | kind: PersistentVolumeClaim
4 | metadata:
5 | name: petclinic-dev-workspace
6 | spec:
7 | resources:
8 | requests:
9 | storage: 5Gi
10 | volumeMode: Filesystem
11 | accessModes:
12 | - ReadWriteOnce
13 | persistentVolumeReclaimPolicy: Retain
14 | ---
15 | apiVersion: v1
16 | kind: PersistentVolumeClaim
17 | metadata:
18 | name: petclinic-stage-workspace
19 | spec:
20 | resources:
21 | requests:
22 | storage: 5Gi
23 | volumeMode: Filesystem
24 | accessModes:
25 | - ReadWriteOnce
26 | persistentVolumeReclaimPolicy: Retain
--------------------------------------------------------------------------------
/demo.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e -u -o pipefail
4 | declare -r SCRIPT_DIR=$(cd -P $(dirname $0) && pwd)
5 | declare PRJ_PREFIX="demo"
6 | declare COMMAND="help"
7 |
8 | valid_command() {
9 | local fn=$1; shift
10 | [[ $(type -t "$fn") == "function" ]]
11 | }
12 |
13 | info() {
14 | printf "\n# INFO: $@\n"
15 | }
16 |
17 | err() {
18 | printf "\n# ERROR: $1\n"
19 | exit 1
20 | }
21 |
22 | while (( "$#" )); do
23 | case "$1" in
24 | install|uninstall|start|promote)
25 | COMMAND=$1
26 | shift
27 | ;;
28 | -p|--project-prefix)
29 | PRJ_PREFIX=$2
30 | shift 2
31 | ;;
32 | --)
33 | shift
34 | break
35 | ;;
36 | -*|--*)
37 | err "Error: Unsupported flag $1"
38 | ;;
39 | *)
40 | break
41 | esac
42 | done
43 |
44 | declare -r dev_prj="$PRJ_PREFIX-dev"
45 | declare -r stage_prj="$PRJ_PREFIX-stage"
46 | declare -r cicd_prj="$PRJ_PREFIX-cicd"
47 |
48 | command.help() {
49 | cat <<-EOF
50 |
51 | Usage:
52 | demo [command] [options]
53 |
54 | Example:
55 | demo install --project-prefix mydemo
56 |
57 | COMMANDS:
58 | install Sets up the demo and creates namespaces
59 | uninstall Deletes the demo
60 | start Starts the deploy DEV pipeline
61 | promote Starts the deploy STAGE pipeline
62 | help Help about this command
63 |
64 | OPTIONS:
65 | -p|--project-prefix [string] Prefix to be added to demo project names e.g. PREFIX-dev
66 | EOF
67 | }
68 |
69 | command.install() {
70 | oc version >/dev/null 2>&1 || err "no oc binary found"
71 |
72 | info "Creating namespaces $cicd_prj, $dev_prj, $stage_prj"
73 | oc get ns $cicd_prj 2>/dev/null || {
74 | oc new-project $cicd_prj
75 | }
76 | oc get ns $dev_prj 2>/dev/null || {
77 | oc new-project $dev_prj
78 | }
79 | oc get ns $stage_prj 2>/dev/null || {
80 | oc new-project $stage_prj
81 | }
82 |
83 | info "Configure service account permissions for pipeline"
84 | oc policy add-role-to-user edit system:serviceaccount:$cicd_prj:pipeline -n $dev_prj
85 | oc policy add-role-to-user edit system:serviceaccount:$cicd_prj:pipeline -n $stage_prj
86 | oc policy add-role-to-user edit system:serviceaccount:$stage_prj:default -n $dev_prj
87 |
88 | info "Deploying CI/CD infra to $cicd_prj namespace"
89 | oc apply -f cd -n $cicd_prj
90 | GOGS_HOSTNAME=$(oc get route gogs -o template --template='{{.spec.host}}' -n $cicd_prj)
91 |
92 | info "Deploying pipeline and tasks to $cicd_prj namespace"
93 | oc apply -f tasks -n $cicd_prj
94 | oc create -f config/maven-settings-configmap.yaml -n $cicd_prj
95 | oc apply -f config/pipeline-pvc.yaml -n $cicd_prj
96 | sed "s/demo-dev/$dev_prj/g" pipelines/pipeline-deploy-dev.yaml | sed -E "s#https://github.com/siamaksade#http://$GOGS_HOSTNAME/gogs#g" | oc apply -f - -n $cicd_prj
97 | sed "s/demo-dev/$dev_prj/g" pipelines/pipeline-deploy-stage.yaml | sed -E "s/demo-stage/$stage_prj/g" | sed -E "s#https://github.com/siamaksade#http://$GOGS_HOSTNAME/gogs#g" | oc apply -f - -n $cicd_prj
98 |
99 | oc apply -f triggers/gogs-triggerbinding.yaml -n $cicd_prj
100 | oc apply -f triggers/triggertemplate.yaml -n $cicd_prj
101 | sed "s/demo-dev/$dev_prj/g" triggers/eventlistener.yaml | oc apply -f - -n $cicd_prj
102 |
103 | info "Initiatlizing git repository in Gogs and configuring webhooks"
104 | sed "s/@HOSTNAME/$GOGS_HOSTNAME/g" config/gogs-configmap.yaml | oc create -f - -n $cicd_prj
105 | oc rollout status deployment/gogs -n $cicd_prj
106 | oc create -f config/gogs-init-taskrun.yaml -n $cicd_prj
107 |
108 | oc project $cicd_prj
109 |
110 | cat <<-EOF
111 |
112 | ############################################################################
113 | ############################################################################
114 |
115 | Demo is installed! Give it a few minutes to finish deployments and then:
116 |
117 | 1) Go to spring-petclinic Git repository in Gogs:
118 | http://$GOGS_HOSTNAME/gogs/spring-petclinic.git
119 |
120 | 2) Log into Gogs with username/password: gogs/gogs
121 |
122 | 3) Edit a file in the repository and commit to trigger the pipeline
123 |
124 | 4) Check the pipeline run logs in Dev Console or Tekton CLI:
125 |
126 | \$ tkn pipeline logs petclinic-deploy-dev -f -n $cicd_prj
127 |
128 |
129 | You can find further details at:
130 |
131 | Gogs Git Server: http://$GOGS_HOSTNAME/explore/repos
132 | Reports Server: http://$(oc get route reports-repo -o template --template='{{.spec.host}}' -n $cicd_prj)
133 | SonarQube: https://$(oc get route sonarqube -o template --template='{{.spec.host}}' -n $cicd_prj)
134 | Sonatype Nexus: http://$(oc get route nexus -o template --template='{{.spec.host}}' -n $cicd_prj)
135 |
136 | ############################################################################
137 | ############################################################################
138 | EOF
139 | }
140 |
141 | command.start() {
142 | oc create -f runs/pipeline-deploy-dev-run.yaml -n $cicd_prj
143 | }
144 |
145 | command.promote() {
146 | oc create -f runs/pipeline-deploy-stage-run.yaml -n $cicd_prj
147 | }
148 |
149 | command.uninstall() {
150 | oc delete project $dev_prj $stage_prj $cicd_prj
151 | }
152 |
153 | main() {
154 | local fn="command.$COMMAND"
155 | valid_command "$fn" || {
156 | err "invalid command '$COMMAND'"
157 | }
158 |
159 | cd $SCRIPT_DIR
160 | $fn
161 | return $?
162 | }
163 |
164 | main
--------------------------------------------------------------------------------
/docs/images/pipeline-diagram-dev.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/docs/images/pipeline-diagram-stage.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/docs/images/pipeline-viz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/siamaksade/tekton-cd-demo/7ae7ea58f310d744081b9373a9fb13a744e8488b/docs/images/pipeline-viz.png
--------------------------------------------------------------------------------
/docs/images/pipelines.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/siamaksade/tekton-cd-demo/7ae7ea58f310d744081b9373a9fb13a744e8488b/docs/images/pipelines.png
--------------------------------------------------------------------------------
/docs/images/projects.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/docs/pipeline-diagram-dev.drawio:
--------------------------------------------------------------------------------
1 | 7Vxbc5s4FP41ntl9yA4Ig+HRsdNs2u4mjbdt0pcdGWSbBCNGiMTeX7+SAXMRwcTGXDrNi9FBEuKc71x0dMhAmaw31wR6q7+whZwBkKzNQJkOAJAlw2A/nLINKYYBQsKS2FbUKSHM7P9QPDKiBraF/ExHirFDbS9LNLHrIpNmaJAQ/JrttsBO9qkeXCKBMDOhI1K/2xZdhVRdlRL6n8heruIny1J0Zw3jzhHBX0ELv6ZIytVAmRCMaXi13kyQw5kX8yUc9+GNu/uFEeTSKgPAfEVH5g8NLi3z1n9+GT9c/LiI2ezTbfzGyGIMiJqY0BVeYhc6Vwn1kuDAtRCfVmKtpM9njD1GlBnxCVG6jaQJA4oZaUXXTnQXbWz6kLp+5FP9oUat6SaaedfYxg2Xku1DupEaxZvJsF1rP86Z77j+ggi1mVwZyQzIy275/PkiGyPO+jggJirjXQRHSJYoGvrkPD1KZHx5O7oZf9S+X7j/Kl/ifpyvqQdEQrpGeI3YelkHghxI7Zcs8GCE3+W+XyJidhFJ+T0Sl4+QeIZjvRJ/reIt7DdsS7w3HzCZaT54vL+YGt+m86+fJvYFKJWui93WFLhWSRS+e8cULZz3BTpB9KSJw9kPpAnzkoKYEplwpr6ubIpmHtzx5ZW51iz/F7bjTLCDyW6sYkGkL0xG9ynBzyh1RzN1NF+UcZ/bRbQp5Vd8V4t8eeTKldizvSaOUY5pq5RT1KRzsbgc7T+bLbOgv9qvXBC1JGnaZHKSooGKJq92RYuG3mGbLXkPOGOUxZuaw1H4PtGgdOSTm0ceHpgofGFhoh0m969TCabFAYDeGZgm0HxMI/MATBNkPmaAWQzTt5GZAXAhhmrDbaEghnXAdEwI3KY6eBw2/tso1qUM+GRNKgWrrhtl/dlFuIB6EWp0FKHyUQiV6zSkjSJU7QBCVeMQQvWy/icjtIyBqWjqGi/ZO7FHaw7j6OWcsKslv7q2+WJniKGTCLBmu3CPX5pbx2aAJYdjrXmI7M/zPQGaz8sd3m8DymZBgwM7yeohFshKQpHVahHW6GwRltJRw3Cc63qXYThe25WKcZTWTBylqtn4Bxhni3+KQTRqH0TnTB+UZX0OYkCpGwNV9b1w1ceoe6/2UDX69KpaLp/q1E+y4IrgOO+Rg6CPmLuEa+7r3LnPf8aeJwi/+0mJYX6T2H5SYti+tasxlj6026vmMs/t4pT4WCmCwXCUm6JqriA/kSppzfrK7uQKup2eH7blX4txM8xtooZyszHWUDDzM8rex2S0MRP+1rf9Hlp3RcmpdXx61Zp110Q+M+WiWw8V7kX/RptAZHy3N6F5lwpa34WOCplOvgRz8Ryl27zNA1qVhs3xtjDi707mrwl/U5Ds43/1bgxifTl7PvokwR9V+vFL8vVIvtUtYbzKlD29DGzHYqSbNa+HEtzYbzNww+5+hC/w9x6GEZomZ6xuo5vEwlKFX1F+RYXSRIUqZGjtVThvHCXv6/tiKElGdo764vzC9+ynu24AAGpbAGg6mS7uQKbIczB/t10KT2ICA9Kth9zZyl7wpU+vvvXQaBtGjtGtG+3y5HibtXVnNcxltXadSb/kwdJwiQ8AnbHLjSd96y6gqIq34n7Sifg6yUKINZ/XyEUEUp4duiP4iX+iAKR75DEB99Am59MX7dtkMe95H7h8I7OzDv8gnxe+5Lcz+aMv2+2tl5RlVc2IBIyMlkXSoarcztnCY0xfQU6hxPQ1EQJrubMOkINS5cLc/ExnPG0rY61gPe4QWWCyhq6JEisi/UxmQtHattwxXDOVCdwvFlf18Xu+TXH05P6k/A29ayl/MUoJUf/VtVNOsw2MC1wt4H3l4AQAvTmIFzNa7Ywn7GOK/e0zkypVV9qJzu8kyYthafzx16dgjoiLKOJmjnkYe9FTddNB9kMFoFU8Jj6funWn8uo96taI2hQEkR1UGzEei9Wmr05JB9mPJZTR+eIu1kz+nUAYIif/lEG5+h8=
--------------------------------------------------------------------------------
/docs/pipeline-diagram-stage.drawio:
--------------------------------------------------------------------------------
1 | 5VhZc9owEP41PKZjW8bAIyGUnkNbMpPjpSPsxVYiLI8sc/TXV7LlCxOgKZQwfQHp064k73572C00mK9GHEfBV+YBbVmGt2qhm5ZlmUavJ/8Uss6QXs/KAJ8TTwuVwIT8glxTownxIK4JCsaoIFEddFkYgitqGOacLetiM0brp0bYhwYwcTFtonfEE0GGdttGiX8A4gf5yaahV+Y4F9ZAHGCPLSsQGrbQgDMmstF8NQCqjJfbJdN7/8JqcTEOoThEwZoGouM+Otj33HH8vOjfXz1e5WaOxTp/YvCkAfSUcREwn4WYDkv0mrMk9EBta8hZKfOFsUiCpgSfQIi19iZOBJNQIOZUr8KKiPvK+EFt9a6tZzcrvXM6WeeTUPD1fXVS0VLTUi2dFXp0mlp9AVwQ6VcJuQlfpNdX5zfNqC0bs4S7sMt2mo6Y+6BVn+jTg8H71+POx/4n5+4q/Im+53LKrpUDtJNGwOYg7ysFOFAsyKJOPKz56xdypYvlQHv5TzxuvsLjNYtdlPuP6t6tcvbbcm+27wLTRJ80oCwECX1OpsBDEDKbquwUkhnEIm6QofSucs8yIAImEU4ttZQpvu7JGaF0wCjjqS7yMHRnrsRjwdkzVFYctwvT2S5/qPiE1U4L5quOrim6pKA8wy7LBG3mWFBJzo5xKqNb/1VMeTgOips3XG0YjjMY/FXoWQeG3tEzq1b9xoi8ckG4XqfOt/YGj7Ln0UrVCryxj2nv2Sh74MZGKSeLxzmIplsLkWW/GZqW1HyorOyjacnMQutYNN3g0Gl5ax+Dpn3O8boiECnaxC+zuGvUyNdGxk6yorxR3y4vB9kFXsvQXQasVK8R81W9alkOlRa9nnI58tVoRNRlJyDZyRu0lr12pIbumhJJWL6/kk0zZn+ZFgB2n/2U7+NEyF1gX794eAGz6p5AZvuw+tU5Wf3qnD8xnLK/29WW7w1W9Kb6O9SIkB9JKIHbrJkzSLg1Wia3/dHwAns9e7P2nr/X654/Vi7i/ck+V3xtr2f2Rv2zzZM1X7vMseXF7PZC38MQqncIqGP+u9jcldIrNr6BiDJ1534UpZ8O5c84gnASkFnaP5wvLzYMvcUdB9vecrons72cll8ps3Aov/Wi4W8=
--------------------------------------------------------------------------------
/docs/projects.drawio:
--------------------------------------------------------------------------------
1 | 7VnbcpswEP0aHtORkC/4sXac9iFN03qmSZ86MsigRCBGyDbu11eAZMCyc3HsOpOEzGS0RyshnbMr1uCgUZx/ETiNvvGAMMcFQe6gc8d1Bx5U/wtgVQHdvlcBoaBBBcEamNC/RINAo3MakKzlKDlnkqZt0OdJQnzZwrAQfNl2m3HWvmuKQ2IBEx8zG72hgYwq1OuCGv9KaBiZO0Oge2JsnDWQRTjgywaExg4aCc5l1YrzEWEFd4aXatzFjt71wgRJ5FMGeJerztXodoFufl2hP1c/70F+d6ZnWWA21xv+npJkEtGZ1KuWK0OF4PMkIMVswEHDZUQlmaTYL3qXSnuFRTJmyoKqmUnB78mIMy4UkvBEuQ1nlDEDOS4a94o/hTM8JeyaZ1RSnqg+X22JKKfhgghJlRiXGw4xDYJiWUPMaLh1xGfdIXmxsBlP5ETvBBq7ijXYUbZmQY0l+U564Vo0FeyEx0SKlXIxka5l1nG+ln1ZR023p7GoGTF9DWIdqeF66lpM1dB6PkNb19I2IDE/86kfvEzbXTK2NVc9vfLaR+Apl5LHTxc4wFlULh9q4xpL5Z+UiAvgYTSGsN8WuW+L7LrIFtmcggfXGG3XOCCLD4n3khj1waMSQ7glj48mcc+SeJIKmoROccL0mLr9cCpUKyxa10SOGE2of8jTW8kMyssOjIvy2jhRwYGkGGxk22DLkdq3legc60D1tidbJosa4iPd9tG4C/dNt2OJPHiv6dZFryzdoF2cvgGaoeu1afZOTbNdJ74FmtEGzSePZrtUm/AEix/z6QsfHq+D706bbwROzLfbfzysQ8VzunPz+pUCnhp38FxS1OPsU3eDFmg/3wAwXk1m3KNFol3HWMyoaWiakceDD2dp9dplRvMiYP9XND6guS1H8+fZllrieEzbxcQbZzo3WW0i+lTUux2b6SAk5iUQFzLioTp/2bhGh/5cLNY1b/sMrgdc8qI+Ll3uiJQrTSieS94WjORU3jbav4upFC+VdZ7rmUtjZYxEbf62aTRGFWY9rLTMuO3KFjveR1dFG58LnzzhEJFYhOShGascsCNFEIYlXbTXd/gwAO80A73TZ2D3IwOPmoGDJ2Zg42vDQTNQmfXXi7Kv8QkIjf8B
--------------------------------------------------------------------------------
/pipelines/pipeline-deploy-dev.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: tekton.dev/v1beta1
2 | kind: Pipeline
3 | metadata:
4 | name: petclinic-deploy-dev
5 | spec:
6 | params:
7 | - name: APP_SOURCE_GIT
8 | type: string
9 | description: The application git repository
10 | default: https://github.com/siamaksade/spring-petclinic
11 | - name: APP_SOURCE_REVISION
12 | type: string
13 | description: The application git revision
14 | default: master
15 | - name: APP_CONFIG_GIT
16 | type: string
17 | description: The application configuration git repository
18 | default: https://github.com/siamaksade/spring-petclinic-config
19 | - name: APP_TESTS_GIT
20 | type: string
21 | description: The application test cases git repository
22 | default: https://github.com/siamaksade/spring-petclinic-gatling
23 | - name: APP_IMAGE
24 | type: string
25 | default: image-registry.openshift-image-registry.svc:5000/demo-dev/spring-petclinic
26 | description: The application image to build
27 | - name: APP_IMAGE_TAG
28 | type: string
29 | default: latest
30 | description: The application image tag to build
31 | workspaces:
32 | - name: workspace
33 | - name: maven-settings
34 | tasks:
35 | - name: source-clone
36 | taskRef:
37 | name: git-clone
38 | kind: ClusterTask
39 | workspaces:
40 | - name: output
41 | workspace: workspace
42 | params:
43 | - name: url
44 | value: $(params.APP_SOURCE_GIT)
45 | - name: revision
46 | value: $(params.APP_SOURCE_REVISION)
47 | - name: depth
48 | value: "0"
49 | - name: subdirectory
50 | value: spring-petclinic
51 | - name: deleteExisting
52 | value: "true"
53 | - name: unit-tests
54 | taskRef:
55 | name: maven
56 | runAfter:
57 | - source-clone
58 | workspaces:
59 | - name: source
60 | workspace: workspace
61 | - name: maven-settings
62 | workspace: maven-settings
63 | params:
64 | - name: GOALS
65 | value: ["package", "-f", "spring-petclinic"]
66 | - name: code-analysis
67 | taskRef:
68 | name: maven
69 | runAfter:
70 | - source-clone
71 | workspaces:
72 | - name: source
73 | workspace: workspace
74 | - name: maven-settings
75 | workspace: maven-settings
76 | params:
77 | - name: GOALS
78 | value:
79 | - install
80 | - sonar:sonar
81 | - -f
82 | - spring-petclinic
83 | - -Dsonar.host.url=http://sonarqube:9000
84 | - -Dsonar.userHome=/tmp/sonar
85 | - -DskipTests=true
86 | - name: dependency-report
87 | taskRef:
88 | name: dependency-report
89 | runAfter:
90 | - source-clone
91 | workspaces:
92 | - name: source
93 | workspace: workspace
94 | - name: maven-settings
95 | workspace: maven-settings
96 | params:
97 | - name: SOURCE_DIR
98 | value: spring-petclinic
99 | - name: release-app
100 | taskRef:
101 | name: maven
102 | runAfter:
103 | - code-analysis
104 | - dependency-report
105 | - unit-tests
106 | workspaces:
107 | - name: source
108 | workspace: workspace
109 | - name: maven-settings
110 | workspace: maven-settings
111 | params:
112 | - name: GOALS
113 | value:
114 | - deploy
115 | - -f
116 | - spring-petclinic
117 | - -DskipTests=true
118 | - -DaltDeploymentRepository=nexus::default::http://nexus:8081/repository/maven-releases/
119 | - -DaltSnapshotDeploymentRepository=nexus::default::http://nexus:8081/repository/maven-snapshots/
120 | - name: build-image
121 | taskRef:
122 | name: s2i-java-11
123 | runAfter:
124 | - release-app
125 | params:
126 | - name: TLSVERIFY
127 | value: "false"
128 | - name: MAVEN_MIRROR_URL
129 | value: http://nexus:8081/repository/maven-public/
130 | - name: PATH_CONTEXT
131 | value: spring-petclinic/target
132 | - name: IMAGE_NAME
133 | value: $(params.APP_IMAGE)
134 | - name: IMAGE_TAG
135 | value: $(params.APP_IMAGE_TAG)
136 | workspaces:
137 | - name: source
138 | workspace: workspace
139 | - name: config-clone
140 | taskRef:
141 | name: git-clone
142 | kind: ClusterTask
143 | workspaces:
144 | - name: output
145 | workspace: workspace
146 | runAfter:
147 | - build-image
148 | params:
149 | - name: url
150 | value: $(params.APP_CONFIG_GIT)
151 | - name: subdirectory
152 | value: spring-petclinic-config
153 | - name: deleteExisting
154 | value: "true"
155 | - name: tests-clone
156 | taskRef:
157 | name: git-clone
158 | kind: ClusterTask
159 | workspaces:
160 | - name: output
161 | workspace: workspace
162 | runAfter:
163 | - build-image
164 | params:
165 | - name: url
166 | value: $(params.APP_TESTS_GIT)
167 | - name: subdirectory
168 | value: spring-petclinic-gatling
169 | - name: deleteExisting
170 | value: "true"
171 | - name: deploy-dev
172 | taskRef:
173 | name: deploy-app
174 | runAfter:
175 | - config-clone
176 | - tests-clone
177 | params:
178 | - name: DEPLOYMENT_NAME
179 | value: spring-petclinic
180 | - name: CURRENT_IMAGE
181 | value: "quay.io/siamaksade/spring-petclinic:latest"
182 | - name: NEW_IMAGE_NAME
183 | value: $(params.APP_IMAGE)
184 | - name: NEW_IMAGE_TAG
185 | value: $(params.APP_IMAGE_TAG)
186 | - name: NEW_IMAGE_DIGEST
187 | value: $(tasks.build-image.results.IMAGE_DIGEST)
188 | - name: NAMESPACE
189 | value: demo-dev
190 | - name: KUSTOMIZE_OVERLAY_DIR
191 | value: environments/dev
192 | workspaces:
193 | - name: source
194 | workspace: workspace
195 | subPath: spring-petclinic-config
196 | - name: int-test
197 | taskRef:
198 | name: openshift-client
199 | kind: ClusterTask
200 | runAfter:
201 | - deploy-dev
202 | params:
203 | - name: SCRIPT
204 | value: |
205 | sleep $(($RANDOM % 40 + 20))
206 | - name: perf-test
207 | taskRef:
208 | name: gatling
209 | runAfter:
210 | - deploy-dev
211 | params:
212 | - name: APP_URL
213 | value: "http://spring-petclinic.demo-dev.svc.cluster.local:8080"
214 | workspaces:
215 | - name: simulations
216 | workspace: workspace
217 | subPath: spring-petclinic-gatling
--------------------------------------------------------------------------------
/pipelines/pipeline-deploy-stage.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: tekton.dev/v1beta1
2 | kind: Pipeline
3 | metadata:
4 | name: petclinic-deploy-stage
5 | spec:
6 | params:
7 | - name: APP_CONFIG_GIT
8 | type: string
9 | description: The application configuration git repository
10 | default: https://github.com/siamaksade/spring-petclinic-config
11 | - name: APP_TESTS_GIT
12 | type: string
13 | description: The application test cases git repository
14 | default: https://github.com/siamaksade/spring-petclinic-gatling
15 | - name: APP_IMAGE_NAME
16 | type: string
17 | default: image-registry.openshift-image-registry.svc:5000/demo-dev/spring-petclinic
18 | description: The application image to deploy to stage
19 | - name: APP_IMAGE_TAG
20 | type: string
21 | default: "latest"
22 | description: The application image tag to deploy to stage
23 | # - name: APP_IMAGE_DIGEST
24 | # type: string
25 | # default: ""
26 | # description: The application image digest to deploy to stage
27 | - name: STAGE_NAMESPACE
28 | type: string
29 | default: demo-stage
30 | description: The namespace for Stage environments
31 | workspaces:
32 | - name: workspace
33 | tasks:
34 | - name: config-clone
35 | taskRef:
36 | name: git-clone
37 | kind: ClusterTask
38 | workspaces:
39 | - name: output
40 | workspace: workspace
41 | params:
42 | - name: url
43 | value: $(params.APP_CONFIG_GIT)
44 | - name: subdirectory
45 | value: spring-petclinic-config
46 | - name: deleteExisting
47 | value: "true"
48 | - name: tests-clone
49 | taskRef:
50 | name: git-clone
51 | kind: ClusterTask
52 | workspaces:
53 | - name: output
54 | workspace: workspace
55 | runAfter:
56 | - config-clone
57 | params:
58 | - name: url
59 | value: $(params.APP_TESTS_GIT)
60 | - name: subdirectory
61 | value: spring-petclinic-gatling
62 | - name: deleteExisting
63 | value: "true"
64 | - name: deploy-stage
65 | taskRef:
66 | name: deploy-app
67 | runAfter:
68 | - config-clone
69 | params:
70 | - name: DEPLOYMENT_NAME
71 | value: spring-petclinic
72 | - name: CURRENT_IMAGE
73 | value: "quay.io/siamaksade/spring-petclinic:latest"
74 | - name: NEW_IMAGE_NAME
75 | value: $(params.APP_IMAGE_NAME)
76 | - name: NEW_IMAGE_TAG
77 | value: $(params.APP_IMAGE_TAG)
78 | - name: NAMESPACE
79 | value: $(params.STAGE_NAMESPACE)
80 | - name: KUSTOMIZE_OVERLAY_DIR
81 | value: environments/stage
82 | workspaces:
83 | - name: source
84 | workspace: workspace
85 | subPath: spring-petclinic-config
86 | - name: test-stage
87 | taskRef:
88 | name: gatling
89 | runAfter:
90 | - deploy-stage
91 | - tests-clone
92 | params:
93 | - name: APP_URL
94 | value: "http://spring-petclinic.$(params.STAGE_NAMESPACE).svc.cluster.local:8080"
95 | workspaces:
96 | - name: simulations
97 | workspace: workspace
98 | subPath: spring-petclinic-gatling
--------------------------------------------------------------------------------
/runs/pipeline-deploy-dev-run.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: tekton.dev/v1beta1
2 | kind: PipelineRun
3 | metadata:
4 | generateName: petclinic-deploy-dev-
5 | spec:
6 | pipelineRef:
7 | name: petclinic-deploy-dev
8 | workspaces:
9 | - name: workspace
10 | persistentVolumeClaim:
11 | claimName: petclinic-dev-workspace
12 | - name: maven-settings
13 | configMap:
14 | name: maven-settings
--------------------------------------------------------------------------------
/runs/pipeline-deploy-stage-run.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: tekton.dev/v1beta1
2 | kind: PipelineRun
3 | metadata:
4 | generateName: petclinic-deploy-stage-
5 | spec:
6 | pipelineRef:
7 | name: petclinic-deploy-stage
8 | workspaces:
9 | - name: workspace
10 | persistentVolumeClaim:
11 | claimName: petclinic-stage-workspace
--------------------------------------------------------------------------------
/tasks/dependency-report-task.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: tekton.dev/v1beta1
2 | kind: Task
3 | metadata:
4 | name: dependency-report
5 | annotations:
6 | tekton.dev/pipelines.minVersion: 0.12.1
7 | spec:
8 | params:
9 | - name: SOURCE_DIR
10 | description: The directory within the workspace where application source is located
11 | default: "."
12 | - name: REPORTS_REPO_HOST
13 | description: The reports repository host based on https://github.com/chmouel/openshift-django-uploader
14 | default: http://reports-repo:8080
15 | - name: REPORTS_REPO_USERNAME
16 | description: The reports repository username
17 | default: reports
18 | - name: REPORTS_REPO_PASSWORD
19 | description: The reports repository password
20 | default: reports
21 | - default: ''
22 | description: The Maven repository mirror url
23 | name: MAVEN_MIRROR_URL
24 | type: string
25 | - default: ''
26 | description: The username for the proxy server
27 | name: PROXY_USER
28 | type: string
29 | - default: ''
30 | description: The password for the proxy server
31 | name: PROXY_PASSWORD
32 | type: string
33 | - default: ''
34 | description: Port number for the proxy server
35 | name: PROXY_PORT
36 | type: string
37 | - default: ''
38 | description: Proxy server Host
39 | name: PROXY_HOST
40 | type: string
41 | - default: ''
42 | description: Non proxy server host
43 | name: PROXY_NON_PROXY_HOSTS
44 | type: string
45 | - default: http
46 | description: Protocol for the proxy ie http or https
47 | name: PROXY_PROTOCOL
48 | type: string
49 | workspaces:
50 | - description: The workspace consisting of maven project.
51 | name: source
52 | - description: The workspace consisting of the custom maven settings provided by the user.
53 | name: maven-settings
54 | steps:
55 | - image: 'registry.access.redhat.com/ubi8/ubi-minimal:latest'
56 | name: mvn-settings
57 | resources: {}
58 | script: >
59 | #!/usr/bin/env bash
60 |
61 |
62 | [[ -f $(workspaces.maven-settings.path)/settings.xml ]] && \
63 |
64 | echo 'using existing $(workspaces.maven-settings.path)/settings.xml' &&
65 | exit 0
66 |
67 |
68 | cat > $(workspaces.maven-settings.path)/settings.xml <
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | EOF
82 |
83 |
84 | xml=""
85 |
86 | if [ -n "$(params.PROXY_HOST)" -a -n "$(params.PROXY_PORT)" ]; then
87 | xml="\
88 | genproxy\
89 | true\
90 | $(params.PROXY_PROTOCOL)\
91 | $(params.PROXY_HOST)\
92 | $(params.PROXY_PORT)"
93 | if [ -n "$(params.PROXY_USER)" -a -n "$(params.PROXY_PASSWORD)" ]; then
94 | xml="$xml\
95 | $(params.PROXY_USER)\
96 | $(params.PROXY_PASSWORD)"
97 | fi
98 | if [ -n "$(params.PROXY_NON_PROXY_HOSTS)" ]; then
99 | xml="$xml\
100 | $(params.PROXY_NON_PROXY_HOSTS)"
101 | fi
102 | xml="$xml\
103 | "
104 | sed -i "s||$xml|" $(workspaces.maven-settings.path)/settings.xml
105 | fi
106 |
107 |
108 | if [ -n "$(params.MAVEN_MIRROR_URL)" ]; then
109 | xml=" \
110 | mirror.default\
111 | $(params.MAVEN_MIRROR_URL)\
112 | central\
113 | "
114 | sed -i "s||$xml|" $(workspaces.maven-settings.path)/settings.xml
115 | fi
116 | - args:
117 | - -Dmaven.repo.local=$(workspaces.source.path)/.m2
118 | - -f
119 | - $(params.SOURCE_DIR)
120 | - -s
121 | - $(workspaces.maven-settings.path)/settings.xml
122 | - site
123 | - -DskipTests=true
124 | command:
125 | - /usr/bin/mvn
126 | image: gcr.io/cloud-builders/mvn
127 | name: mvn-goals
128 | resources: {}
129 | workingDir: $(workspaces.source.path)
130 | - name: archive-site
131 | workingDir: $(workspaces.source.path)
132 | image: registry.access.redhat.com/ubi8/ubi:latest
133 | env:
134 | - name: PIPELINERUN_NAME
135 | valueFrom:
136 | fieldRef:
137 | fieldPath: metadata.labels['tekton.dev/pipelineRun']
138 | script: |
139 | #!/usr/bin/env bash
140 |
141 | for f in $(find $(params.SOURCE_DIR)/target/site -type f); do
142 | curl -u $(params.REPORTS_REPO_USERNAME):$(params.REPORTS_REPO_PASSWORD) -F path=$PIPELINERUN_NAME/${f} -X POST -F file=@${f} $(params.REPORTS_REPO_HOST)/upload; echo ""
143 | done
--------------------------------------------------------------------------------
/tasks/deploy-app-task.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: tekton.dev/v1beta1
2 | kind: Task
3 | metadata:
4 | name: deploy-app
5 | spec:
6 | params:
7 | - name: DEPLOYMENT_NAME
8 | description: The name of deployment
9 | type: string
10 | - name: CURRENT_IMAGE
11 | description: The current image repo/image:tag in the manifests for the deployment
12 | type: string
13 | - name: NEW_IMAGE_NAME
14 | description: The new image repo/image to be deployed
15 | type: string
16 | - name: NEW_IMAGE_TAG
17 | description: The new image tag to be deployed
18 | type: string
19 | default: ""
20 | - name: NEW_IMAGE_DIGEST
21 | description: The digest of the new image to get deployed
22 | type: string
23 | default: ""
24 | - name: NAMESPACE
25 | description: The namespace for the deployment
26 | type: string
27 | - name: KUSTOMIZE_OVERLAY_DIR
28 | description: The subdirectory in configs git repo for the kustomize overlay to be applied
29 | workspaces:
30 | - description: The workspace consisting of maven project.
31 | name: source
32 | steps:
33 | - name: apply-manifests
34 | workingDir: $(workspaces.source.path)
35 | image: image-registry.openshift-image-registry.svc:5000/openshift/cli
36 | script: |
37 |
38 | find $(workspaces.source.path)
39 |
40 | cat >> $(workspaces.source.path)/$(params.KUSTOMIZE_OVERLAY_DIR)/kustomization.yaml <<- EOF
41 |
42 | images:
43 | - name: quay.io/siamaksade/spring-petclinic:latest
44 | newName: $(params.NEW_IMAGE_NAME)
45 | newTag: $(params.NEW_IMAGE_TAG)
46 | digest: $(params.NEW_IMAGE_DIGEST)
47 | EOF
48 |
49 | [[ "x$(params.NEW_IMAGE_DIGEST)" == "x" ]] && sed -i "/digest/d" $(workspaces.source.path)/$(params.KUSTOMIZE_OVERLAY_DIR)/kustomization.yaml
50 | [[ "x$(params.NEW_IMAGE_TAG)" == "x" ]] && sed -i "/newTag/d" $(workspaces.source.path)/$(params.KUSTOMIZE_OVERLAY_DIR)/kustomization.yaml
51 |
52 | echo "########################"
53 | echo "## kustomization.yaml ##"
54 | echo "########################"
55 |
56 | cat $(workspaces.source.path)/$(params.KUSTOMIZE_OVERLAY_DIR)/kustomization.yaml
57 |
58 | echo "######## DRY RUN #######"
59 | oc apply -k $(params.KUSTOMIZE_OVERLAY_DIR) --dry-run=client -o yaml -n $(params.NAMESPACE)
60 | echo "########################"
61 |
62 | oc apply -k $(params.KUSTOMIZE_OVERLAY_DIR) -n $(params.NAMESPACE)
63 | oc rollout status deploy/$(params.DEPLOYMENT_NAME) -n $(params.NAMESPACE)
64 |
--------------------------------------------------------------------------------
/tasks/gatling-task.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: tekton.dev/v1beta1
2 | kind: Task
3 | metadata:
4 | name: gatling
5 | spec:
6 | params:
7 | - name: DURATION
8 | description: The duration of running simulations
9 | type: string
10 | default: "30"
11 | - name: CONCURRENT_USERS
12 | description: The number of concurrent users
13 | type: string
14 | default: "10"
15 | - name: APP_URL
16 | description: The application under test url
17 | type: string
18 | - name: REPORTS_REPO_HOST
19 | description: The reports repository host based on https://github.com/chmouel/openshift-django-uploader
20 | default: http://reports-repo:8080
21 | - name: REPORTS_REPO_USERNAME
22 | description: The reports repository username
23 | default: reports
24 | - name: REPORTS_REPO_PASSWORD
25 | description: The reports repository password
26 | default: reports
27 | workspaces:
28 | - description: The workspace consisting of maven project.
29 | name: simulations
30 | steps:
31 | - name: run-tests
32 | image: quay.io/siamaksade/gatling:latest
33 | env:
34 | - name: PIPELINERUN_NAME
35 | valueFrom:
36 | fieldRef:
37 | fieldPath: metadata.labels['tekton.dev/pipelineRun']
38 | script: |
39 | #!/usr/bin/env bash
40 |
41 | # set simulation params
42 | export JAVA_OPTS="-DtestDuration=$(params.CONCURRENT_USERS) -DuserCount=$(params.DURATION) -Dserver=$(params.APP_URL)"
43 |
44 | # run simulation
45 | /opt/gatling/bin/gatling.sh -rd "Spring PetClinic Performance Test" -sf $(workspaces.simulations.path)
46 |
47 | # upload results
48 | REPORT=$(ls -td /opt/gatling/results/* | head -1)
49 | for f in $(find $REPORT/ -type f); do
50 | curl -u $(params.REPORTS_REPO_USERNAME):$(params.REPORTS_REPO_PASSWORD) -F path=$PIPELINERUN_NAME${f#/opt/gatling/results} -X POST -F file=@${f} $(params.REPORTS_REPO_HOST)/upload; echo ""
51 | done
--------------------------------------------------------------------------------
/tasks/mvn-task.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: tekton.dev/v1beta1
2 | kind: Task
3 | metadata:
4 | annotations:
5 | tekton.dev/pipelines.minVersion: 0.12.1
6 | tekton.dev/tags: build-tool
7 | name: maven
8 | labels:
9 | app.kubernetes.io/version: '0.1'
10 | operator.tekton.dev/provider-type: community
11 | spec:
12 | description: This Task can be used to run a Maven build.
13 | params:
14 | - default: gcr.io/cloud-builders/mvn:3.5.0-jdk-8
15 | description: Maven base image
16 | name: MAVEN_IMAGE
17 | type: string
18 | - default:
19 | - package
20 | description: maven goals to run
21 | name: GOALS
22 | type: array
23 | - default: ''
24 | description: The Maven repository mirror url
25 | name: MAVEN_MIRROR_URL
26 | type: string
27 | - default: ''
28 | description: The username for the proxy server
29 | name: PROXY_USER
30 | type: string
31 | - default: ''
32 | description: The password for the proxy server
33 | name: PROXY_PASSWORD
34 | type: string
35 | - default: ''
36 | description: Port number for the proxy server
37 | name: PROXY_PORT
38 | type: string
39 | - default: ''
40 | description: Proxy server Host
41 | name: PROXY_HOST
42 | type: string
43 | - default: ''
44 | description: Non proxy server host
45 | name: PROXY_NON_PROXY_HOSTS
46 | type: string
47 | - default: http
48 | description: Protocol for the proxy ie http or https
49 | name: PROXY_PROTOCOL
50 | type: string
51 | workspaces:
52 | - description: The workspace consisting of maven project.
53 | name: source
54 | - description: The workspace consisting of the custom maven settings provided by the user.
55 | name: maven-settings
56 | steps:
57 | - image: 'registry.access.redhat.com/ubi8/ubi-minimal:latest'
58 | name: mvn-settings
59 | resources: {}
60 | script: >
61 | #!/usr/bin/env bash
62 |
63 |
64 | [[ -f $(workspaces.maven-settings.path)/settings.xml ]] && \
65 |
66 | echo 'using existing $(workspaces.maven-settings.path)/settings.xml' &&
67 | exit 0
68 |
69 |
70 | cat > $(workspaces.maven-settings.path)/settings.xml <
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | EOF
84 |
85 |
86 | xml=""
87 |
88 | if [ -n "$(params.PROXY_HOST)" -a -n "$(params.PROXY_PORT)" ]; then
89 | xml="\
90 | genproxy\
91 | true\
92 | $(params.PROXY_PROTOCOL)\
93 | $(params.PROXY_HOST)\
94 | $(params.PROXY_PORT)"
95 | if [ -n "$(params.PROXY_USER)" -a -n "$(params.PROXY_PASSWORD)" ]; then
96 | xml="$xml\
97 | $(params.PROXY_USER)\
98 | $(params.PROXY_PASSWORD)"
99 | fi
100 | if [ -n "$(params.PROXY_NON_PROXY_HOSTS)" ]; then
101 | xml="$xml\
102 | $(params.PROXY_NON_PROXY_HOSTS)"
103 | fi
104 | xml="$xml\
105 | "
106 | sed -i "s||$xml|" $(workspaces.maven-settings.path)/settings.xml
107 | fi
108 |
109 |
110 | if [ -n "$(params.MAVEN_MIRROR_URL)" ]; then
111 | xml=" \
112 | mirror.default\
113 | $(params.MAVEN_MIRROR_URL)\
114 | central\
115 | "
116 | sed -i "s||$xml|" $(workspaces.maven-settings.path)/settings.xml
117 | fi
118 | - args:
119 | - -Dmaven.repo.local=$(workspaces.source.path)/.m2
120 | - '-s'
121 | - $(workspaces.maven-settings.path)/settings.xml
122 | - $(params.GOALS)
123 | command:
124 | - /usr/bin/mvn
125 | image: $(params.MAVEN_IMAGE)
126 | name: mvn-goals
127 | resources: {}
128 | workingDir: $(workspaces.source.path)
129 |
--------------------------------------------------------------------------------
/tasks/s2i-java-11-task.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: tekton.dev/v1beta1
2 | kind: Task
3 | metadata:
4 | name: s2i-java-11
5 | annotations:
6 | tekton.dev/displayName: s2i java 11
7 | tekton.dev/pipelines.minVersion: 0.11.3
8 | tekton.dev/tags: 's2i, java, workspace'
9 | spec:
10 | description: >-
11 | s2i-java-11 task clones a Git repository and builds and pushes a container
12 | image using S2I and a Java 11 builder image.
13 | params:
14 | - default: .
15 | description: The location of the path to run s2i from
16 | name: PATH_CONTEXT
17 | type: string
18 | - default: 'true'
19 | description: >-
20 | Verify the TLS on the registry endpoint (for push/pull to a non-TLS
21 | registry)
22 | name: TLSVERIFY
23 | type: string
24 | - default: ''
25 | description: Additional Maven arguments
26 | name: MAVEN_ARGS_APPEND
27 | type: string
28 | - default: 'false'
29 | description: Remove the Maven repository after the artifact is built
30 | name: MAVEN_CLEAR_REPO
31 | type: string
32 | - default: ''
33 | description: The base URL of a mirror used for retrieving artifacts
34 | name: MAVEN_MIRROR_URL
35 | type: string
36 | - description: Location of the repo where image has to be pushed
37 | name: IMAGE_NAME
38 | type: string
39 | - description: The tag of the image to be pushed
40 | name: IMAGE_TAG
41 | type: string
42 | default: "latest"
43 |
44 | results:
45 | - name: IMAGE_DIGEST
46 | description: Digest of the image just built.
47 | steps:
48 | - args:
49 | - |-
50 | echo "MAVEN_CLEAR_REPO=$(params.MAVEN_CLEAR_REPO)" > env-file
51 |
52 | [[ '$(params.MAVEN_ARGS_APPEND)' != "" ]] &&
53 | echo "MAVEN_ARGS_APPEND=$(params.MAVEN_ARGS_APPEND)" >> env-file
54 |
55 | [[ '$(params.MAVEN_MIRROR_URL)' != "" ]] &&
56 | echo "MAVEN_MIRROR_URL=$(params.MAVEN_MIRROR_URL)" >> env-file
57 |
58 | echo "Generated Env file"
59 | echo "------------------------------"
60 | cat env-file
61 | echo "------------------------------"
62 | command:
63 | - /bin/sh
64 | - '-c'
65 | image: >-
66 | registry.redhat.io/ocp-tools-43-tech-preview/source-to-image-rhel8@sha256:562dbdac04ae9260e21d457585b3251fd8cc5310966f8fc544fb77dc544c92f8
67 | name: gen-env-file
68 | resources: {}
69 | volumeMounts:
70 | - mountPath: /env-params
71 | name: envparams
72 | workingDir: /env-params
73 | - command:
74 | - s2i
75 | - build
76 | - $(params.PATH_CONTEXT)
77 | - 'image-registry.openshift-image-registry.svc:5000/openshift/java:11'
78 | - '--image-scripts-url'
79 | - 'image:///usr/local/s2i'
80 | - '--as-dockerfile'
81 | - /gen-source/Dockerfile.gen
82 | - '--environment-file'
83 | - /env-params/env-file
84 | image: >-
85 | registry.redhat.io/ocp-tools-43-tech-preview/source-to-image-rhel8@sha256:562dbdac04ae9260e21d457585b3251fd8cc5310966f8fc544fb77dc544c92f8
86 | name: generate
87 | resources: {}
88 | volumeMounts:
89 | - mountPath: /gen-source
90 | name: gen-source
91 | - mountPath: /env-params
92 | name: envparams
93 | workingDir: $(workspaces.source.path)
94 | - command:
95 | - buildah
96 | - bud
97 | - '--storage-driver=vfs'
98 | - '--tls-verify=$(params.TLSVERIFY)'
99 | - '--layers'
100 | - '-f'
101 | - /gen-source/Dockerfile.gen
102 | - '-t'
103 | - $(params.IMAGE_NAME):$(params.IMAGE_TAG)
104 | - '-t'
105 | - $(params.IMAGE_NAME):latest
106 | - .
107 | image: >-
108 | registry.redhat.io/rhel8/buildah@sha256:180c4d9849b6ab0e5465d30d4f3a77765cf0d852ca1cb1efb59d6e8c9f90d467
109 | name: build
110 | resources: {}
111 | volumeMounts:
112 | - mountPath: /var/lib/containers
113 | name: varlibcontainers
114 | - mountPath: /gen-source
115 | name: gen-source
116 | workingDir: /gen-source
117 | - command:
118 | - buildah
119 | - push
120 | - '--storage-driver=vfs'
121 | - '--tls-verify=$(params.TLSVERIFY)'
122 | - --digestfile
123 | - $(workspaces.source.path)/image-digest
124 | - $(params.IMAGE_NAME):$(params.IMAGE_TAG)
125 | - 'docker://$(params.IMAGE_NAME):$(params.IMAGE_TAG)'
126 | image: registry.redhat.io/rhel8/buildah@sha256:180c4d9849b6ab0e5465d30d4f3a77765cf0d852ca1cb1efb59d6e8c9f90d467
127 | name: push-tag
128 | resources: {}
129 | volumeMounts:
130 | - mountPath: /var/lib/containers
131 | name: varlibcontainers
132 | - command:
133 | - buildah
134 | - push
135 | - '--storage-driver=vfs'
136 | - '--tls-verify=$(params.TLSVERIFY)'
137 | - --digestfile
138 | - $(workspaces.source.path)/image-digest
139 | - $(params.IMAGE_NAME):$(params.IMAGE_TAG)
140 | - 'docker://$(params.IMAGE_NAME):latest'
141 | image: registry.redhat.io/rhel8/buildah@sha256:180c4d9849b6ab0e5465d30d4f3a77765cf0d852ca1cb1efb59d6e8c9f90d467
142 | name: push-latest
143 | resources: {}
144 | volumeMounts:
145 | - mountPath: /var/lib/containers
146 | name: varlibcontainers
147 | - name: digest-to-results
148 | image: registry.redhat.io/rhel8/buildah@sha256:180c4d9849b6ab0e5465d30d4f3a77765cf0d852ca1cb1efb59d6e8c9f90d467
149 | script: cat $(workspaces.source.path)/image-digest | tee /tekton/results/IMAGE_DIGEST
150 | volumes:
151 | - emptyDir: {}
152 | name: varlibcontainers
153 | - emptyDir: {}
154 | name: gen-source
155 | - emptyDir: {}
156 | name: envparams
157 | workspaces:
158 | - mountPath: /workspace/source
159 | name: source
160 |
--------------------------------------------------------------------------------
/triggers/eventlistener.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: triggers.tekton.dev/v1alpha1
3 | kind: EventListener
4 | metadata:
5 | name: webhook
6 | spec:
7 | serviceAccountName: pipeline
8 | triggers:
9 | - name: petclinic-webhook
10 | interceptors:
11 | - cel:
12 | overlays:
13 | - key: short_sha
14 | expression: "body.after.truncate(7)"
15 | - key: branch_name
16 | expression: "body.ref.split('/')[2]"
17 | bindings:
18 | - ref: gogs-triggerbinding
19 | template:
20 | name: petclinic-trigger-template
21 | ---
22 | apiVersion: route.openshift.io/v1
23 | kind: Route
24 | metadata:
25 | name: webhook
26 | labels:
27 | app.kubernetes.io/managed-by: EventListener
28 | app.kubernetes.io/part-of: Triggers
29 | eventlistener: webhook
30 | spec:
31 | port:
32 | targetPort: 8080
33 | to:
34 | kind: "Service"
35 | name: el-webhook
36 | weight: 100
37 |
--------------------------------------------------------------------------------
/triggers/gogs-triggerbinding.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: triggers.tekton.dev/v1alpha1
3 | kind: TriggerBinding
4 | metadata:
5 | name: gogs-triggerbinding
6 | spec:
7 | params:
8 | - name: gitrevision
9 | value: $(body.after)
10 | - name: gitshortsha
11 | value: $(body.short_sha)
12 | - name: gitbranchname
13 | value: $(body.branch_name)
14 | - name: gitrepositoryurl
15 | value: $(body.repository.clone_url)
16 | - name: contenttype
17 | value: $(header.Content-Type)
--------------------------------------------------------------------------------
/triggers/triggertemplate.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | apiVersion: triggers.tekton.dev/v1alpha1
3 | kind: TriggerTemplate
4 | metadata:
5 | name: petclinic-trigger-template
6 | spec:
7 | params:
8 | - name: gitrevision
9 | description: The git revision
10 | default: master
11 | - name: gitshortsha
12 | description: The short commit sha
13 | default: master
14 | - name: gitbranchname
15 | description: The branch name
16 | default: master
17 | - name: gitrepositoryurl
18 | description: The git repository url
19 | - name: message
20 | description: The message to print
21 | default: This is the default message
22 | - name: contenttype
23 | description: The Content-Type of the event
24 | resourcetemplates:
25 | - apiVersion: tekton.dev/v1beta1
26 | kind: PipelineRun
27 | metadata:
28 | generateName: petclinic-deploy-dev-
29 | # name: petclinic-dev-$(tt.params.gitbranchname)-$(tt.params.gitshortsha)
30 | labels:
31 | tekton.dev/pipeline: petclinic-deploy-dev
32 | spec:
33 | pipelineRef:
34 | name: petclinic-deploy-dev
35 | params:
36 | - name: APP_SOURCE_GIT
37 | value: $(tt.params.gitrepositoryurl)
38 | - name: APP_SOURCE_REVISION
39 | value: $(tt.params.gitrevision)
40 | - name: APP_IMAGE_TAG
41 | value: $(tt.params.gitbranchname)-$(tt.params.gitshortsha)
42 | workspaces:
43 | - name: maven-settings
44 | configMap:
45 | name: maven-settings
46 | - name: workspace
47 | persistentVolumeClaim:
48 | claimName: petclinic-dev-workspace
--------------------------------------------------------------------------------