This project shows how to set up a local development environment for running Testkube workflows using Tilt, enabling fast iteration on both tests and services without having to commit changes to git or Testkube to run updated tests.
Head over to the Testkube documentation to learn more about Local Test Development and Execution.
You can use the included Tiltfile as is in your own project by adjusting configuration parameters to match your repository setup, or use this as a blueprint for new projects with corresponding requirements. Don't hesitate to open issues on this repo for improvements/bugs/etc.
The project depends on a Testkube Runner Agent running in a local Minikube Cluster, to which Tilt will automatically sync both Workflows and tests as they are updated locally. Furthermore, the projectcan be configured to automatically (re)run tests as they (or the target services) are updated (see below).
Head over to the Testkube documentation to read more about the foundation for the approach used in this project.
- Minikube - Local Kubernetes cluster - https://minikube.sigs.k8s.io/
- Tilt - Development workflow automation - https://tilt.dev
- Helm - Kubernetes package manager - https://helm.sh/
- Kubectl - Kubernetes CLI
- Testkube - Testkube - https://testkube.io/
- Testkube CLI - Testkube CLI - https://docs.testkube.io/articles/cli
Before using this project, ensure:
- Minikube is running - Required k8s context:
minikube - Testkube CLI is installed and you are authenticated with your Testkube Environment - Use
testkube loginto authenticate - Testkube Runner Agent is deployed - Deploy a Testkube Runner Agent as described at https://docs.testkube.io/articles/agents-overview and provide the name and namespace in the corresponding configuration values below.
The Tiltfile can be customized via constants at the top:
AGENT_NAMESPACE = 'minikube-runner-1' # namespace where local Testkube Runner Agent runs
RUNNER_AGENT_NAME = 'minikube-runner-1' # name of the local runner agent - usually the same as the namespace
KUBE_CONTEXT = 'minikube' # your local minikube k8s context
WORKFLOW_DIR = 'workflows' # where workflow yamls live
SERVICE_ROOT = 'services' # code folders that should trigger runs
AUTO_RUN = True # True -> automatically rerun Workflows when tests are updated
AUTO_DELETE = False # True -> automatically delete Workflows from Environment when they are deleted in the filesystem
RUN_SILENTLY = True # True -> run Testkube executions silently
EXECUTION_TAGS = 'local-dev=true' # tags to add to executions triggered locallyThe Tiltfile automatically:
-
Prerequisites:
- Sets to the specified KUBE_CONTEXT as the current context for kubectl
- Checks that the Testkube CLI is installed
- Checks that the Testkube Context is configured for an Environment
- Checks that the Testkube Runner Agent is installed in the specified namespace
-
Watches for changes in:
WORKFLOW_DIR/*.yaml- TestWorkflow definitionsSERVICE_ROOT/<service-name>/- Service code directories
-
Creates Tilt resources for each workflow:
- Update Workflow - Applies workflow changes to Testkube (auto-applies on file change)
- Run Workflow - Executes the workflow on the local runner (auto-runs on code changes)
-
Targets local agent - All workflow executions triggered by Tilt automatically
-
target the
RUNNER_AGENT_NAMErunner agent. -
add the defined
EXECUTION_TAGSfor easy filtering in the Testkube Dashboard -
run silently if
RUN_SILENTLYisTRUE; these executions will not trigger webhooks/events or skew Health and Insights metrics, Read More -
automatically passes a
HOST_NETWORK_ADDRESSvariable which Workflows can use to target services/apps running on host outside of Minikube. -
You can see this in the log output in the Tilt Console for the "Run Workflow.. " resources:
Running cmd: sh -c "bash -lc 'set -euo pipefail;\necho \"Running workflow api-vite-test2 on local runner: minikube-runner-1\"\ntestkube run testworkflow \"api-vite-test2\" --target name=minikube-runner-1 -f --tag local-dev=true --variable HOST_NAME=host.minikube.internal --silent\n'" Running workflow api-vite-test2 on local runner: minikube-runner-1 -
More specifically:
--target name=minikube-runner-1passes theRUNNER_AGENT_NAMERunner name--tag local-dev=truepasses theEXECUTION_TAGS--variable HOST_NAME=host.minikube.internalpasses theHOST_NETWORK_ADDRESS
-
-
Provides local dev overrides - Creates a TestWorkflowTemplate (
minikube-local-dev-override) that mounts the root folder into Minikube so it can be used to override repository content when running tests, see the Configuration Example below.
Starts Tilt UI and watches for changes:
tilt upStops Tilt and cleans up:
tilt downThe Tiltfile provides manual trigger buttons:
- Testkube Runner Agent Status - View cluster and pod status of the Testkube Runner Agent in the AGENT_NAMESPACE
- Testkube Status - Check Testkube connectivity
- Testkube Dashboard - Open Testkube dashboard in browser
- Mount local test folder into Minikube - Mount local filesystem into minikube at
/minikube-host/testkube-local-dev, this is to enable the TestWorkflowTemplate to override test contents cloned from git with files in the local repo.
.
├── services/ # Service code directories -> Tilt will watch this directory for changes to run tests if `AUTO_RUN` is set
│ └── api/ # Example API service with tests
├── workflows/ # TestWorkflow definitions -> Tilt will automatically add/update these Workflows to your Environment
│ ├── api/
│ │ └── api.yaml # API test workflow
│ └── frontend/
│ ├── e2e.yaml # E2E test workflow
│ └── example-1.yaml
└── Tiltfile # Tilt configuration
- Start Tilt:
tilt up - Edit code in
services/<service>/ - Workflow automatically re-runs with your changes
- View results in Tilt UI or Testkube dashboard
- Iterate - Any file change triggers a new run
Workflows will need to be modified to use the minikube-local-dev-override template to use local code when tests are executed:
apiVersion: testworkflows.testkube.io/v1
kind: TestWorkflow
metadata:
name: my-test
spec:
use:
- name: minikube-local-dev-override
config:
workingDir: /services/api/tests # Mount local code here
content:
git:
uri: https://github.com/yourorg/yourrepo
revision: main
paths:
- services/api
# ... rest of workflow definitionThe template injects a step in the beginning of the Workflow that looks for the mounted folder/directory and copies files from there into the cloned /data/repo folder, effectivly overwriting any git content with local files (including deletes).
If the mount is not available the template will fail silently.
The Tiltfile automatically creates/updates a TestWorkflowTemplate in your configured Testkube Environment that overrides git repository context from the Minikube Mount created by the "Mount Tests into Testkube" Resource.
The Template is as follows:
kind: TestWorkflowTemplate
apiVersion: testworkflows.testkube.io/v1
metadata:
name: minikube-local-dev-override
namespace: testkube
spec:
config:
workingDir: # required to specify which folder that contain the tests, to avoid replacing the entire repo
type: string
pod:
volumes:
- name: hostshare
hostPath:
path: /minikube-host/testkube-local-dev # this is the folder mounted into Minikube
type: DirectoryOrCreate
setup:
- name: Overwrite from local
optional: true # optional steps are ignored if they fail, i.e. if the mount or specified folder isn't available
container:
image: busybox
volumeMounts:
- name: hostshare
mountPath: /data/local # makes the mounted folder available to the Workflow
shell: |
# check if mounted volume folder exists
[ -d "/data/local{{ config.workingDir }}" ] || { echo "Folder /data/local{{ config.workingDir }} for local override not found!"; exit 1; }
# delete existing tests (to correctly mirror deleted tests) and copy local tests into repo
rm -rf /data/repo{{ config.workingDir }}
cp -rfv /data/local{{ config.workingDir }} /data/repo{{ config.workingDir }}