deployment testing of helm chart with ctlptl, tilt & kind

This commit is contained in:
Iain Sproat
2026-04-01 11:50:43 +01:00
parent c2f50cd71b
commit 476a95b842
24 changed files with 215 additions and 17 deletions
+1 -2
View File
@@ -1,6 +1,5 @@
# Irrelevant source files
deployment/docker/Dockerfile
deployment/helm
deployment/
# Build output and other temporary files
.husky/_/
+1 -1
View File
@@ -41,7 +41,7 @@ jobs:
uses: useblacksmith/build-push-action@30c71162f16ea2c27c3e21523255d209b8b538c1
with:
push: ${{ inputs.PUBLISH }}
tags: ghcr.io/specklesystems/speckle-dui3:${{ inputs.IMAGE_VERSION_TAG }}
tags: ghcr.io/specklesystems/speckle-dui:${{ inputs.IMAGE_VERSION_TAG }}
file: ./deployment/docker/Dockerfile
network: host # to be able to connect to Tailscale and pull private base image during build
allow: network.host # to be able to connect to Tailscale and pull private base image during build
@@ -1,5 +1,5 @@
apiVersion: v2
name: speckle-dui3-chart
name: speckle-dui-chart
description: A Helm chart for deploying the Speckle DUI3 application
# A chart can be either an 'application' or a 'library' chart.
@@ -76,6 +76,7 @@ spec:
secretName: {{ .Values.speckleLicense.secretName }}
items:
- key: {{ .Values.speckleLicense.secretKey }}
path: {{ .Values.speckleLicense.secretKey }}
{{- with .Values.volumes }}
{{- toYaml . | nindent 8 }}
{{- end }}
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "speckle-dui3.fullname" . }}
labels: {{- include "speckle-dui3.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector: {{- include "speckle-dui3.selectorLabels" . | nindent 4 }}
@@ -1,13 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: { { include "speckle-dui3.fullname" . } }
labels: { { - include "speckle-dui3.labels" . | nindent 4 } }
spec:
type: { { .Values.service.type } }
ports:
- port: { { .Values.service.port } }
targetPort: http
protocol: TCP
name: http
selector: { { - include "speckle-dui3.selectorLabels" . | nindent 4 } }
+7
View File
@@ -10,6 +10,13 @@
"build": "nuxt build",
"dev:nuxt": "nuxt dev",
"dev": "concurrently \"nuxt dev\" \"yarn gqlgen:watch\"",
"dev:kind:up": "ctlptl apply --filename ./tests/deployment/helm/cluster-config.yaml",
"dev:kind:down": "ctlptl delete -f ./tests/deployment/helm/cluster-config.yaml",
"dev:kind:helm:up": "yarn run dev:kind:up && tilt up --file ./tests/deployment/helm/Tiltfile --context kind-speckle-dui",
"dev:kind:helm:down": "tilt down --file ./tests/deployment/helm/Tiltfile --context kind-speckle-dui",
"dev:kind:helm:ci": "tilt ci --file ./tests/deployment/helm/Tiltfile --context kind-speckle-dui --timeout 10m",
"docker:build": "docker build -f ./deployment/docker/Dockerfile -t ghcr.io/specklesystems/speckle-dui:local .",
"docker:run": "docker run --rm -p 8083:80 -v ./deployment/docker/configuration.toml:/app/configuration.toml:ro ghcr.io/specklesystems/speckle-dui:local",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare",
+67
View File
@@ -0,0 +1,67 @@
print('🚀 Deploying Speckle DUI into a Kind Cluster via Tilt...')
# we limit tilt to run only on the kind cluster
allow_k8s_contexts(['kind-speckle-dui'])
if k8s_context() != 'kind-speckle-dui':
fail('Failing early as tilt should only ever connect to kind-speckle-dui.')
# Install extensions
load('ext://helm_resource', 'helm_resource', 'helm_repo')
load('ext://k8s_yaml_glob', 'k8s_yaml_glob')
docker_build('ghcr.io/specklesystems/speckle-dui',
context='../../..',
dockerfile='../../../deployment/docker/Dockerfile',
ignore = ['**/.nuxt', '**/node_modules', '**/dist', '**/build', '**/.git', '**/.claude', '**/.cursor', '../../../deployment/**/*', '../../../tests/**/*']
)
# Create namespaces
k8s_yaml_glob('./manifests/*.namespace.yaml')
k8s_yaml('./manifests/coredns.configmap.yaml')
k8s_resource(new_name='coredns',
objects=['coredns:configmap:kube-system'],
resource_deps=[],
labels=['coredns'])
k8s_yaml('./manifests/license.secret.yaml')
# Update CoreDNS to allow for local resolution of services internally (i.e. speckle.internal will be routed to nginx)
local_resource('coredns-up',
cmd='./scripts/coredns-up.sh',
resource_deps=['coredns'],
deps=['./manifests/coredns.configmap.yaml', './scripts/coredns-up.sh'],
labels=['coredns'])
helm_repo('ingress-nginx-repo',
'https://kubernetes.github.io/ingress-nginx')
#nginx should be deployed as the last dependency as it opens ports to services
#it expects these services to exist, which are created by the helm charts above
helm_resource('ingress-nginx',
release_name='ingress-nginx',
namespace='ingress-nginx',
chart='ingress-nginx-repo/ingress-nginx',
flags=['--version=4.8.0',
'--values=./values/nginx.values.yaml',
'--kube-context=kind-speckle-dui'],
deps=['./values/nginx.values.yaml'],
resource_deps=['ingress-nginx-repo', 'coredns'],
labels=['speckle-dependencies'])
helm_resource('speckle-dui',
release_name='speckle-dui',
namespace='speckle-dui',
chart='./../../../deployment/helm/speckle-dui',
flags=['--values=./values/speckle-dui.values.yaml',
'--kube-context=kind-speckle-dui'],
image_deps=[
'ghcr.io/specklesystems/speckle-dui'
],
image_keys=[
('image.repository', 'image.tag')
],
deps=['./../../../deployment/helm/speckle-dui',
'./values/speckle-dui.values.yaml'],
resource_deps=['ingress-nginx', 'coredns'],
labels=['speckle-dui'])
+29
View File
@@ -0,0 +1,29 @@
apiVersion: ctlptl.dev/v1alpha1
kind: Registry
name: ctlptl-registry
port: 5000
---
apiVersion: ctlptl.dev/v1alpha1
kind: Cluster
product: kind
registry: ctlptl-registry
name: kind-speckle-dui
kindV1Alpha4Cluster:
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraMounts: []
extraPortMappings:
- containerPort: 80
hostPort: 80 # Docker requires privileged ports binding permissions https://docs.docker.com/desktop/mac/permission-requirements/#binding-privileged-ports
protocol: TCP
listenAddress: '127.0.0.1' #DO NOT REMOVE - this is required to prevent access from the local network or the world!!!
- containerPort: 443
hostPort: 443 # Docker requires privileged ports binding permissions https://docs.docker.com/desktop/mac/permission-requirements/#binding-privileged-ports
protocol: TCP
listenAddress: '127.0.0.1' #DO NOT REMOVE - this is required to prevent access from the local network or the world!!!
@@ -0,0 +1,24 @@
{ pkgs ? import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/63dacb46bf939521bdc93981b4cbb7ecb58427a0.tar.gz") {} }:
let
corepack = pkgs.stdenv.mkDerivation {
name = "corepack";
buildInputs = [ pkgs.nodejs_22 ];
phases = [ "installPhase" ];
installPhase = ''
mkdir -p $out/bin
corepack enable --install-directory=$out/bin
'';
};
in pkgs.mkShell {
buildInputs = [
pkgs.docker
pkgs.kind
pkgs.kubectl
pkgs.nodejs_22
pkgs.ctlptl
pkgs.kubernetes-helm
pkgs.tilt
corepack
];
}
@@ -0,0 +1,28 @@
apiVersion: v1
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
rewrite name speckle.internal ingress-nginx-controller.ingress-nginx.svc.cluster.local.
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: 'ingress-nginx'
@@ -0,0 +1,8 @@
apiVersion: v1
kind: Secret
metadata:
name: license
namespace: speckle-dui
type: Opaque
data:
license_token: 'Zm9vYmFyCg==' # base64 for 'foobar'
@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: 'speckle-dui'
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/env bash
set -eou pipefail
kubectl --context="kind-speckle-dui" --namespace="kube-system" rollout restart deployment/coredns
kubectl --context="kind-speckle-dui" --namespace="kube-system" rollout status deployment "coredns" --timeout=90s
@@ -0,0 +1,7 @@
controller:
# We must set the kind cluster listen address for every port to '127.0.0.1' when hostNetwork is true
hostNetwork: true
admissionWebhooks:
enabled: false
# progressDeadlineSeconds: 600 #HACK helm chart was complaining that this was less than minReadySeconds https://github.com/kubernetes/ingress-nginx/blob/c72441585e1ab1a32df86e760613d36fa804315d/charts/ingress-nginx/templates/controller-deployment.yaml#L26
tcp: {}
@@ -0,0 +1,16 @@
ingress:
enabled: true
className: "nginx"
annotations: {}
hosts:
- host: speckle.internal
paths:
# Please retain this path, the dashboards expect to serve all paths under the root.
- path: /
pathType: ImplementationSpecific
security:
trustedProxies: []
frameAncestors:
- "speckle.internal"
frameSource:
- "speckle.internal"