Skip to content

Commit

Permalink
Add official getting started guide using provided webhook and ingress…
Browse files Browse the repository at this point in the history
… tasks
  • Loading branch information
iancoffey authored and tekton-robot committed Oct 10, 2019
1 parent 047ae7b commit d131943
Show file tree
Hide file tree
Showing 11 changed files with 543 additions and 5 deletions.
10 changes: 5 additions & 5 deletions docs/create-webhook.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ spec:
volumes:
- name: github-secret
secret:
secretName: $(inputs.params.GitHubSecretName)
secretName: $(inputs.params.GitHubSecretName)

inputs:
params:
- name: ExternalDomain
description: "The external domain for the EventListener e.g. `$(inputs.params.EventListenerName).<PROXYIP>.nip.io`"
- name: GitHubUser
description: "The GitHub user"
description: "The GitHub user"
- name: GitHubRepo
description: "The GitHub repo where the webhook will be created"
- name: GitHubOrg
Expand All @@ -23,7 +23,7 @@ spec:
- name: GitHubAccessTokenKey
description: "The GitHub access token key name"
- name: GitHubSecretStringKey
description: The GitHub secret string key name"
description: "The GitHub secret string key name"
- name: GitHubDomain
description: "The GitHub domain. Override for GitHub Enterprise"
default: "github.com"
Expand All @@ -44,7 +44,7 @@ spec:
set -e
echo "Create Webhook"
if [ $(inputs.params.GitHubDomain) = "github.com" ];then
curl -d "{\"name\": \"web\",\"active\": true,\"events\": $(inputs.params.WebhookEvents),\"config\": {\"url\": \"https://$(inputs.params.ExternalDomain)\",\"content_type\": \"json\",\"insecure_ssl\": \"1\" ,\"secret\": \"$(cat /var/secret/$(inputs.params.GitHubSecretStringKey))\"}}" -X POST -u $(cat /var/secret/$(inputs.params.GitHubUser)):$(cat /var/secret/$(inputs.params.GitHubAccessTokenKey)) -L https://api.github.com/repos/$(inputs.params.GitHubOrg)/$(inputs.params.GitHubRepo)/hooks
curl -v -d "{\"name\": \"web\",\"active\": true,\"events\": $(inputs.params.WebhookEvents),\"config\": {\"url\": \"https://$(inputs.params.ExternalDomain)\",\"content_type\": \"json\",\"insecure_ssl\": \"1\" ,\"secret\": \"$(cat /var/secret/$(inputs.params.GitHubSecretStringKey))\"}}" -X POST -u $(inputs.params.GitHubUser):$(cat /var/secret/$(inputs.params.GitHubAccessTokenKey)) -L https://api.github.com/repos/$(inputs.params.GitHubOrg)/$(inputs.params.GitHubRepo)/hooks
else
curl -d "{\"name\": \"web\",\"active\": true,\"events\": $(inputs.params.WebhookEvents),\"config\": {\"url\": \"https://$(inputs.params.ExternalDomain)/\",\"content_type\": \"json\",\"insecure_ssl\": \"1\" ,\"secret\": \"$(cat /var/secret/$(inputs.params.GitHubSecretStringKey))\"}}" -X POST -u $(cat /var/secret/$(inputs.params.GitHubUser)):$(cat /var/secret/$(inputs.params.GitHubAccessTokenKey)) -L https://$(inputs.params.GitHubDomain)/api/v3/repos/$(inputs.params.GitHubOrg)/$(inputs.params.GitHubRepo)/hooks
curl -d "{\"name\": \"web\",\"active\": true,\"events\": $(inputs.params.WebhookEvents),\"config\": {\"url\": \"https://$(inputs.params.ExternalDomain)/\",\"content_type\": \"json\",\"insecure_ssl\": \"1\" ,\"secret\": \"$(cat /var/secret/$(inputs.params.GitHubSecretStringKey))\"}}" -X POST -u $(inputs.params.GitHubUser):$(cat /var/secret/$(inputs.params.GitHubAccessTokenKey)) -L https://$(inputs.params.GitHubDomain)/api/v3/repos/$(inputs.params.GitHubOrg)/$(inputs.params.GitHubRepo)/hooks
fi
4 changes: 4 additions & 0 deletions docs/getting-started/01-namespace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: getting-started
142 changes: 142 additions & 0 deletions docs/getting-started/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# Getting started with Triggers

To get started with Triggers, let's put it to work building and deploying a real image. In the following guide, we will use `Triggers` to handle a real GitHub webhook request to kickoff a PipelineRun.

## Install dependencies

Before we can use the Triggers project, we need to get some dependencies out of the way.

