Skip to content

Commit

Permalink
Add support for Slack notifications
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jlebon authored and dustymabe committed Dec 17, 2019
1 parent a608949 commit 1e95f44
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 3 deletions.
15 changes: 14 additions & 1 deletion HACKING.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ If you're planning to test changes, it would be best to fork
this repo so that you do your work there. The workflow
requires a remote repo to which to push changes.

### Creating AWS credentials configs
### [OPTIONAL] Creating AWS credentials configs

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

And provide it to `--bucket` below.

### [OPTIONAL] Slack integration

If you want to be able to have build status messages appear in Slack,
create a `slack-api-token` secret:

```
$ echo -n "$TOKEN" > slack-token
$ oc create secret generic slack-api-token --from-file=token=slack-token
```

You can obtain a token when creating a new instance of the Jenkins CI
app in your Slack workspace.

### Create a Jenkins instance with a persistent volume backing store

```
Expand Down
43 changes: 41 additions & 2 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ echo "Final podspec: ${pod}"
podTemplate(cloud: 'openshift', label: 'coreos-assembler', yaml: pod) {
node('coreos-assembler') { container('coreos-assembler') {

// declare this early so we can use it in Slack
def newBuildID

try {

// this is defined IFF we *should* and we *can* upload to S3
def s3_stream_dir

Expand Down Expand Up @@ -227,12 +232,13 @@ podTemplate(cloud: 'openshift', label: 'coreos-assembler', yaml: pod) {
""")
}

def newBuildID = utils.shwrap_capture("readlink builds/latest")
if (prevBuildID == newBuildID) {
def buildID = utils.shwrap_capture("readlink builds/latest")
if (prevBuildID == buildID) {
currentBuild.result = 'SUCCESS'
currentBuild.description = "[${params.STREAM}] 💤 (no new build)"
return
} else {
newBuildID = buildID
currentBuild.description = "[${params.STREAM}] ⚡ ${newBuildID}"

// and insert the parent info into meta.json so we can display it in
Expand Down Expand Up @@ -439,5 +445,38 @@ podTemplate(cloud: 'openshift', label: 'coreos-assembler', yaml: pod) {
}
}
}

// main try {} finishes here
} catch (e) {
currentBuild.result = 'FAILURE'
throw e
} finally {
def color
def message = "[${params.STREAM}] <${env.BUILD_URL}|${env.BUILD_NUMBER}>"

if (currentBuild.result == 'SUCCESS') {
if (!newBuildID) {
// SUCCESS, but no new builds? Must've been a no-op
return
}
message = ":fcos: :sparkles: ${message} - SUCCESS"
color = 'good';
} else {
message = ":fcos: :trashfire: ${message} - FAILURE"
color = 'danger';
}

if (newBuildID) {
message = "${message} (${newBuildID})"
}

try {
if (official) {
slackSend(color: color, message: message)
}
} finally {
echo message
}
}
}}
}
2 changes: 2 additions & 0 deletions jenkins/master/plugins.txt
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
github-oauth:0.33
configuration-as-code:1.33
slack:2.34
20 changes: 20 additions & 0 deletions manifests/jenkins.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ objects:
value: "true"
- name: JNLP_SERVICE_NAME
value: ${JNLP_SERVICE_NAME}
# DELTA: point c-as-c plugin to config map files; see below
- name: CASC_JENKINS_CONFIG
value: /var/lib/jenkins/configuration-as-code
image: ' '
imagePullPolicy: IfNotPresent
livenessProbe:
Expand All @@ -100,13 +103,30 @@ objects:
volumeMounts:
- mountPath: /var/lib/jenkins
name: ${JENKINS_SERVICE_NAME}-data
# DELTA: mount c-as-c config map
- name: ${JENKINS_SERVICE_NAME}-casc-cfg
mountPath: /var/lib/jenkins/configuration-as-code
readOnly: true
# DELTA: mount Slack token; see below
- name: slack-token
mountPath: /var/run/secrets/slack-api-token
readOnly: true
dnsPolicy: ClusterFirst
restartPolicy: Always
serviceAccountName: ${JENKINS_SERVICE_NAME}
volumes:
- name: ${JENKINS_SERVICE_NAME}-data
persistentVolumeClaim:
claimName: ${JENKINS_SERVICE_NAME}
# DELTA: add a configmap -- it's defined in pipeline.yaml
- name: ${JENKINS_SERVICE_NAME}-casc-cfg
configMap:
name: jenkins-casc-cfg
# DELTA: add the Slack token
- name: slack-token
secret:
secretName: slack-api-token
optional: true
triggers:
- imageChangeParams:
automatic: true
Expand Down
33 changes: 33 additions & 0 deletions manifests/pipeline.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ parameters:
- description: Whether to use KVM device plugin or legacy OCI KVM hook
name: KVM_SELECTOR
value: kvm-device-plugin
- description: Slack domain on which to post build status updates
name: SLACK_DOMAIN
value: coreos
- description: Slack channel on which to post build status updates
name: SLACK_CHANNEL
value: jenkins-coreos

objects:

Expand Down Expand Up @@ -123,6 +129,33 @@ objects:
importPolicy:
scheduled: true

### JENKINS CONFIGURATION ###

# this uses the configuration-as-code plugin:
# https://github.com/jenkinsci/configuration-as-code-plugin
- apiVersion: v1
kind: ConfigMap
metadata:
name: jenkins-casc-cfg
annotations:
coreos.com/deploy-default: "true"
data:
jenkins.yaml: |
credentials:
system:
domainCredentials:
- credentials:
- string:
scope: GLOBAL
id: slack-token
secret: ${slack-api-token/token}
description: Slack API token
unclassified:
slackNotifier:
teamDomain: ${SLACK_DOMAIN}
tokenCredentialId: slack-token
room: "#${SLACK_CHANNEL}"
### COREOS-ASSEMBLER ###

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

0 comments on commit 1e95f44

Please sign in to comment.