Skip to content

Commit 3b90452

Browse files
committed
Add support for Slack notifications
We need to add more monitoring on the pipeline. Otherwise it's going to be very easy to go red for a few days without noticing. My initial goal was to hook up to IRC, but the reality is that I think we'll need both Slack and IRC because many folks mostly live in Slack nowadays. (That said, I still fully intend to add IRC support via fedmsgs as discussed in coreos#41). Now, how this patch works is that we add two new Jenkins plugins: - configuration-as-code - slack The first one is used to configure the second one. More broadly, it's able to configure almost all of Jenkins and its plugins via YAML instead of dropping to XML, so we'll likely be leveraging it some more in the future. The actual configuration bit here is more or less the same as RHCOS, with some minor variations (we use secrets instead of defining the token at template generation time, and we just set a default channel instead of passing it through an env var) Of course, this is all still optional. The local developer workflow should still work fine.
1 parent a608949 commit 3b90452

File tree

5 files changed

+110
-3
lines changed

5 files changed

+110
-3
lines changed

HACKING.md

+15-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ If you're planning to test changes, it would be best to fork
163163
this repo so that you do your work there. The workflow
164164
requires a remote repo to which to push changes.
165165

166-
### Creating AWS credentials configs
166+
### [OPTIONAL] Creating AWS credentials configs
167167

168168
If you are in production where we upload builds to S3 OR you want to
169169
test uploading to S3 as part of your pipeline development, you need to
@@ -217,6 +217,20 @@ $ aws s3 mb my-fcos-bucket
217217

218218
And provide it to `--bucket` below.
219219

220+
### [OPTIONAL] Slack integration
221+
222+
If you want to be able to have build status messages appear in Slack,
223+
create a `slack-api-token` secret:
224+
225+
```
226+
$ echo -n "$TOKEN" > slack-token
227+
$ oc create secret generic slack-api-token --from-file=token=slack-token
228+
```
229+
230+
You can obtain a token (Slack calls this the "Integration Token
231+
Credential ID") when creating a new instance of the Jenkins CI app in
232+
your Slack workspace.
233+
220234
### Create a Jenkins instance with a persistent volume backing store
221235

222236
```

Jenkinsfile

+40-2
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ echo "Final podspec: ${pod}"
133133
podTemplate(cloud: 'openshift', label: 'coreos-assembler', yaml: pod) {
134134
node('coreos-assembler') { container('coreos-assembler') {
135135

136+
// declare this early so we can use it in Slack
137+
def newBuildID
138+
139+
try {
140+
136141
// this is defined IFF we *should* and we *can* upload to S3
137142
def s3_stream_dir
138143

@@ -227,12 +232,13 @@ podTemplate(cloud: 'openshift', label: 'coreos-assembler', yaml: pod) {
227232
""")
228233
}
229234

230-
def newBuildID = utils.shwrap_capture("readlink builds/latest")
231-
if (prevBuildID == newBuildID) {
235+
def buildID = utils.shwrap_capture("readlink builds/latest")
236+
if (prevBuildID == buildID) {
232237
currentBuild.result = 'SUCCESS'
233238
currentBuild.description = "[${params.STREAM}] 💤 (no new build)"
234239
return
235240
} else {
241+
newBuildID = buildID
236242
currentBuild.description = "[${params.STREAM}] ⚡ ${newBuildID}"
237243

238244
// and insert the parent info into meta.json so we can display it in
@@ -439,5 +445,37 @@ podTemplate(cloud: 'openshift', label: 'coreos-assembler', yaml: pod) {
439445
}
440446
}
441447
}
448+
449+
} catch (e) {
450+
currentBuild.result = 'FAILURE'
451+
throw e
452+
} finally {
453+
def color
454+
def message = "[${params.STREAM}] <${env.BUILD_URL}|${env.BUILD_NUMBER}>"
455+
456+
if (currentBuild.result == 'SUCCESS') {
457+
if (!newBuildID) {
458+
// SUCCESS, but no new builds? Must've been a no-op
459+
return
460+
}
461+
message = ":fcos: :sparkles: ${message} - SUCCESS"
462+
color = 'good';
463+
} else {
464+
message = ":fcos: :trashfire: ${message} - FAILURE"
465+
color = 'danger';
466+
}
467+
468+
if (newBuildID) {
469+
message = "${message} (${newBuildID})"
470+
}
471+
472+
try {
473+
if (official) {
474+
slackSend(color: color, message: message)
475+
}
476+
} finally {
477+
echo message
478+
}
479+
}
442480
}}
443481
}

jenkins/master/plugins.txt

+2
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
github-oauth:0.33
2+
configuration-as-code:1.33
3+
slack:2.34

manifests/jenkins.yaml

+20
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ objects:
7474
value: "true"
7575
- name: JNLP_SERVICE_NAME
7676
value: ${JNLP_SERVICE_NAME}
77+
# DELTA: point c-as-c plugin to config map files; see below
78+
- name: CASC_JENKINS_CONFIG
79+
value: /var/lib/jenkins/configuration-as-code
7780
image: ' '
7881
imagePullPolicy: IfNotPresent
7982
livenessProbe:
@@ -100,13 +103,30 @@ objects:
100103
volumeMounts:
101104
- mountPath: /var/lib/jenkins
102105
name: ${JENKINS_SERVICE_NAME}-data
106+
# DELTA: mount c-as-c config map
107+
- name: ${JENKINS_SERVICE_NAME}-casc-cfg
108+
mountPath: /var/lib/jenkins/configuration-as-code
109+
readOnly: true
110+
# DELTA: mount Slack token; see below
111+
- name: slack-token
112+
mountPath: /var/run/secrets/slack-api-token
113+
readOnly: true
103114
dnsPolicy: ClusterFirst
104115
restartPolicy: Always
105116
serviceAccountName: ${JENKINS_SERVICE_NAME}
106117
volumes:
107118
- name: ${JENKINS_SERVICE_NAME}-data
108119
persistentVolumeClaim:
109120
claimName: ${JENKINS_SERVICE_NAME}
121+
# DELTA: add a configmap -- it's defined in pipeline.yaml
122+
- name: ${JENKINS_SERVICE_NAME}-casc-cfg
123+
configMap:
124+
name: jenkins-casc-cfg
125+
# DELTA: add the Slack token
126+
- name: slack-token
127+
secret:
128+
secretName: slack-api-token
129+
optional: true
110130
triggers:
111131
- imageChangeParams:
112132
automatic: true

manifests/pipeline.yaml

+33
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ parameters:
4444
- description: Whether to use KVM device plugin or legacy OCI KVM hook
4545
name: KVM_SELECTOR
4646
value: kvm-device-plugin
47+
- description: Slack domain on which to post build status updates
48+
name: SLACK_DOMAIN
49+
value: coreos
50+
- description: Slack channel on which to post build status updates
51+
name: SLACK_CHANNEL
52+
value: jenkins-coreos
4753

4854
objects:
4955

@@ -123,6 +129,33 @@ objects:
123129
importPolicy:
124130
scheduled: true
125131

132+
### JENKINS CONFIGURATION ###
133+
134+
# this uses the configuration-as-code plugin:
135+
# https://github.com/jenkinsci/configuration-as-code-plugin
136+
- apiVersion: v1
137+
kind: ConfigMap
138+
metadata:
139+
name: jenkins-casc-cfg
140+
annotations:
141+
coreos.com/deploy-default: "true"
142+
data:
143+
jenkins.yaml: |
144+
credentials:
145+
system:
146+
domainCredentials:
147+
- credentials:
148+
- string:
149+
scope: GLOBAL
150+
id: slack-token
151+
secret: ${slack-api-token/token}
152+
description: Slack API token
153+
unclassified:
154+
slackNotifier:
155+
teamDomain: ${SLACK_DOMAIN}
156+
tokenCredentialId: slack-token
157+
room: "#${SLACK_CHANNEL}"
158+
126159
### COREOS-ASSEMBLER ###
127160

128161
# keep a local copy of coreos-assembler so we're not constantly pulling it

0 commit comments

Comments
 (0)