Skip to content

Commit a62c29b

Browse files
author
Doug Davis
committed
add kafka and github
Signed-off-by: Doug Davis <dug@us.ibm.com>
1 parent d099c44 commit a62c29b

7 files changed

Lines changed: 244 additions & 0 deletions

File tree

‎README.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,12 @@ is demonstrating.
177177
new files in the bucket and then uploading a new object into a secondary
178178
bucket. It can also get Cron events to periodically check for missed
179179
files.
180+
- [github](github)<br>
181+
This sample will show how to get events from Github (via its webhooks)
182+
delivered to a Code Engine Application.
183+
- [kafka](kafka)<br>
184+
This sample shows how to create a Kafka subscription to automatically have
185+
messages in a Kafka instances delivered to an application.
180186

181187
#### Misc
182188
- [configmaps-env](configmaps-env)<br>

‎github/Dockerfile‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
FROM golang:alpine
2+
COPY github.go /
3+
RUN go build -o /github /github.go
4+
5+
# Copy the exe into a smaller base image
6+
FROM alpine
7+
COPY --from=0 /github /github
8+
CMD /github

‎github/README.md‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Github
2+
3+
This sample will show how to get events from Github (via its webhooks)
4+
delivered to a Code Engine Application. In this case the Application will
5+
look for a "push" even and then pretend to kick off a new build for that
6+
repository. While the code in here doesn't do the build itself, to keep it
7+
simple, if you combine this sample with the "cecli" sample you should be
8+
able to do a full build pipeline.
9+
10+
In this sample we simulate the event from github via a "curl" command
11+
sending the "sample-commit" file as the event. In a real scenario you'll
12+
want to setup your github repo to send "push" events to your Code Engine
13+
application. You can do that by:
14+
- going to your repo's "setting"
15+
- click on "Webhooks"
16+
- press "Add webhook" button
17+
- in the "Payload URL" field put the URL to your Code Engine application
18+
- in the "Content type" drop-down, select "application/json"
19+
- In the "Secret" field entry some random string. This will be used to
20+
verify that the event it coming from your repo
21+
- leave "Just the push event." radio button selected
22+
- press "Add webhook"
23+
24+
You should immediately see a "ping" event sent to your application as a
25+
test.
26+
27+
- - -
28+
29+
As noted in [the main README](../README.md), this sample has two pieces:
30+
31+
- a `build` script which will build the container image(s) used
32+
- a `run` script which deploys resources that use those images
33+
34+
The main purpose of this example is the `run` script, but the `build`
35+
script is included for complete educational (and reuse) purposes.

‎github/build‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/bash
2+
3+
# Env Vars:
4+
# REGISTRY: name of the image registry/namespace to store the images
5+
# NOCACHE: set this to "--no-cache" to turn off the Docker build cache
6+
#
7+
# NOTE: to run this you MUST set the REGISTRY environment variable to
8+
# your own image registry/namespace otherwise the `docker push` commands
9+
# will fail due to an auth failure. Which means, you also need to be logged
10+
# into that registry before you run it.
11+
12+
set -ex
13+
export REGISTRY=${REGISTRY:-icr.io/codeengine}
14+
15+
# Build the image
16+
docker build ${NOCACHE} -t ${REGISTRY}/github .
17+
18+
# And push it
19+
docker push ${REGISTRY}/github