- [A Kubernetes Cluster](https://kubernetes.io/docs/setup/)
- This guide depends on an having access to a Kubernetes cluster which is publicly reachable from the internet.
- The cluster also needs the ability to [create ingress resources](https://kubernetes.io/docs/concepts/services-networking/ingress/).
- Most cloud providers k8s offerings work for this purpose...
- but ingress does not work out of the box for GKE clusters.
- For now, GKE users should consider using the [nginx ingress](https://kubernetes.github.io/ingress-nginx/deploy/#gce-gke).
- [Install Tekton Pipelines](https://github.com/tektoncd/pipeline/blob/master/docs/install.md#installing-tekton-pipelines)
- Pipelines is the backbone of Tekton and will allow us to accomplish the work we plan to do.
- [Install Triggers](https://github.com/tektoncd/triggers/blob/master/DEVELOPMENT.md#install-triggers)
- Of course we need to install our project as well, so we can accept and process events into PipelineRuns!
- Pick a GitHub repo with a Dockerfile as your build object (or you can fork [this one](https://github.com/iancoffey/ulmaceae)).
- Clone this repo locally - we will come back to this repo later.

## Configure the cluster

Now that we have our cluster ready, we need to setup our getting-started namespace and RBAC. We will keep everything inside this single namespace for easy cleanup. In the unlikely event that you get stuck/flummoxed, the best course of action might be to just delete this namespace and start fresh.

- Create the *getting-started* namespace, where all our resources will live.
- `kubectl create namespace getting-started`
- [Create the admin user, role and rolebinding](./rbac/admin-role.yaml)
- `kubectl apply -f ./docs/getting-started/rbac/admin-role.yaml`
- [Create the create-webhook user, role and rolebinding](./rbac/webhook-role.yaml)
- `kubectl apply -f ./docs/getting-started/rbac/webhook-role.yaml`
- This will allow our webhook to create the things it needs to.

## Install the Pipeline and Triggers

### [Install the Pipeline](./pipeline.yaml)
Now we have to install the Pipeline we plan to use and also our Triggers resources.

`kubectl apply -f ./docs/getting-started/pipeline.yaml`

Our Pipeline will do a few things.
- Retrieve the source code
- Build and push the source code into a Docker image
- Push the image to the specified repository
- Run the image locally

#### What does it do?

The Pipeline will build a Docker image with [img](https://github.com/genuinetools/img) and deploy it locally via kubectl image.

### [Install the TriggerTemplate, TriggerBinding and EventListener](./triggers.yaml)
The Triggers project will pickup from there.
- We will setup an `EventListener` to accept and process GitHub Push events
- A `TriggerTemplate` to create templated PipelineResource and PipelineRun resources per event received by the `EventListener`.
- First, **update** the `triggers.yaml` file to reflect the Docker repository you wish to push the image blob to.
- You will need to replace the `DOCKERREPO-REPLACEME` string everywhere it is needed.
- Once you have updated the triggers file, you can apply it!
- `kubectl apply -f ./docs/getting-started/triggers.yaml`
- If that succeeded, your cluster is ready to start handling Events.

## Add Ingress and GitHub-Webook Tasks

We will need an ingress to handle incoming webhooks and we will make use of our new ingress by configuring Github with our GitHub Task.

First lets create our ingress Task.

`kubectl apply -f ./docs/create-ingress.yaml -n getting-started`

Now lets create our webhook Task.

`kubectl apply -f ./docs/create-webhook.yaml -n getting-started`

## Run Ingress Task

### Update the Ingress TaskRun

Lets first update the TaskRun to make any needed changes

edit the `docs/getting-started/ingress-run.yaml` file to adjust the settings.

At the mimimum, you will need to update the ExternalDomain field to match your own DNS name.

### Run the Ingress Task

When you are ready, run the ingress Task.

`kubectl apply -f docs/getting-started/ingress-run.yaml`

## Run GitHub Webhook Task

You will need to create a [Github Personal Access Token](https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line#creating-a-token) with the following access.
- `public_repo`
- `admin:repo_hook`

Next, create a secret like so with your access token.

```
apiVersion: v1
kind: Secret
metadata:
name: webook-secret
namespace: getting-started
stringData:
token: YOUR-GITHUB-ACCESS-TOKEN
secret: random-string-data
```

### Update webhook task run

Now lets update the GitHub Task run.

There are a few fields to change, but these fields must be updated at the minimum.

- GitHubOrg: The GitHub org you are using for this getting-started.
- GitHubUser: Your GitHub username.
- GitHubRepo: The repo we will be using for this example.

### Run the Webhook Task

Now lets run our updated webhook task.

`kubectl apply -f docs/getting-started/webhook-run.yaml`

## Watch it work!

- Commit and push an empty commit to your development repo.
- `git commit -a -m "build commit" --allow-empty && git push origin mybranch`
- Now, you can follow the Task output in `kubectl logs`.
- First the image builder task.
- `kubectl logs -l somelabel=somekey --all-containers`
- Then our deployer task.
- `kubectl logs -l tekton.dev/pipeline=getting-started-pipeline -n getting-started --all-containers`
- We can see now that our CI system is working! Images pushed to this repo result in a running pod in our cluster.
- We can examine our pod like so.
- kubectl logs tekton-triggers-built-me -n getting-started --all-containers

Now we can see our new image running our cluster, after having been retrieved, tested, vetted and built, docker pushed (and pulled) and finally ran on our cluster as a Pod.

## Clean up

- Delete the *getting-started* namespace!
- `kubectl delete namespace getting-started`
Binary file added docs/getting-started/images/trigger-webhook.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/getting-started/images/trigger-webhook2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions docs/getting-started/ingress-run.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
apiVersion: tekton.dev/v1alpha1
kind: TaskRun
metadata:
name: create-ingress-run
namespace: getting-started
spec:
taskRef:
name: create-ingress
inputs:
params:
- name: CreateCertificate
value: "true"
- name: CertificateKeyPassphrase
value: asecretphrase
- name: CertificateSecretName
value: ingresssecret
- name: ExternalDomain
value: getting-started.iancoffey.com
- name: Service
value: getting-started
- name: ServicePort
value: "8080"
timeout: 1000s
serviceAccount: tekton-triggers-createwebhook
153 changes: 153 additions & 0 deletions docs/getting-started/pipeline.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
---
# The getting-started Pipeline will run through several tasks:
# - source is pulled from git
# - conditions say go test must pass before moving on
# - source is built into an image by img
# - image output is pushed to ECR
# - cloudevent emitted
apiVersion: tekton.dev/v1alpha1
kind: Pipeline
metadata:
name: getting-started-pipeline
namespace: getting-started
spec:
resources:
- name: source-repo
type: git
- name: image-source
type: image
- name: event-to-sink
type: cloudEvent
tasks:
- name: build-docker-image
taskRef:
name: build-docker-image
conditions:
- conditionRef: "go-test"
resources:
- name: source-repo
resource: source-repo
params:
- name: pathToContext
value: /workspace/source-repo
resources:
inputs:
- name: source-repo
resource: source-repo
outputs:
- name: builtImage
resource: image-source
- name: deploy-locally
taskRef:
name: deploy-locally
resources:
inputs:
- name: image-source
resource: image-source
from:
- build-docker-image
outputs:
- name: event-to-sink
resource: event-to-sink
---
apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
name: deploy-locally
namespace: getting-started
spec:
inputs:
resources:
- name: image-source
type: image
outputs:
resources:
- name: event-to-sink
type: cloudEvent
steps:
- name: run-kubectl
image: lachlanevenson/k8s-kubectl
command: ["kubectl"]
args:
- "run"
- "tekton-triggers-built-me"
- "--image"
- "${inputs.resources.image-source.url}"
- "--env=PORT=8080"
---
apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
name: build-docker-image
namespace: getting-started
spec:
inputs:
resources:
- name: source-repo
type: git
params:
- name: pathToContext
description:
The build directory used by img
default: /workspace/source-repo
outputs:
resources:
- name: builtImage
type: image
steps:
- name: build-and-push
image: r.j3ss.co/img
command:
- /usr/bin/img
args:
- build
- -t
- "${outputs.resources.builtImage.url}"
- --no-cache
- "${inputs.params.pathToContext}"
---
apiVersion: tekton.dev/v1alpha1
kind: Condition
metadata:
name: go-test
namespace: getting-started
spec:
resources:
- name: source-repo
type: git
check:
image: golang
command: ["go"]
args: ['test', "$(inputs.resources.source-repo.path)/..."]
---
# Finally, we need something to receive our cloudevent announcing success!
# That is this services only purpose
apiVersion: v1
kind: Service
metadata:
name: event-display
namespace: getting-started
labels:
app: event-display
spec:
type: ClusterIP
ports:
- name: listener
port: 8080
protocol: TCP
selector:
app: event-display
---
apiVersion: v1
kind: Pod
metadata:
name: event-display
namespace: getting-started
labels:
name: event-display
spec:
hostname: event-display
containers:
- image: gcr.io/knative-releases/github.com/knative/eventing-sources/cmd/event_display
name: web

Loading

0 comments on commit d131943

Please sign in to comment.