Skip to content

Commit

Permalink
Update the gitwebhook sample (#215)
Browse files Browse the repository at this point in the history
* Clean up sample

* Swap token IDs to the right values

* Set format to json

* Remove old yaml
  • Loading branch information
rgregg committed Jul 20, 2018
1 parent 654804a commit d0b7828
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 116 deletions.
20 changes: 14 additions & 6 deletions serving/samples/gitwebhook-go/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,22 @@

FROM golang AS builder

WORKDIR /go/src/github.com/knative/docs/
ADD . /go/src/github.com/knative/docs/
# copy the source
ADD . /go/src/github.com/knative/docs/serving/samples/gitwebhook-go
WORKDIR /go/src/github.com/knative/docs/serving/samples/gitwebhook-go

RUN CGO_ENABLED=0 go build ./serving/samples/gitwebhook-go/
# install dependencies
RUN go get github.com/google/go-github/github
RUN go get golang.org/x/oauth2
RUN go get gopkg.in/go-playground/webhooks.v3
RUN go get gopkg.in/go-playground/webhooks.v3/github

FROM gcr.io/distroless/base
# build the sample
RUN CGO_ENABLED=0 go build -o /go/bin/webhook-sample .

FROM golang:alpine

EXPOSE 8080
COPY --from=builder /go/src/github.com/knative/docs/gitwebhook-go /sample
COPY --from=builder /go/bin/webhook-sample /app/webhook-sample

ENTRYPOINT ["/sample"]
ENTRYPOINT ["/app/webhook-sample"]
175 changes: 122 additions & 53 deletions serving/samples/gitwebhook-go/README.md
Original file line number Diff line number Diff line change
@@ -1,84 +1,153 @@
# gitwebhook
# GitHub Webhook - Go sample

A simple git webhook handler that demonstrates interacting with
github.
[Modeled after GCF example](https://cloud.google.com/community/tutorials/github-auto-assign-reviewers-cloud-functions)
A handler written in Go that demonstrates interacting with GitHub
through a webhook.

## Prerequisites

1. [Install Knative Serving](https://github.com/knative/docs/blob/master/install/README.md)
1. Install [docker](https://www.docker.com/)
* A Kubernetes cluster with Knative installed. Follow the
[installation instructions](https://github.com/knative/docs/blob/master/install/README.md)
if you need to create one.
* [Docker](https://www.docker.com) installed and running on your local machine,
and a Docker Hub account configured (we'll use it for a container registry).
* An account on [GitHub](https://github.com) with read/write access to a
repository.

## Build the sample code

1. Use Docker to build a container image for this service. Replace
`{username}` with your Docker Hub username in the following commands.

```shell
export DOCKER_HUB_USERNAME=username

# Build the container, run from the project folder
docker build -t ${DOCKER_HUB_USERNAME}/gitwebhook-go .

# Push the container to the registry
docker push ${DOCKER_HUB_USERNAME}/gitwebhook-go
```

1. Create a secret that holds two values from GitHub, a personal access token
used to make API requests to GitHub, and a webhook secret, used to validate
incoming requests.

1. Follow the GitHub instructions to [create a personal access token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/).
Ensure to grant the `repo` permission to give read/write access to the
personal access token.
1. Base64 encode the access token:

```shell
$ echo -n "45d382d4a9a93c453fb7c8adc109121e7c29fa3ca" | base64
NDVkMzgyZDRhOWE5M2M0NTNmYjdjOGFkYzEwOTEyMWU3YzI5ZmEzY2E=
```

1. Copy the encoded access token into `github-secret.yaml` next to `personalAccessToken:`.
1. Create a webhook secert value unique to this sample, base64 encode it, and
copy it into `github-secret.yaml` next to `webhookSecret:`:

```shell
$ echo -n "mygithubwebhooksecret" | base64
bXlnaXRodWJ3ZWJob29rc2VjcmV0
```

1. Apply the secret to your cluster:

```shell
kubectl apply -f github-secret.yaml
```

1. Next, update the `service.yaml` file in the project to reference the tagged
image from step 1.

```yaml
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: gitwebhook
namespace: default
spec:
runLatest:
configuration:
revisionTemplate:
spec:
container:
# Replace {DOCKER_HUB_USERNAME} with your actual docker hub username
image: docker.io/{DOCKER_HUB_USERNAME}/gitwebhook-go
env:
- name: SECRET_TOKEN
valueFrom:
secretKeyRef:
name: githubsecret
key: secretToken
- name: ACCESS_TOKEN
valueFrom:
secretKeyRef:
name: githubsecret
key: accessToken
```

1. Use `kubectl` to apply the `service.yaml` file.

## Setup
```shell
$ kubectl apply -f service.yaml
service "gitwebhook" created
```

Build the app container and publish it to your registry of choice:
1. Finally, once the service is running, create the webhook from your GitHub repo
to the URL for this service. For this to work properly you will
need to [configure a custom domain](https://github.com/knative/docs/blob/master/serving/using-a-custom-domain.md)
and [assign a static IP address](https://github.com/knative/docs/blob/master/serving/gke-assigning-static-ip-address.md).

```shell
REPO="gcr.io/<your-project-here>"
1. Retrieve the hostname for this service, using the following command:

# Build and publish the container, run from the root directory.
docker build \
--tag "${REPO}/serving/samples/gitwebhook-go" \
--file=serving/samples/gitwebhook-go/Dockerfile .
docker push "${REPO}/serving/samples/gitwebhook-go"
```shell
$ kubectl get services.serving.knative.dev gitwebhook \
-o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain
# Replace the image reference with our published image.
perl -pi -e "s@github.com/knative/docs/serving/samples/gitwebhook-go@${REPO}/serving/samples/gitwebhook-go@g" serving/samples/gitwebhook-go/*.yaml
NAME DOMAIN
gitwebhook gitwebhook.default.example.com
```

# Deploy the Knative Serving sample
kubectl apply -f serving/samples/gitwebhook-go/sample.yaml
```
1. Browse on GitHub to the repository where you want to create a webhook.
1. Click **Settings**, then **Webhooks**, then **Add webhook**.
1. Enter the **Payload URL** as `http://{DOMAIN}`, with the value of DOMAIN listed above.
1. Set the **Content type** to `application/json`.
1. Enter the **Secret** value to be the same as the original base used for
`webhookSecret` above (the original value, not the base64 encoded value).
1. Select **Disable** under SSL Validation, unless you've [enabled SSL](https://github.com/knative/docs/blob/master/serving/using-an-ssl-cert.md).
1. Click **Add webhook** to create the webhook.
## Exploring
Once deployed, you can inspect the created resources with `kubectl` commands:
```shell
# This will show the Route that we created:
# This will show the Knative service that we created:
kubectl get service.serving.knative.dev -o yaml
# This will show the Route, created by the service:
kubectl get route -o yaml
# This will show the Configuration that we created:
# This will show the Configuration, created by the service:
kubectl get configurations -o yaml
# This will show the Revision that was created by our configuration:
# This will show the Revision, created by the Configuration:
kubectl get revisions -o yaml

```

To make this service accessible to github, we first need to determine its ingress address
(might have to wait a little while until `EXTERNAL-IP` gets assigned):
```shell
watch kubectl get svc knative-ingressgateway -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
knative-ingressgateway LoadBalancer 10.23.247.74 35.203.155.229 80:32380/TCP,443:32390/TCP,32400:32400/TCP 2d
```
Once the `EXTERNAL-IP` gets assigned to the cluster, you need to assign a DNS name for that IP address.
[Using GCP DNS](https://support.google.com/domains/answer/3290350)

So, you'd need to create an A record for demostuff.aikas.org pointing to 35.202.30.59.

Then you need to go to github and [set up a webhook](https://cloud.google.com/community/tutorials/github-auto-assign-r
eviewers-cloud-functions).
For the Payload URL however, use your DNS entry you created above, so for my example it would be:
http://demostuff.aikas.org/

Create a secret that has access to the tokens. Take the Secret you used for the webhook
(secretToken) and the generated access token (accessToken) (as per the above webhook)
## Testing the service
```shell
echo -n "your-chosen-secret-token" > secretToken
echo -n "github-generated-access-token" > accessToken
kubectl create secret generic githubsecret --from-file=./secretToken --from-file=./accessToken
```

Then create a PR for the repo you configured the webhook for, and you'll see that the Title
will be modified with the suffix '(looks pretty legit)'
Now that you have the service running and the webhook created, send a Pull
Request to the same GitHub repo where you added the webhook. If all is working
right, you'll see the title of the PR will be modified, with the text
`(looks pretty legit)` appended the end of the title.

## Cleaning up

To clean up the sample service:

```shell
kubectl delete -f serving/samples/gitwebhook-go/sample.yaml
kubectl delete -f service.yaml
```

12 changes: 12 additions & 0 deletions serving/samples/gitwebhook-go/github-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: v1
kind: Secret
metadata:
name: githubsecret
type: Opaque
data:
# Generate a personal access token from GitHub
# See https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/
personalAccessToken: <base64 encoded personal access token>
# The secret specified when creating the webhook on GitHub
# This is used to validate incoming webhook messages.
webhookSecret: <base64 encoded webhook secret>
13 changes: 6 additions & 7 deletions serving/samples/gitwebhook-go/gitwebhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,18 @@ import (
"os"
"strings"

ghclient "github.com/google/go-github/github"
"golang.org/x/oauth2"
webhooks "gopkg.in/go-playground/webhooks.v3"
"gopkg.in/go-playground/webhooks.v3/github"

ghclient "github.com/google/go-github/github"
)

const (
// Secret given to github. Used for verifying the incoming objects.
accessTokenKey = "ACCESS_TOKEN"
personalAccessTokenKey = "GITHUB_PERSONAL_TOKEN"
// Personal Access Token created in github that allows us to make
// calls into github.
secretTokenKey = "SECRET_TOKEN"
webhookSecretKey = "WEBHOOK_SECRET"
// this is what we tack onto each PR title if not there already
titleSuffix = "looks pretty legit"
)
Expand Down Expand Up @@ -82,15 +81,15 @@ func (handler *GithubHandler) HandlePullRequest(payload interface{}, header webh
func main() {
flag.Parse()
log.Print("gitwebhook sample started.")
accessToken := os.Getenv(accessTokenKey)
secretToken := os.Getenv(secretTokenKey)
personalAccessToken := os.Getenv(personalAccessTokenKey)
secretToken := os.Getenv(webhookSecretKey)

// Set up the auth for being able to talk to Github. It's
// odd that you have to also pass context around for the
// calls even after giving it to client. But, whatever.
ctx := context.Background()
ts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: accessToken},
&oauth2.Token{AccessToken: personalAccessToken},
)
tc := oauth2.NewClient(ctx, ts)

Expand Down
50 changes: 0 additions & 50 deletions serving/samples/gitwebhook-go/sample.yaml

This file was deleted.

37 changes: 37 additions & 0 deletions serving/samples/gitwebhook-go/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Copyright 2018 The Knative Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: gitwebhook
namespace: default
spec:
runLatest:
configuration:
revisionTemplate:
spec:
container:
# Replace {DOCKER_HUB_USERNAME} with your actual docker hub username
image: docker.io/{DOCKER_HUB_USERNAME}/gitwebhook:latest
env:
- name: GITHUB_PERSONAL_TOKEN
valueFrom:
secretKeyRef:
name: githubsecret
key: personalAccessToken
- name: WEBHOOK_SECRET
valueFrom:
secretKeyRef:
name: githubsecret
key: webhookSecret

0 comments on commit d0b7828

Please sign in to comment.