Skip to content

Commit d899cd0

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 7bd8546 commit d899cd0

File tree

5 files changed

+107
-3
lines changed

5 files changed

+107
-3
lines changed

HACKING.md

+11-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,16 @@ $ 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+
220230
### Create a Jenkins instance with a persistent volume backing store
221231

222232
```

Jenkinsfile

+40-2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ node {
125125
podTemplate(cloud: 'openshift', label: 'coreos-assembler', yaml: pod, defaultContainer: 'jnlp') {
126126
node('coreos-assembler') { container('coreos-assembler') {
127127

128+
// declare this early so we can use it in Slack
129+
def newBuildID
130+
131+
try {
132+
128133
// this is defined IFF we *should* and we *can* upload to S3
129134
def s3_stream_dir
130135

@@ -219,12 +224,13 @@ podTemplate(cloud: 'openshift', label: 'coreos-assembler', yaml: pod, defaultCon
219224
""")
220225
}
221226

222-
def newBuildID = utils.shwrap_capture("readlink builds/latest")
223-
if (prevBuildID == newBuildID) {
227+
def buildID = utils.shwrap_capture("readlink builds/latest")
228+
if (prevBuildID == buildId) {
224229
currentBuild.result = 'SUCCESS'
225230
currentBuild.description = "[${params.STREAM}] 💤 (no new build)"
226231
return
227232
} else {
233+
newBuildID = buildID
228234
currentBuild.description = "[${params.STREAM}] ⚡ ${newBuildID}"
229235

230236
// and insert the parent info into meta.json so we can display it in
@@ -423,5 +429,37 @@ podTemplate(cloud: 'openshift', label: 'coreos-assembler', yaml: pod, defaultCon
423429
}
424430
}
425431
}
432+
433+
} catch (e) {
434+
currentBuild.result = 'FAILURE'
435+
throw e
436+
} finally {
437+
def color
438+
def message = "[${params.STREAM}] <${env.BUILD_URL}|${env.BUILD_NUMBER}>"
439+
440+
if (currentBuild.result == 'SUCCESS') {
441+
if (!newBuildID) {
442+
// SUCCESS, but no new builds? Must've been a no-op
443+
return
444+
}
445+
message = ":fcos: :sparkles: ${message} - SUCCESS"
446+
color = 'good';
447+
} else {
448+
message = ":fcos: :trashfire: ${message} - FAILURE"
449+
color = 'danger';
450+
}
451+
452+
if (newBuildID) {
453+
message = "${message} (${newBuildID})"
454+
}
455+
456+
try {
457+
if (official) {
458+
slackSend(color: color, message: message)
459+
}
460+
} finally {
461+
echo message
462+
}
463+
}
426464
}}
427465
}

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/jcasc
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}-cfg
108+
mountPath: /var/lib/jenkins/jcasc
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}-cfg
123+
configMap:
124+
name: jenkins-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

+34
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,34 @@ 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-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+
159+
126160
### COREOS-ASSEMBLER ###
127161

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

0 commit comments

Comments
 (0)