-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Adding GitHub Sample for move from eventing. #339
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5b4477d
14be1b2
d9eda3b
b8c3e8e
4820035
6e0ab61
954f997
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # 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. | ||
|
|
||
| FROM golang AS builder | ||
|
|
||
| WORKDIR /go/src/github.com/knative/docs/ | ||
| ADD . /go/src/github.com/knative/docs/ | ||
|
|
||
| RUN CGO_ENABLED=0 go build ./eventing/samples/github-events | ||
|
|
||
| FROM gcr.io/distroless/base | ||
|
|
||
| COPY --from=builder /go/src/github.com/knative/docs/github-events /sample | ||
|
|
||
| ENTRYPOINT ["/sample"] | ||
| EXPOSE 8080 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,174 @@ | ||
| # Reacting to GitHub Events | ||
|
|
||
| In response to a pull request event, the sample app _legit_ Service will add | ||
| `(looks pretty legit)` to the PR title. | ||
|
|
||
| A GitHub webhook will be created on a repository and a Knative `Service` will be | ||
| deployed to receive the webhook's event deliveries and forward them into a | ||
| `Channel`, through a `Bus`, and out to the consumer via a `Subscription`. The | ||
| `Flow` resource takes care of provisioning the webhook, the `Service`, the | ||
| `Channel`, and the `Subscription`. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| You will need: | ||
|
|
||
| - A Kubernetes cluster with Knative serving 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 (you'll use it for a container registry). | ||
| - Knative eventing core installed on your Kubernetes cluster. You can install | ||
| with: | ||
| ```shell | ||
| kubectl apply -f https://storage.googleapis.com/knative-releases/eventing/latest/release.yaml | ||
| ``` | ||
| - A domain name that allows GitHub to call into the cluster: Follow the | ||
| [assign a static IP address](https://github.com/knative/docs/blob/master/serving/gke-assigning-static-ip-address.md) | ||
| and | ||
| [configure a custom domain](https://github.com/knative/docs/blob/master/serving/using-a-custom-domain.md) | ||
| instructions. | ||
|
|
||
| ## Configuring Knative | ||
|
|
||
| To use this sample, you'll need to install the `stub` ClusterBus and the | ||
| `github` EventSource: | ||
|
|
||
| ```shell | ||
| # Installs ClusterBus | ||
| kubectl apply -f https://storage.googleapis.com/knative-releases/eventing/latest/release-clusterbus-stub.yaml | ||
| # Installs EventSource | ||
| kubectl apply -f https://storage.googleapis.com/knative-releases/eventing/latest/release-source-github.yaml | ||
| ``` | ||
|
|
||
| ## Granting permissions | ||
|
|
||
| Because the `github` EventSource needs to create a Knative Service, you'll need | ||
| to provision a special ServiceAccount with the necessary permissions. | ||
|
|
||
| The `eventing/samples/github-events/auth.yaml` file provisions a service | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd prefer to do this from this directory, rather than rooted at
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This matches how k8s events is asked to run. if we want to change that, then perhaps both need to be updated. It will mean that the Docker file interactions will be from a different directory than the kubectl commands. |
||
| account, and creates a role which can create a Knative Service in the `default` | ||
| namespace. In a production environment, you might want to limit the access of | ||
| this service account to only specific namespaces. | ||
|
|
||
| ```shell | ||
| kubectl apply -f eventing/samples/github-events/auth.yaml | ||
| ``` | ||
|
|
||
| ## Building and deploying the sample | ||
|
|
||
| 1. Use Docker to build the sample code into a container. To build and push with | ||
| Docker Hub, run the following commands, replacing `{username}` with your | ||
| Docker Hub username. Run these commands, r following from the _root_ of the | ||
| `knative/docs` repo: | ||
|
|
||
| ```shell | ||
| # Build the container on your local machine | ||
| docker build -t {username}/github-events --file=eventing/samples/github-events/Dockerfile . | ||
|
|
||
| # Push the container to docker registry | ||
| docker push {username}/github-events | ||
| ``` | ||
|
|
||
| 1. After the build has completed and the container is pushed to Docker Hub, you | ||
| can deploy the function into your cluster. **Ensure that the container image | ||
| value in `function.yaml` matches the container you built in the previous | ||
| step.** Apply the configuration using `kubectl`: | ||
|
|
||
| ```shell | ||
| kubectl apply -f eventing/samples/github-events/function.yaml | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again (and below), it would be nice if these could be relative to the current directory. I'll see if I can do this for the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added an issue to fix this for all eventing samples: #351 |
||
| ``` | ||
|
|
||
| 1. Check that your service is running using: | ||
|
|
||
| ```shell | ||
| kubectl get services.serving.knative.dev -o "custom-columns=NAME:.metadata.name,READY:.status.conditions[2].status,REASON:.status.conditions[2].message" | ||
| NAME READY REASON | ||
| legit True <none> | ||
| ``` | ||
|
|
||
| 1. Create a [personal access token](https://github.com/settings/tokens) to | ||
| GitHub repo that the GitHub source can use to register webhooks with the | ||
| GitHub API. Also decide on a token that your code will use to authenticate | ||
| the incoming webhooks from GitHub (*accessToken*). | ||
|
|
||
| The token can be named anything you find convenient. This sample requires | ||
| full `repo` control to be able update the title of the _Pull Request_. | ||
| The Source requires `admin:repo_hook`, this allows it to create webhooks | ||
| into repos that your account is allowed to do so. Copy and save this token; | ||
| GitHub will force you to generate it again if misplaced. | ||
|
|
||
| Here I named my token "EventingSample" and have selected the recommended | ||
| scopes: | ||
|
|
||
|  | ||
|
|
||
| Update `eventing/samples/github-events/githubsecret.yaml` with those | ||
| values. If your generated access token is `'asdfasfdsaf'` and you choose | ||
| your *secretToken* as `'personal_access_token_value'`, you'd modify | ||
| `eventing/samples/github-events/githubsecret.yaml` like so: | ||
|
|
||
| ```yaml | ||
| apiVersion: v1 | ||
| kind: Secret | ||
| metadata: | ||
| name: githubsecret | ||
| type: Opaque | ||
| stringData: | ||
| githubCredentials: > | ||
| { | ||
| "accessToken": "asdfasfdsaf", | ||
| "secretToken": "personal_access_token_value" | ||
| } | ||
| ``` | ||
|
|
||
| Hint: you can makeup a random *accessToken* with: | ||
|
|
||
| ```shell | ||
| head -c 8 /dev/urandom | base64 | ||
| ``` | ||
|
|
||
| Then, apply the githubsecret using `kubectl`: | ||
|
|
||
| ```shell | ||
| kubectl apply -f eventing/samples/github-events/githubsecret.yaml | ||
| ``` | ||
|
|
||
| 1. Update the resource inside `eventing/samples/github-events/flow.yaml` to the | ||
| org/repo of your choosing. Note that the personal access token must be valid | ||
| for the chosen org/repo. | ||
|
|
||
| Then create the flow sending GitHub Events to the service: | ||
|
|
||
| ```shell | ||
| kubectl apply -f eventing/samples/github-events/flow.yaml | ||
| ``` | ||
|
|
||
| 1. 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)` | ||
|
|
||
|
|
||
| ## Understanding what happened | ||
|
|
||
| `TODO: similar to k8s-events.` | ||
|
|
||
| <!--TODO: | ||
| explain the resources and communication channels, as well as where the secret | ||
| is used. In particular include a note to look at | ||
| https://github.com/<owner>/<repo>/settings/hooks to see the webhook registered | ||
| and then deleted. | ||
| --> | ||
|
|
||
| ## Cleaning up | ||
|
|
||
| To clean up the function, `Flow`, auth, and secret: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to clean up
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes but I need help because I have not looked into what rbac arguments should look like |
||
|
|
||
| ```shell | ||
| kubectl delete -f eventing/samples/github-events/function.yaml | ||
| kubectl delete -f eventing/samples/github-events/flow.yaml | ||
| kubectl delete -f eventing/samples/github-events/auth.yaml | ||
| kubectl delete -f eventing/samples/github-events/githubsecret.yaml | ||
| ``` | ||
|
|
||
| And then delete the [personal access token](https://github.com/settings/tokens) | ||
| created from GitHub. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| # 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 | ||
| # | ||
| # http://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: v1 | ||
| kind: ServiceAccount | ||
| metadata: | ||
| name: feed-sa | ||
| namespace: default | ||
| --- | ||
| apiVersion: rbac.authorization.k8s.io/v1 | ||
| kind: Role | ||
| metadata: | ||
| name: create-knative-service | ||
| namespace: default | ||
| rules: | ||
| - apiGroups: ["serving.knative.dev"] | ||
| resources: ["services"] | ||
| verbs: ["get", "list", "watch", "create", "update", "delete", "patch"] | ||
| --- | ||
| # This enables the feed-sa to deploy the receive adapter. | ||
| apiVersion: rbac.authorization.k8s.io/v1 | ||
| kind: RoleBinding | ||
| metadata: | ||
| name: feed-sa-deploy | ||
| namespace: default | ||
| subjects: | ||
| - kind: ServiceAccount | ||
| name: feed-sa | ||
| namespace: default | ||
| roleRef: | ||
| kind: Role | ||
| name: create-knative-service | ||
| apiGroup: rbac.authorization.k8s.io |
| 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: flows.knative.dev/v1alpha1 | ||
| kind: Flow | ||
| metadata: | ||
| name: github-flow | ||
| namespace: default | ||
| spec: | ||
| serviceAccountName: feed-sa | ||
| trigger: | ||
| eventType: dev.knative.github.pullrequest | ||
| resource: <org>/<repo> # TODO: update this | ||
| service: github | ||
| parameters: | ||
| secretName: githubsecret | ||
| secretKey: githubCredentials | ||
| parametersFrom: | ||
| - secretKeyRef: | ||
| name: githubsecret | ||
| key: githubCredentials | ||
| action: | ||
| target: | ||
| kind: Service | ||
| apiVersion: serving.knative.dev/v1alpha1 | ||
| name: legit |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| /* | ||
| 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. | ||
| */ | ||
|
|
||
| package main | ||
|
|
||
| import ( | ||
| "context" | ||
| "encoding/json" | ||
| "flag" | ||
| "fmt" | ||
| ghclient "github.com/google/go-github/github" | ||
| "github.com/knative/eventing/pkg/event" | ||
| "golang.org/x/oauth2" | ||
| "gopkg.in/go-playground/webhooks.v3/github" | ||
| "log" | ||
| "net/http" | ||
| "os" | ||
| "strings" | ||
| ) | ||
|
|
||
| const ( | ||
| // Environment variable containing json credentials | ||
| envSecret = "GITHUB_SECRET" | ||
| // this is what we tack onto each PR title if not there already | ||
| titleSuffix = "looks pretty legit" | ||
| ) | ||
|
|
||
| // GithubHandler holds necessary objects for communicating with the Github. | ||
| type GithubHandler struct { | ||
| client *ghclient.Client | ||
| ctx context.Context | ||
| } | ||
|
|
||
| type GithubSecrets struct { | ||
| AccessToken string `json:"accessToken"` | ||
| SecretToken string `json:"secretToken"` | ||
| } | ||
|
|
||
| func (h *GithubHandler) newPullRequestPayload(ctx context.Context, pl *github.PullRequestPayload) { | ||
|
|
||
| title := pl.PullRequest.Title | ||
| log.Printf("GOT PR with Title: %q", title) | ||
|
|
||
| // Check the title and if it contains 'looks pretty legit' leave it alone | ||
| if strings.Contains(title, titleSuffix) { | ||
| // already modified, leave it alone. | ||
| return | ||
| } | ||
|
|
||
| newTitle := fmt.Sprintf("%s (%s)", title, titleSuffix) | ||
| updatedPR := ghclient.PullRequest{ | ||
| Title: &newTitle, | ||
| } | ||
| newPR, response, err := h.client.PullRequests.Edit(h.ctx, | ||
| pl.Repository.Owner.Login, pl.Repository.Name, int(pl.Number), &updatedPR) | ||
| if err != nil { | ||
| log.Printf("Failed to update PR: %s\n%s", err, response) | ||
| return | ||
| } | ||
| if newPR.Title != nil { | ||
| log.Printf("New PR Title: %q", *newPR.Title) | ||
| } else { | ||
| log.Printf("New PR title is nil") | ||
| } | ||
| } | ||
|
|
||
| func main() { | ||
| flag.Parse() | ||
| githubSecrets := os.Getenv(envSecret) | ||
|
|
||
| var credentials GithubSecrets | ||
| err := json.Unmarshal([]byte(githubSecrets), &credentials) | ||
| if err != nil { | ||
| log.Fatalf("Failed to unmarshal credentials: %s", err) | ||
| return | ||
| } | ||
|
|
||
| // Set up the auth for being able to talk to Github. | ||
| ctx := context.Background() | ||
| ts := oauth2.StaticTokenSource( | ||
| &oauth2.Token{AccessToken: credentials.AccessToken}, | ||
| ) | ||
| tc := oauth2.NewClient(ctx, ts) | ||
|
|
||
| client := ghclient.NewClient(tc) | ||
|
|
||
| h := &GithubHandler{ | ||
| client: client, | ||
| ctx: ctx, | ||
| } | ||
|
|
||
| log.Fatal(http.ListenAndServe(":8080", event.Handler(h.newPullRequestPayload))) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like you don't need to use
dep, so this is much cleaner than what I had to do in thek8seventscommit (see f00e99d and d1b685a for thedepchanges). Prior to needingdep, I used the following, which is even simpler than what you have here, and works from the sample directory:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I copied the k8s event docker file and changed the path of the runable. I was able to get this to work testing the README script just fine.