Repository: grafana/tanka
Pull request #938 (2023-10-26 16:57:17)

Drone -> Github Actions
From our internal Drone instance to public Github actions runners

github-actions[bot]: [PR Preview Action](https://github.com/rossjrw/pr-preview-action) v1.4.4
:---:
:rocket: Deployed preview to https://grafana.github.io/tanka/pr-preview/pr-938/
on branch [`gh-pages`](https://github.com/grafana/tanka/tree/gh-pages) at 2023-10-26 17:02 UTC
<!-- Sticky Pull Request Commentpr-preview -->
julienduchesne: > Nice one. Admittedly I didn't review the new workflows to make sure they match the previous exactly but we'll find out soon enough.
> 
> The biggest thing to watch out for here is the huge increase in arm64 build time: [41s](https://drone.grafana.net/grafana/tanka/1727/3/1) vs. [7m53s](https://github.com/grafana/tanka/actions/runs/6662167255/job/18106111874), due to the switch from a native builder to emulation. It might be worth doing the Go build as a cross-build by setting `GOARCH` instead of emulating it, to get around at least some of this.

A lot of the time is spent installing jb as well, but we could get it from their github releases instead. So yeah, some optimization could be made for sure

Patch:
diff --git a/.drone/docker-manifest.tmpl b/.drone/docker-manifest.tmpl
deleted file mode 100644
index 2ec7d492..00000000
--- a/.drone/docker-manifest.tmpl
+++ /dev/null
@@ -1,22 +0,0 @@
-image: grafana/tanka:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
-{{#if build.tags}}
-tags:
-{{#each build.tags}}
-  - {{this}}
-{{/each}}
-{{/if}}
-manifests:
-  - image: grafana/tanka:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}amd64
-    platform:
-      architecture: amd64
-      os: linux
-  - image: grafana/tanka:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}arm64
-    platform:
-      architecture: arm64
-      os: linux
-      variant: v8
-  - image: grafana/tanka:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}arm
-    platform:
-      architecture: arm
-      os: linux
-      variant: v7
diff --git a/.drone/drone.jsonnet b/.drone/drone.jsonnet
deleted file mode 100644
index a7a8382a..00000000
--- a/.drone/drone.jsonnet
+++ /dev/null
@@ -1,161 +0,0 @@
-local vault = import 'vault.libsonnet';
-
-local golang = 'golang:1.20';
-
-local volumes = [{ name: 'gopath', temp: {} }];
-local mounts = [{ name: 'gopath', path: '/go' }];
-
-local constraints = {
-  local withRef(ref) = {
-    trigger+: {
-      ref+: [ref],
-    },
-  },
-
-  tags: withRef('refs/tags/v*'),
-  mainPush: withRef('refs/heads/main'),
-  pullRequest: withRef('refs/pull/*/head'),
-};
-
-local go(name, commands) = {
-  name: name,
-  image: golang,
-  volumes: mounts,
-  commands: commands,
-};
-
-local make(target) = go(target, [
-  // Only download it once, then for every step, copy it to the right place.
-  'if [ ! -f linux-amd64/helm ]; then',
-  '  wget -q https://get.helm.sh/helm-v3.9.0-linux-amd64.tar.gz',
-  '  tar -zxvf helm-v3.9.0-linux-amd64.tar.gz',
-  '  rm -f helm-v3.9.0-linux-amd64.tar.gz',
-  'fi',
-  'cp linux-amd64/helm /usr/local/bin/helm',
-  'go install github.com/google/go-jsonnet/cmd/jsonnet@v0.20.0',
-  'make ' + target,
-]);
-
-local pipeline(name) = {
-  kind: 'pipeline',
-  name: name,
-  volumes: volumes,
-  steps: [],
-};
-
-local docker(arch, depends_on=[]) =
-  pipeline('docker-' + arch) {
-    platform: {
-      os: 'linux',
-      arch: arch,
-    },
-    steps: [
-      go('fetch-tags', ['git fetch origin --tags']),
-      make('static'),
-      {
-        name: 'container',
-        image: 'plugins/docker',
-        settings: {
-          repo: 'grafana/tanka',
-          auto_tag: true,
-          auto_tag_suffix: arch,
-          username: { from_secret: vault.dockerhub_username },
-          password: { from_secret: vault.dockerhub_password },
-        },
-      },
-    ],
-    depends_on: depends_on,
-  };
-
-[
-  pipeline('check') {
-    steps: [
-      go('download', ['go mod download']),
-      make('lint'),
-      make('test'),
-      make('cross') { name: 'build' },
-    ],
-  } + constraints.pullRequest + constraints.mainPush,
-
-  pipeline('benchmark against main') {
-    node: {
-      // To ensure that benchmarks are accurate, run this build on a node that doesn't do parallel builds.
-      type: 'no-parallel',
-    },
-    steps: [
-      go('benchmark', [
-        'go install github.com/google/go-jsonnet/cmd/jsonnet@v0.20.0',
-        'go test -bench=. -benchmem -count=6 -run=^$ ./... | tee bench-pr.txt',
-        'git fetch origin main',
-        'git reset --hard origin/main',
-        'go test -bench=. -benchmem -count=6 -run=^$ ./... | tee bench-main.txt',
-        'go install golang.org/x/perf/cmd/...@latest',
-        'benchstat bench-main.txt bench-pr.txt',
-      ]),
-    ],
-  } + constraints.pullRequest,
-
-  pipeline('release') {
-    steps: [
-      go('fetch-tags', ['git fetch origin --tags']),
-      make('cross'),
-      {
-        name: 'publish',
-        image: 'plugins/github-release',
-        settings: {
-          title: '${DRONE_TAG}',
-          note: importstr 'release-note.md',
-          api_key: { from_secret: vault.grafanabot_public_account_token },
-          files: 'dist/*',
-          draft: true,
-        },
-      },
-    ],
-  } + { depends_on: ['check'] } + constraints.tags,
-
-  docker('amd64', depends_on=['check']) + constraints.tags + constraints.mainPush,
-  docker('arm64', depends_on=['check']) + constraints.tags + constraints.mainPush,
-
-  pipeline('manifest-main') {
-    steps: [
-      go('fetch-tags', [
-        'git fetch origin --tags',
-        'echo "main-$(git describe --tags)" > .tags',
-      ]),
-      {
-        name: 'manifest',
-        image: 'plugins/manifest:1.4.0',
-        settings: {
-          ignore_missing: true,
-          spec: '.drone/docker-manifest.tmpl',
-          username: { from_secret: vault.dockerhub_username },
-          password: { from_secret: vault.dockerhub_password },
-        },
-      },
-    ],
-  } + {
-    depends_on: [
-      'docker-amd64',
-      'docker-arm64',
-    ],
-  } + constraints.mainPush,
-
-  pipeline('manifest') {
-    steps: [{
-      name: 'manifest',
-      image: 'plugins/manifest:1.4.0',
-      settings: {
-        auto_tag: true,
-        ignore_missing: true,
-        spec: '.drone/docker-manifest.tmpl',
-        username: { from_secret: vault.dockerhub_username },
-        password: { from_secret: vault.dockerhub_password },
-      },
-    }],
-  } + {
-    depends_on: [
-      'docker-amd64',
-      'docker-arm64',
-    ],
-  } + constraints.tags + constraints.mainPush,
-] + vault.secrets
diff --git a/.drone/drone.yml b/.drone/drone.yml
deleted file mode 100644
index 143da179..00000000
--- a/.drone/drone.yml
+++ /dev/null
@@ -1,318 +0,0 @@
----
-kind: pipeline
-name: check
-steps:
-- commands:
-  - go mod download
-  image: golang:1.20
-  name: download
-  volumes:
-  - name: gopath
-    path: /go
-- commands:
-  - if [ ! -f linux-amd64/helm ]; then
-  - '  wget -q https://get.helm.sh/helm-v3.9.0-linux-amd64.tar.gz'
-  - '  tar -zxvf helm-v3.9.0-linux-amd64.tar.gz'
-  - '  rm -f helm-v3.9.0-linux-amd64.tar.gz'
-  - fi
-  - cp linux-amd64/helm /usr/local/bin/helm
-  - go install github.com/google/go-jsonnet/cmd/jsonnet@v0.20.0
-  - make lint
-  image: golang:1.20
-  name: lint
-  volumes:
-  - name: gopath
-    path: /go
-- commands:
-  - if [ ! -f linux-amd64/helm ]; then
-  - '  wget -q https://get.helm.sh/helm-v3.9.0-linux-amd64.tar.gz'
-  - '  tar -zxvf helm-v3.9.0-linux-amd64.tar.gz'
-  - '  rm -f helm-v3.9.0-linux-amd64.tar.gz'
-  - fi
-  - cp linux-amd64/helm /usr/local/bin/helm
-  - go install github.com/google/go-jsonnet/cmd/jsonnet@v0.20.0
-  - make test
-  image: golang:1.20
-  name: test
-  volumes:
-  - name: gopath
-    path: /go
-- commands:
-  - if [ ! -f linux-amd64/helm ]; then
-  - '  wget -q https://get.helm.sh/helm-v3.9.0-linux-amd64.tar.gz'
-  - '  tar -zxvf helm-v3.9.0-linux-amd64.tar.gz'
-  - '  rm -f helm-v3.9.0-linux-amd64.tar.gz'
-  - fi
-  - cp linux-amd64/helm /usr/local/bin/helm
-  - go install github.com/google/go-jsonnet/cmd/jsonnet@v0.20.0
-  - make cross
-  image: golang:1.20
-  name: build
-  volumes:
-  - name: gopath
-    path: /go
-trigger:
-  ref:
-  - refs/pull/*/head
-  - refs/heads/main
-volumes:
-- name: gopath
-  temp: {}
----
-kind: pipeline
-name: benchmark against main
-node:
-  type: no-parallel
-steps:
-- commands:
-  - go install github.com/google/go-jsonnet/cmd/jsonnet@v0.20.0
-  - go test -bench=. -benchmem -count=6 -run=^$ ./... | tee bench-pr.txt
-  - git fetch origin main
-  - git reset --hard origin/main
-  - go test -bench=. -benchmem -count=6 -run=^$ ./... | tee bench-main.txt
-  - go install golang.org/x/perf/cmd/...@latest
-  - benchstat bench-main.txt bench-pr.txt
-  image: golang:1.20
-  name: benchmark
-  volumes:
-  - name: gopath
-    path: /go
-trigger:
-  ref:
-  - refs/pull/*/head
-volumes:
-- name: gopath
-  temp: {}
----
-depends_on:
-- check
-kind: pipeline
-name: release
-steps:
-- commands:
-  - git fetch origin --tags
-  image: golang:1.20
-  name: fetch-tags
-  volumes:
-  - name: gopath
-    path: /go
-- commands:
-  - if [ ! -f linux-amd64/helm ]; then
-  - '  wget -q https://get.helm.sh/helm-v3.9.0-linux-amd64.tar.gz'
-  - '  tar -zxvf helm-v3.9.0-linux-amd64.tar.gz'
-  - '  rm -f helm-v3.9.0-linux-amd64.tar.gz'
-  - fi
-  - cp linux-amd64/helm /usr/local/bin/helm
-  - go install github.com/google/go-jsonnet/cmd/jsonnet@v0.20.0
-  - make cross
-  image: golang:1.20
-  name: cross
-  volumes:
-  - name: gopath
-    path: /go
-- image: plugins/github-release
-  name: publish
-  settings:
-    api_key:
-      from_secret: grafanabot_pat
-    draft: true
-    files: dist/*
-    note: |
-      This is release ${DRONE_TAG} of Tanka (`tk`). Check out the [CHANGELOG](https://github.com/grafana/tanka/blob/main/CHANGELOG.md) for detailed release notes.
-      ## Install instructions
-
-      #### Binary:
-      ```bash
-      # download the binary (adapt os and arch as needed)
-      $ curl -fSL -o "/usr/local/bin/tk" "https://github.com/grafana/tanka/releases/download/${DRONE_TAG}/tk-linux-amd64"
-
-      # make it executable
-      $ chmod a+x "/usr/local/bin/tk"
-
-      # have fun :)
-      $ tk --help
-      ```
-
-      #### Docker container:
-      https://hub.docker.com/r/grafana/tanka
-      ```bash
-      $ docker pull grafana/tanka:${DRONE_TAG#v}
-      ```
-    title: ${DRONE_TAG}
-trigger:
-  ref:
-  - refs/tags/v*
-volumes:
-- name: gopath
-  temp: {}
----
-depends_on:
-- check
-kind: pipeline
-name: docker-amd64
-platform:
-  arch: amd64
-  os: linux
-steps:
-- commands:
-  - git fetch origin --tags
-  image: golang:1.20
-  name: fetch-tags
-  volumes:
-  - name: gopath
-    path: /go
-- commands:
-  - if [ ! -f linux-amd64/helm ]; then
-  - '  wget -q https://get.helm.sh/helm-v3.9.0-linux-amd64.tar.gz'
-  - '  tar -zxvf helm-v3.9.0-linux-amd64.tar.gz'
-  - '  rm -f helm-v3.9.0-linux-amd64.tar.gz'
-  - fi
-  - cp linux-amd64/helm /usr/local/bin/helm
-  - go install github.com/google/go-jsonnet/cmd/jsonnet@v0.20.0
-  - make static
-  image: golang:1.20
-  name: static
-  volumes:
-  - name: gopath
-    path: /go
-- image: plugins/docker
-  name: container
-  settings:
-    auto_tag: true
-    auto_tag_suffix: amd64
-    password:
-      from_secret: dockerhub_password
-    repo: grafana/tanka
-    username:
-      from_secret: dockerhub_username
-trigger:
-  ref:
-  - refs/tags/v*
-  - refs/heads/main
-volumes:
-- name: gopath
-  temp: {}
----
-depends_on:
-- check
-kind: pipeline
-name: docker-arm64
-platform:
-  arch: arm64
-  os: linux
-steps:
-- commands:
-  - git fetch origin --tags
-  image: golang:1.20
-  name: fetch-tags
-  volumes:
-  - name: gopath
-    path: /go
-- commands:
-  - if [ ! -f linux-amd64/helm ]; then
-  - '  wget -q https://get.helm.sh/helm-v3.9.0-linux-amd64.tar.gz'
-  - '  tar -zxvf helm-v3.9.0-linux-amd64.tar.gz'
-  - '  rm -f helm-v3.9.0-linux-amd64.tar.gz'
-  - fi
-  - cp linux-amd64/helm /usr/local/bin/helm
-  - go install github.com/google/go-jsonnet/cmd/jsonnet@v0.20.0
-  - make static
-  image: golang:1.20
-  name: static
-  volumes:
-  - name: gopath
-    path: /go
-- image: plugins/docker
-  name: container
-  settings:
-    auto_tag: true
-    auto_tag_suffix: arm64
-    password:
-      from_secret: dockerhub_password
-    repo: grafana/tanka
-    username:
-      from_secret: dockerhub_username
-trigger:
-  ref:
-  - refs/tags/v*
-  - refs/heads/main
-volumes:
-- name: gopath
-  temp: {}
----
-depends_on:
-- docker-amd64
-- docker-arm64
-kind: pipeline
-name: manifest-main
-steps:
-- commands:
-  - git fetch origin --tags
-  - echo "main-$(git describe --tags)" > .tags
-  image: golang:1.20
-  name: fetch-tags
-  volumes:
-  - name: gopath
-    path: /go
-- image: plugins/manifest:1.4.0
-  name: manifest
-  settings:
-    ignore_missing: true
-    password:
-      from_secret: dockerhub_password
-    spec: .drone/docker-manifest.tmpl
-    username:
-      from_secret: dockerhub_username
-trigger:
-  ref:
-  - refs/heads/main
-volumes:
-- name: gopath
-  temp: {}
----
-depends_on:
-- docker-amd64
-- docker-arm64
-kind: pipeline
-name: manifest
-steps:
-- image: plugins/manifest:1.4.0
-  name: manifest
-  settings:
-    auto_tag: true
-    ignore_missing: true
-    password:
-      from_secret: dockerhub_password
-    spec: .drone/docker-manifest.tmpl
-    username:
-      from_secret: dockerhub_username
-trigger:
-  ref:
-  - refs/tags/v*
-  - refs/heads/main
-volumes:
-- name: gopath
-  temp: {}
----
-get:
-  name: pat
-  path: infra/data/ci/github/grafanabot
-kind: secret
-name: grafanabot_pat
----
-get:
-  name: username
-  path: infra/data/ci/docker_hub
-kind: secret
-name: dockerhub_username
----
-get:
-  name: password
-  path: infra/data/ci/docker_hub
-kind: secret
-name: dockerhub_password
----
-kind: signature
-hmac: d6e20fdf35f6a2177b563a0db363b55872b276a880165349685c1f6aa1641495
-
-...
diff --git a/.drone/release-note.md b/.drone/release-note.md
deleted file mode 100644
index 3c9d47e7..00000000
--- a/.drone/release-note.md
+++ /dev/null
@@ -1,20 +0,0 @@
-This is release ${DRONE_TAG} of Tanka (`tk`). Check out the [CHANGELOG](https://github.com/grafana/tanka/blob/main/CHANGELOG.md) for detailed release notes.
-## Install instructions
-
-#### Binary:
-```bash
-# download the binary (adapt os and arch as needed)
-$ curl -fSL -o "/usr/local/bin/tk" "https://github.com/grafana/tanka/releases/download/${DRONE_TAG}/tk-linux-amd64"
-
-# make it executable
-$ chmod a+x "/usr/local/bin/tk"
-
-# have fun :)
-$ tk --help
-```
-
-#### Docker container:
-https://hub.docker.com/r/grafana/tanka
-```bash
-$ docker pull grafana/tanka:${DRONE_TAG#v}
-```
diff --git a/.drone/vault.libsonnet b/.drone/vault.libsonnet
deleted file mode 100644
index ce08d436..00000000
--- a/.drone/vault.libsonnet
+++ /dev/null
@@ -1,20 +0,0 @@
-local secret(name, vault_path, key) = {
-  kind: 'secret',
-  name: name,
-  get: {
-    path: vault_path,
-    name: key,
-  },
-};
-
-{
-  dockerhub_username: 'dockerhub_username',
-  dockerhub_password: 'dockerhub_password',
-  grafanabot_public_account_token: 'grafanabot_pat',
-
-  secrets: [
-    secret($.grafanabot_public_account_token, 'infra/data/ci/github/grafanabot', 'pat'),
-    secret($.dockerhub_username, 'infra/data/ci/docker_hub', 'username'),
-    secret($.dockerhub_password, 'infra/data/ci/docker_hub', 'password'),
-  ],
-}
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
new file mode 100644
index 00000000..b0fbe9c6
--- /dev/null
+++ b/.github/workflows/docker.yml
@@ -0,0 +1,136 @@
+# See https://docs.docker.com/build/ci/github-actions/multi-platform/
+name: Docker
+
+on:
+  push:
+    branches:
+      - main
+    tags:
+      - v*
+  pull_request:
+    branches:
+      - '*'
+
+permissions:
+  contents: read
+  id-token: write
+
+env:
+  REGISTRY_IMAGE: grafana/tanka
+  # Docker image tags. See https://github.com/docker/metadata-action for format
+  TAGS_CONFIG: |
+    type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
+    type=sha,prefix={{branch}}-,format=short,enable=${{ github.ref == 'refs/heads/main' }}
+    type=semver,pattern={{version}}
+
+jobs:
+  build:
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        platform:
+          - linux/amd64
+          - linux/arm64
+    
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4
+      - name: Docker meta
+        id: meta
+        uses: docker/metadata-action@v5
+        with:
+          images: ${{ env.REGISTRY_IMAGE }}
+          tags: ${{ env.TAGS_CONFIG }}
+
+      # Setup buildx
+      - name: Set up QEMU
+        uses: docker/setup-qemu-action@v3
+      - name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v3
+
+      # Login to Docker Hub
+      - name: Get Secrets
+        if: github.event_name != 'pull_request'
+        uses: grafana/shared-workflows/actions/get-vault-secrets@main
+        with:
+          # Secrets placed in the ci/common/<path> path in Vault
+          common_secrets: |
+            DOCKERHUB_USERNAME=dockerhub:username
+            DOCKERHUB_TOKEN=dockerhub:password
+
+      - name: Login to Docker Hub
+        if: github.event_name != 'pull_request'
+        uses: docker/login-action@v3
+        with:
+          username: ${{ env.DOCKERHUB_USERNAME }}
+          password: ${{ env.DOCKERHUB_TOKEN }}
+  
+      - name: Build and push by digest
+        id: build
+        uses: docker/build-push-action@v5
+        with:
+          context: .
+          platforms: ${{ matrix.platform }}
+          labels: ${{ steps.meta.outputs.labels }}
+          outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=${{ github.event_name != 'pull_request' }}
+
+      - name: Export digest
+        if: github.event_name != 'pull_request'
+        run: |
+          mkdir -p /tmp/digests
+          digest="${{ steps.build.outputs.digest }}"
+          touch "/tmp/digests/${digest#sha256:}"          
+      - name: Upload digest
+        if: github.event_name != 'pull_request'
+        uses: actions/upload-artifact@v3
+        with:
+          name: digests
+          path: /tmp/digests/*
+          if-no-files-found: error
+          retention-days: 1
+  
+  merge:
+    runs-on: ubuntu-latest
+    if: github.event_name != 'pull_request'
+    needs: 
+      - build
+    steps:
+      - name: Download digests
+        uses: actions/download-artifact@v3
+        with:
+          name: digests
+          path: /tmp/digests
+
+      - name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v3
+    
+      - name: Docker meta
+        id: meta
+        uses: docker/metadata-action@v5
+        with:
+          images: ${{ env.REGISTRY_IMAGE }}
+          tags: ${{ env.TAGS_CONFIG }}
+
+      # Login to Docker Hub
+      - name: Get Secrets
+        uses: grafana/shared-workflows/actions/get-vault-secrets@main
+        with:
+          # Secrets placed in the ci/common/<path> path in Vault
+          common_secrets: |
+            DOCKERHUB_USERNAME=dockerhub:username
+            DOCKERHUB_TOKEN=dockerhub:password
+      - name: Login to Docker Hub
+        uses: docker/login-action@v3
+        with:
+          username: ${{ env.DOCKERHUB_USERNAME }}
+          password: ${{ env.DOCKERHUB_TOKEN }}
+
+      - name: Create manifest list and push
+        working-directory: /tmp/digests
+        run: |
+          docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
+            $(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)          
+      - name: Inspect image
+        run: |
+          docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }}          
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 00000000..0a6abe7a
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,50 @@
+name: Release
+
+on:
+  push:
+    tags:
+      - v*
+
+permissions:
+  contents: write
+
+jobs:
+  release:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          fetch-tags: true
+      - uses: actions/setup-go@v2
+        with:
+          go-version: '1.20'
+      - run: make cross
+      - id: docker_tag
+        run: echo "DOCKER_TAG=${GITHUB_REF_NAME#v}" >> "$GITHUB_ENV"
+      - name: Release
+        uses: softprops/action-gh-release@v1
+        with:
+          body: |
+            This is release `${{ env.GITHUB_REF_NAME }}` of Tanka (`tk`). Check out the [CHANGELOG](https://github.com/grafana/tanka/blob/main/CHANGELOG.md) for detailed release notes.
+            ## Install instructions
+
+            #### Binary:
+            ```bash
+            # download the binary (adapt os and arch as needed)
+            $ curl -fSL -o "/usr/local/bin/tk" "https://github.com/grafana/tanka/releases/download/${{ env.GITHUB_REF_NAME }}/tk-linux-amd64"
+
+            # make it executable
+            $ chmod a+x "/usr/local/bin/tk"
+
+            # have fun :)
+            $ tk --help
+            ```
+
+            #### Docker container:
+            https://hub.docker.com/r/grafana/tanka
+            ```bash
+            $ docker pull grafana/tanka:${{ env.DOCKER_TAG }}
+            ```
+          draft: true
+          files: |
+            dist/*
diff --git a/Dockerfile b/Dockerfile
index 486ed33d..89e53c16 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -39,10 +39,15 @@ RUN export TAG=$(curl --silent "https://api.github.com/repos/kubernetes-sigs/kus
     curl -SL "https://github.com/kubernetes-sigs/kustomize/releases/download/${TAG}/kustomize_${VERSION_TAG}_${OS}_${ARCH}.tar.gz" > kustomize.tgz && \
     tar -xvf kustomize.tgz
 
+FROM golang:1.21.1 as build
+WORKDIR /app
+COPY . .
+RUN make static
+
 # assemble final container
 FROM alpine:3.18
 RUN apk add --no-cache coreutils diffutils less git openssh-client
-COPY tk /usr/local/bin/tk
+COPY --from=build /app/tk /usr/local/bin/tk
 COPY --from=kubectl /usr/local/bin/kubectl /usr/local/bin/kubectl
 COPY --from=jb /usr/local/bin/jb /usr/local/bin/jb
 COPY --from=helm /tmp/helm/helm /usr/local/bin/helm
diff --git a/Makefile b/Makefile
index 4dc47767..86c32d6e 100644
--- a/Makefile
+++ b/Makefile
@@ -38,9 +38,3 @@ cross: $(GOX)
 # Docker container
 container: static
 	docker build -t grafana/tanka .
-
-# CI
-drone:
-	drone jsonnet --source .drone/drone.jsonnet --target .drone/drone.yml --stream --format
-	drone lint .drone/drone.yml
-	drone sign --save grafana/tanka .drone/drone.yml
diff --git a/README.md b/README.md
index e731de5e..94177345 100644
--- a/README.md
+++ b/README.md
@@ -7,9 +7,6 @@
 </p>
 
 <p align="center">
-  <a href="https://cloud.drone.io/grafana/tanka">
-    <img src="https://img.shields.io/drone/build/grafana/tanka?style=flat-square&server=https%3A%2F%2Fdrone.grafana.net">
-  </a>
   <a href="https://github.com/grafana/tanka/releases">
     <img src="https://img.shields.io/github/release/grafana/tanka?style=flat-square" />
   </a>


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
new file mode 100644
index 00000000..47af5a77
--- /dev/null
+++ b/.github/workflows/tests.yml
@@ -0,0 +1,42 @@
+name: Tests
+
+on:
+  push:
+    branches:
+      - main
+  pull_request:
+    branches:
+      - '*'
+
+jobs:
+  lint:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+      - uses: actions/setup-go@v2
+        with:
+          go-version: '1.20'
+      - run: make lint
+  
+  test:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+      - uses: actions/setup-go@v2
+        with:
+          go-version: '1.20'
+      - uses: azure/setup-helm@v3
+        with:
+          version: '3.13.1' 
+      - name: Install jsonnet
+        run: go install github.com/google/go-jsonnet/cmd/jsonnet@v0.20.0
+      - run: make test
+
+  build:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+      - uses: actions/setup-go@v2
+        with:
+          go-version: '1.20'
+      - run: make cross