From a06a6c50488798a9cf130398b0de65dfd63f0e17 Mon Sep 17 00:00:00 2001 From: Vitalii Valkov Date: Sat, 1 Aug 2026 00:13:37 +0200 Subject: [PATCH 1/5] fix(devspace): make dev work against a standalone install Two things stopped devspace dev from running at all outside the umbrella chart's layout: - devspace 6.3.20 rejects a colon in pipeline and command names, so the config failed to parse before doing anything. The e2e workflow had been rewriting test:e2e to test-e2e in place to get past it. - The deployment was patched by the hardcoded name threads-threads, which only exists when the umbrella chart installs it. It is now resolved by label, which covers both layouts. --- devspace.yaml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/devspace.yaml b/devspace.yaml index 0af57b9..36ad004 100644 --- a/devspace.yaml +++ b/devspace.yaml @@ -25,9 +25,16 @@ functions: else echo "WARNING: ArgoCD Application 'threads' not found in argocd namespace." fi + threads_deployment: |- + # The release name varies by install: the umbrella chart names it + # threads-threads, a standalone install just threads. Resolve it by label + # rather than guessing. + kubectl get deployment -n ${THREADS_NAMESPACE} \ + -l app.kubernetes.io/name=threads \ + -o jsonpath='{.items[0].metadata.name}' patch_deployment: |- echo "Patching threads deployment for DevSpace..." - kubectl patch deployment threads-threads -n ${THREADS_NAMESPACE} --type strategic --patch "$(cat <<'EOF' + kubectl patch deployment "$(threads_deployment)" -n ${THREADS_NAMESPACE} --type strategic --patch "$(cat <<'EOF' spec: template: spec: @@ -94,8 +101,8 @@ deployments: app.kubernetes.io/name: threads-e2e commands: - test:e2e: |- - devspace run-pipeline test:e2e $@ + test-e2e: |- + devspace run-pipeline test-e2e $@ pipelines: dev: @@ -127,7 +134,7 @@ pipelines: stop_dev threads fi - test:e2e: + test-e2e: run: |- create_deployments e2e-runner start_dev e2e-runner & From 38609bd9310f628bc466394aa7e35f2f98694571 Mon Sep 17 00:00:00 2001 From: Vitalii Valkov Date: Sat, 1 Aug 2026 01:04:13 +0200 Subject: [PATCH 2/5] fix(devspace): select the threads pod by name only The selector also pinned app.kubernetes.io/instance to threads, which is the Helm release name -- true for a standalone install, but the umbrella chart names it agyn-platform. devspace then waited for a pod that could not exist and timed out. --- devspace.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/devspace.yaml b/devspace.yaml index 36ad004..bbd9844 100644 --- a/devspace.yaml +++ b/devspace.yaml @@ -160,9 +160,10 @@ hooks: dev: threads: namespace: ${THREADS_NAMESPACE} + # Name only: the instance label is the Helm release, which is threads for a + # standalone install and agyn-platform under the umbrella chart. labelSelector: app.kubernetes.io/name: threads - app.kubernetes.io/instance: threads containers: threads: container: threads From 9d5601f3eb54a906c711ab8c9b67559e294c74bd Mon Sep 17 00:00:00 2001 From: Vitalii Valkov Date: Sat, 1 Aug 2026 01:10:24 +0200 Subject: [PATCH 3/5] fix(devspace): let the dev container finish building The dev container generates from the BSR and compiles before it listens, which takes minutes on a cold module cache. The chart's liveness probe killed it at around 40s, so it restarted forever and never served. Liveness goes. Readiness stays, because without it the pod reports Ready while nothing is on the port and callers get connection refused, but with a threshold long enough to cover a cold build. --- devspace.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/devspace.yaml b/devspace.yaml index bbd9844..4b6989c 100644 --- a/devspace.yaml +++ b/devspace.yaml @@ -49,6 +49,18 @@ functions: - name: threads image: ghcr.io/agynio/devcontainer-go:1 # keep in sync with E2E_IMAGE workingDir: /opt/app/data + # The dev container generates and compiles before it listens, + # which takes minutes. Liveness would restart it mid-build, so it + # goes; readiness stays -- without it the pod reports Ready while + # nothing is on the port and callers get connection refused -- but + # with a threshold long enough to cover a cold build. + livenessProbe: null + startupProbe: null + readinessProbe: + tcpSocket: + port: 50051 + periodSeconds: 10 + failureThreshold: 120 command: - sh - -c From 11198320820a47db21848e1bc3837b0e67328f4c Mon Sep 17 00:00:00 2001 From: Vitalii Valkov Date: Sat, 1 Aug 2026 01:18:54 +0200 Subject: [PATCH 4/5] fix(devspace): wait for the sync instead of racing it devspace starts syncing only after the pod reports ready, so a container that gives up on the sync restarts, and the sync it was waiting for never lands: the two waited on each other until the backoff won. The wait is now long enough to lose that race safely, and covers the whole set generation needs rather than go.mod alone, which could let buf run against a half synced tree. --- devspace.yaml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/devspace.yaml b/devspace.yaml index 4b6989c..e6661c6 100644 --- a/devspace.yaml +++ b/devspace.yaml @@ -66,10 +66,22 @@ functions: - -c - | set -eu + # devspace only starts syncing once the pod is up, and waits + # for it to be ready first -- so exiting here restarts the + # container and the sync never lands. Wait for the whole set + # generation needs, not just go.mod, or buf runs on a half + # synced tree. elapsed=0 - while [ ! -f /opt/app/data/go.mod ]; do + until [ -f /opt/app/data/go.mod ] \ + && [ -f /opt/app/data/go.sum ] \ + && [ -f /opt/app/data/buf.gen.yaml ] \ + && [ -f /opt/app/data/buf.yaml ]; do sleep 1; elapsed=$((elapsed + 1)) - [ "$elapsed" -ge 120 ] && { echo "ERROR: sync timeout" >&2; exit 1; } + if [ "$elapsed" -ge 600 ]; then + echo "ERROR: sync timeout waiting for source files" >&2 + ls -la /opt/app/data >&2 || true + exit 1 + fi done buf generate buf.build/agynio/api --path agynio/api/threads/v1 --path agynio/api/notifications/v1 --path agynio/api/identity/v1 --path agynio/api/metering/v1 --path agynio/api/authorization/v1 --path agynio/api/agents/v1 exec go run ./cmd/threads From 956a67e61f70ba5047dc467cd0c0a4b2066a003b Mon Sep 17 00:00:00 2001 From: Vitalii Valkov Date: Sat, 1 Aug 2026 01:25:21 +0200 Subject: [PATCH 5/5] fix(devspace): drop the readiness probe too devspace does not start syncing until the pod is ready, so a readiness probe on the service port deadlocks the dev container: no source, so no listener, so never ready, so no sync. The dev pipeline already waits on port 50051 itself once the sync is through. --- devspace.yaml | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/devspace.yaml b/devspace.yaml index e6661c6..b35c988 100644 --- a/devspace.yaml +++ b/devspace.yaml @@ -49,18 +49,15 @@ functions: - name: threads image: ghcr.io/agynio/devcontainer-go:1 # keep in sync with E2E_IMAGE workingDir: /opt/app/data - # The dev container generates and compiles before it listens, - # which takes minutes. Liveness would restart it mid-build, so it - # goes; readiness stays -- without it the pod reports Ready while - # nothing is on the port and callers get connection refused -- but - # with a threshold long enough to cover a cold build. + # All three go. The container generates and compiles before it + # listens, so liveness would restart it mid-build -- and devspace + # will not start syncing until the pod is ready, so a readiness + # probe on the port deadlocks: no source, so no listener, so never + # ready, so no sync. The dev pipeline waits on port 50051 itself + # once the sync is through. livenessProbe: null startupProbe: null - readinessProbe: - tcpSocket: - port: 50051 - periodSeconds: 10 - failureThreshold: 120 + readinessProbe: null command: - sh - -c