‎github/github.go‎

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package main
2+
3+
import (
4+
"crypto/hmac"
5+
"crypto/sha1"
6+
"encoding/hex"
7+
"encoding/json"
8+
"io/ioutil"
9+
"log"
10+
"net/http"
11+
"os"
12+
)
13+
14+
// To verify events are from out github webhook set this to the "secert"
15+
// we set on the github webhook. Leave it blank to skip the check.
16+
var GitHubSecret = os.Getenv("GIT_SECRET")
17+
18+
// Verify the incoming github event by checking its signature against
19+
// the SHA of the body, using our GIT_SECRET as the key
20+
func VerifyEvent(req *http.Request, body []byte, secret string) bool {
21+
sig := req.Header.Get("X-HUB-SIGNATURE")
22+
if len(sig) != 45 || sig[:5] != "sha1=" {
23+
return false
24+
}
25+
calc := make([]byte, 20)
26+
hex.Decode(calc, []byte(sig[5:]))
27+
mac := hmac.New(sha1.New, []byte(secret))
28+
mac.Write(body)
29+
return hmac.Equal(calc, mac.Sum(nil))
30+
}
31+
32+
// Do whatever logic we need for the incoming event
33+
func ProcessEvent(eventType string, eventBody []byte) {
34+
log.Printf("Event Type: %s", eventType)
35+
36+
// Only care about "push" events
37+
if eventType != "push" {
38+
log.Print("Not a 'push' event so exit")
39+
return
40+
}
41+
42+
pretty, _ := json.MarshalIndent(json.RawMessage(eventBody), "", " ")
43+
log.Printf("\nEvent:\n%s", string(pretty))
44+
45+
// The following sample JSON is just a subset of the data in the event,
46+
// but has the key bits we care about:
47+
//
48+
// {
49+
// "ref": "refs/heads/master",
50+
// "before": "--commit-ID--",
51+
// "after": "--commit-ID--",
52+
// "repository": {
53+
// "name": "CodeEngine",
54+
// "full_name": "IBM/CodeEngin,
55+
// }
56+
// "pusher": {
57+
// "name": "github-id",
58+
// "email": "user-email"
59+
// },
60+
// "sender": {},
61+
// "commits": []
62+
// }
63+
64+
// Define a var/struct to hold the parsed event data
65+
PushEvent := struct {
66+
Ref string
67+
After string
68+
Repo struct {
69+
Name string
70+
FullName string
71+
}
72+
Pusher struct {
73+
Name string
74+
Email string
75+
}
76+
}{}
77+
78+
// Parse the event data into the PushEvent object
79+
err := json.Unmarshal(eventBody, &PushEvent)
80+
if err != nil {
81+
log.Printf("Error parsing:\n%s\n%s", err, string(eventBody))
82+
return
83+
}
84+
85+
// Only care about pushes to the "main" branch
86+
if PushEvent.Ref != "refs/heads/main" {
87+
log.Printf("Skipping branch: %s", PushEvent.Ref)
88+
return
89+
}
90+
91+
log.Printf("%s commited %q to %q branch",
92+
PushEvent.Pusher.Name, PushEvent.After, PushEvent.Ref)
93+
94+
// Now we'd normally do a build, but let's just fake it.
95+
// To see how to kick off CodeEngine CLI commands from inside of an app
96+
// see the "cecli" sample.
97+
log.Print("ibmcloud ce buildrun submit ...")
98+
}
99+
100+
// Simple web server that waits for incoming events, verifies they're
101+
// from our webhook (by using the GIT_SECRET, if set) and if ok process it
102+
func main() {
103+
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
104+
body, _ := ioutil.ReadAll(r.Body)
105+
106+
// Make sure it comes from our repo (if we want to check it at all)
107+
if GitHubSecret != "" && !VerifyEvent(r, body, GitHubSecret) {
108+
log.Printf("Error verifying github event")
109+
w.WriteHeader(http.StatusUnauthorized)
110+
return
111+
}
112+
113+
ProcessEvent(r.Header.Get("X-Github-Event"), body)
114+
})
115+
116+
log.Printf("Listening on port 8080")
117+
http.ListenAndServe(":8080", nil)
118+
}

‎github/run‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/bin/bash
2+
3+
# Env Vars:
4+
# REGISTRY: name of the image registry/namespace to get the images
5+
# GIT_REPO: org/repo to use (can also put it in a file called .gitRepo)
6+
#
7+
# Also put the Github personal access token in a file called ".gitToken".
8+
# It needs to have the "admin:repo_hook" and "repo" permissions.
9+
# If the file is not found then you will be prompted to enter it.
10+
11+
# Clean up previous run
12+
function clean() {
13+
set +ex
14+
echo Cleaning...
15+
(
16+
ibmcloud ce app delete -n github -f
17+
rm -f out
18+
) > /dev/null 2>&1
19+
}
20+
21+
clean
22+
[[ "$1" == "clean" ]] && exit 0
23+
24+
export REGISTRY=${REGISTRY:-icr.io/codeengine}
25+
26+
# Create our github webhook processor Application, use secret in a env vars
27+
ibmcloud ce app create -n github --image $REGISTRY/github
28+
29+
# Save App's URL for later
30+
APP=$(ibmcloud ce app get -n github -o url)
31+
32+
# Now send a pre-created github "push" event to the app to simulate
33+
# it coming from github
34+
curl $APP -XPOST -d @sample-commit -H "X-Github-Event: push"
35+
36+
ibmcloud ce app logs -n github --raw | tee out
37+
38+
if ! grep "ibmcloud ce buildrun submit" out > /dev/null 2>&1 ; then
39+
echo "Missing expected output"
40+
exit 1
41+
fi
42+
43+
clean

‎github/sample-commit‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"ref": "refs/heads/main",
3+
"before": "--commit-ID--",
4+
"after": "--commit-ID--",
5+
"repository": {
6+
"name": "CodeEngine",
7+
"full_name": "IBM/CodeEngine"
8+
},
9+
"pusher": {
10+
"name": "someuser",
11+
"email": "me@example.com"
12+
},
13+
"sender": {},
14+
"commits": []
15+
}

0 commit comments

Comments
 (0)