diff --git a/.github/actions/kustomize/Dockerfile b/.github/actions/kustomize/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..2ebd6334a69711340f7904a3a901a2cb4dfe280c
--- /dev/null
+++ b/.github/actions/kustomize/Dockerfile
@@ -0,0 +1,6 @@
+FROM giantswarm/tiny-tools
+
+COPY entrypoint.sh /entrypoint.sh
+RUN chmod +x /entrypoint.sh
+
+ENTRYPOINT ["/entrypoint.sh"]
diff --git a/.github/actions/kustomize/action.yml b/.github/actions/kustomize/action.yml
new file mode 100644
index 0000000000000000000000000000000000000000..bd53d1d73e5576b7a1856de02e3d4e7f8cb6410d
--- /dev/null
+++ b/.github/actions/kustomize/action.yml
@@ -0,0 +1,9 @@
+name: 'kustomize'
+description: 'A GitHub Action to run kustomize commands'
+author: 'Stefan Prodan'
+branding:
+  icon: 'command'
+  color: 'blue'
+runs:
+  using: 'docker'
+  image: 'Dockerfile'
diff --git a/.github/actions/kustomize/entrypoint.sh b/.github/actions/kustomize/entrypoint.sh
new file mode 100644
index 0000000000000000000000000000000000000000..b9d560c920cb64fcd8b5ab442dad45a26786daaf
--- /dev/null
+++ b/.github/actions/kustomize/entrypoint.sh
@@ -0,0 +1,12 @@
+#!/bin/sh -l
+
+VERSION=3.5.4
+curl -sL https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv${VERSION}/kustomize_v${VERSION}_linux_amd64.tar.gz | tar xz
+
+mkdir -p $GITHUB_WORKSPACE/bin
+cp ./kustomize $GITHUB_WORKSPACE/bin
+chmod +x $GITHUB_WORKSPACE/bin/kustomize
+ls -lh $GITHUB_WORKSPACE/bin
+
+echo "::add-path::$GITHUB_WORKSPACE/bin"
+echo "::add-path::$RUNNER_WORKSPACE/$(basename $GITHUB_REPOSITORY)/bin"
diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..6b1dae6e59d6bc3fa1bf21bb6a4789f69129a260
--- /dev/null
+++ b/.github/workflows/e2e.yaml
@@ -0,0 +1,46 @@
+name: e2e
+
+on:
+  pull_request:
+  push:
+    branches:
+      - master
+
+jobs:
+  kind:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v2
+      - name: Restore Go cache
+        uses: actions/cache@v1
+        with:
+          path: ~/go/pkg/mod
+          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
+          restore-keys: |
+            ${{ runner.os }}-go-
+      - name: Setup Go
+        uses: actions/setup-go@v2-beta
+        with:
+          go-version: 1.14.x
+      - name: Setup Kubernetes
+        uses: engineerd/setup-kind@v0.3.0
+      - name: Setup Kustomize
+        uses: ./.github/actions/kustomize
+      - name: Run test
+        run: make test
+      - name: Check if working tree is dirty
+        run: |
+          if [[ $(git diff --stat) != '' ]]; then
+            echo 'run make test and commit changes'
+            exit 1
+          fi
+      - name: Build
+        run: sudo go build -o ./bin/tk ./cmd/tk
+      - name: Run integration tests
+        run: |
+          ./bin/tk install --manifests ./manifests/install/
+      - name: Debug failure
+        if: failure()
+        run: |
+          kubectl -n gitops-system get all
diff --git a/Makefile b/Makefile
index 2ada45ec445aface92c680ba24715db04186b7e8..b5c78f2c685e85a550f272db40a67d81b0e8d261 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,9 @@
 VERSION?=$(shell grep 'VERSION' cmd/tk/main.go | awk '{ print $$4 }' | tr -d '"')
 
-all: tidy fmt vet test build
+all: test build
 
-build:
-	CGO_ENABLED=0 go build -o ./bin/tk ./cmd/tk
+tidy:
+	go mod tidy
 
 fmt:
 	go fmt ./...
@@ -11,9 +11,11 @@ fmt:
 vet:
 	go vet ./...
 
-tidy:
-	go mod tidy
-
-test:
+test: tidy fmt vet
 	go test ./... -coverprofile cover.out
 
+build:
+	CGO_ENABLED=0 go build -o ./bin/tk ./cmd/tk
+
+install:
+	go install cmd/tk
diff --git a/README.md b/README.md
index c2765f6ada4e78d7924f21ef177ecf4336142fd9..9a2d2859bf08fc1c5d64f10b9bba144c8cfce636 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,9 @@
 # toolkit
-Experimental toolkit for assembling CD pipelines
+
+[![e2e](https://github.com/fluxcd/toolkit/workflows/e2e/badge.svg)](https://github.com/fluxcd/toolkit/actions)
+
+Experimental toolkit for assembling CD pipelines.
+
+Components:
+* [source-controller](https://github.com/fluxcd/source-controller)
+* [kustomize-controller](https://github.com/fluxcd/kustomize-controller)
diff --git a/go.sum b/go.sum
index 7a5d5664981ab2337d6f62ee4c6916f864d14f20..333dd9c9e7c0e2bdca334f0f3a517ab4ad1af065 100644
--- a/go.sum
+++ b/go.sum
@@ -26,7 +26,6 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
 github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
-github.com/blang/semver v1.1.0 h1:ol1rO7QQB5uy7umSNV7VAmLugfLRD+17sYJujRNYPhg=
 github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
 github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=