Files
pikasTech-unidesk/src/components/microservices/k3sctl-adapter/k3s/ci/unidesk-ci.pipeline.yaml
T
2026-05-18 13:07:34 +00:00

1052 lines
41 KiB
YAML

apiVersion: v1
kind: Namespace
metadata:
name: unidesk-ci
labels:
app.kubernetes.io/part-of: unidesk
unidesk.ai/purpose: ci
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: unidesk-ci-runner
namespace: unidesk-ci
labels:
app.kubernetes.io/name: unidesk-ci
app.kubernetes.io/part-of: unidesk
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: unidesk-ci-runner
namespace: unidesk-ci
rules:
- apiGroups: [""]
resources: ["pods", "pods/log", "services"]
verbs: ["get", "list", "watch", "create", "delete", "patch"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "delete", "patch"]
- apiGroups: ["tekton.dev"]
resources: ["pipelineruns", "taskruns"]
verbs: ["get", "list", "watch", "create", "delete", "patch"]
- apiGroups: ["triggers.tekton.dev"]
resources: ["eventlisteners", "triggers", "triggerbindings", "triggertemplates", "interceptors"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: unidesk-ci-runner
namespace: unidesk-ci
subjects:
- kind: ServiceAccount
name: unidesk-ci-runner
namespace: unidesk-ci
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: unidesk-ci-runner
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: unidesk-ci-trigger-reader
labels:
app.kubernetes.io/name: unidesk-ci
app.kubernetes.io/part-of: unidesk
rules:
- apiGroups: ["triggers.tekton.dev"]
resources: ["clusterinterceptors", "clustertriggerbindings"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: unidesk-ci-trigger-reader
labels:
app.kubernetes.io/name: unidesk-ci
app.kubernetes.io/part-of: unidesk
subjects:
- kind: ServiceAccount
name: unidesk-ci-runner
namespace: unidesk-ci
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: unidesk-ci-trigger-reader
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: unidesk-ci-dev-e2e-manager
labels:
app.kubernetes.io/name: unidesk-ci
app.kubernetes.io/part-of: unidesk
rules:
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["get", "list", "watch", "create", "delete", "patch"]
- apiGroups: [""]
resources: ["configmaps", "services", "pods", "pods/log"]
verbs: ["get", "list", "watch", "create", "delete", "patch"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "delete", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: unidesk-ci-dev-e2e-manager
labels:
app.kubernetes.io/name: unidesk-ci
app.kubernetes.io/part-of: unidesk
subjects:
- kind: ServiceAccount
name: unidesk-ci-runner
namespace: unidesk-ci
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: unidesk-ci-dev-e2e-manager
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: unidesk-ci-cross-namespace
namespace: unidesk
rules:
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: unidesk-ci-cross-namespace
namespace: unidesk
subjects:
- kind: ServiceAccount
name: unidesk-ci-runner
namespace: unidesk-ci
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: unidesk-ci-cross-namespace
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: unidesk-ci-cache
namespace: unidesk-ci
labels:
app.kubernetes.io/name: unidesk-ci
app.kubernetes.io/part-of: unidesk
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
---
apiVersion: v1
kind: ConfigMap
metadata:
name: unidesk-ci-budgets
namespace: unidesk-ci
labels:
app.kubernetes.io/name: unidesk-ci
app.kubernetes.io/part-of: unidesk
data:
firstPaintMs: "10000"
traceSummaryMs: "10000"
traceStepsMs: "20000"
traceStepDetailMs: "20000"
overviewP95Ms: "20000"
---
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: unidesk-repo-check
namespace: unidesk-ci
labels:
app.kubernetes.io/name: unidesk-ci
app.kubernetes.io/component: repo-check
spec:
params:
- name: repo-url
type: string
- name: revision
type: string
- name: image
type: string
default: unidesk-code-queue:dev
workspaces:
- name: source
volumes:
- name: docker-sock
hostPath:
path: /var/run/docker.sock
type: Socket
steps:
- name: clone
image: alpine/git:2.45.2
env:
- name: HTTP_PROXY
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: HTTPS_PROXY
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: ALL_PROXY
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: NO_PROXY
value: "localhost,127.0.0.1,::1,ci-git-mirror,ci-git-mirror.unidesk-ci,ci-git-mirror.unidesk-ci.svc,ci-git-mirror.unidesk-ci.svc.cluster.local,d601-provider-egress-proxy,d601-provider-egress-proxy.unidesk,d601-provider-egress-proxy.unidesk.svc,d601-provider-egress-proxy.unidesk.svc.cluster.local,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,code-queue-ci-read,code-queue-ci-read.unidesk-ci,code-queue-ci-read.unidesk-ci.svc,code-queue-ci-read.unidesk-ci.svc.cluster.local"
- name: http_proxy
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: https_proxy
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: all_proxy
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: no_proxy
value: "localhost,127.0.0.1,::1,ci-git-mirror,ci-git-mirror.unidesk-ci,ci-git-mirror.unidesk-ci.svc,ci-git-mirror.unidesk-ci.svc.cluster.local,d601-provider-egress-proxy,d601-provider-egress-proxy.unidesk,d601-provider-egress-proxy.unidesk.svc,d601-provider-egress-proxy.unidesk.svc.cluster.local,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,code-queue-ci-read,code-queue-ci-read.unidesk-ci,code-queue-ci-read.unidesk-ci.svc,code-queue-ci-read.unidesk-ci.svc.cluster.local"
script: |
#!/bin/sh
set -eu
rm -rf "$(workspaces.source.path)/repo"
git clone --filter=blob:none "$(params.repo-url)" "$(workspaces.source.path)/repo"
cd "$(workspaces.source.path)/repo"
git fetch --depth=1 origin "$(params.revision)"
git checkout --detach FETCH_HEAD
git rev-parse HEAD | tee "$(workspaces.source.path)/commit.txt"
- name: install-and-check
image: "$(params.image)"
imagePullPolicy: Never
env:
- name: DOCKER_HOST
value: unix:///var/run/docker.sock
- name: BUN_INSTALL_CACHE_DIR
value: "$(workspaces.source.path)/cache/bun"
- name: HTTP_PROXY
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: HTTPS_PROXY
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: ALL_PROXY
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: NO_PROXY
value: "localhost,127.0.0.1,::1,d601-provider-egress-proxy,d601-provider-egress-proxy.unidesk,d601-provider-egress-proxy.unidesk.svc,d601-provider-egress-proxy.unidesk.svc.cluster.local,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,code-queue-ci-read,code-queue-ci-read.unidesk-ci,code-queue-ci-read.unidesk-ci.svc,code-queue-ci-read.unidesk-ci.svc.cluster.local"
- name: http_proxy
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: https_proxy
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: all_proxy
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: no_proxy
value: "localhost,127.0.0.1,::1,d601-provider-egress-proxy,d601-provider-egress-proxy.unidesk,d601-provider-egress-proxy.unidesk.svc,d601-provider-egress-proxy.unidesk.svc.cluster.local,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,code-queue-ci-read,code-queue-ci-read.unidesk-ci,code-queue-ci-read.unidesk-ci.svc,code-queue-ci-read.unidesk-ci.svc.cluster.local"
volumeMounts:
- name: docker-sock
mountPath: /var/run/docker.sock
script: |
#!/usr/bin/env bash
set -euo pipefail
cd "$(workspaces.source.path)/repo"
command -v bun
command -v git
command -v docker
docker compose version >/dev/null
bun install --frozen-lockfile
(cd src && bun install --frozen-lockfile)
UNIDESK_D601_RUST_CHECK=1 bun scripts/cli.ts check --full --rust
---
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: unidesk-code-queue-read-perf
namespace: unidesk-ci
labels:
app.kubernetes.io/name: unidesk-ci
app.kubernetes.io/component: code-queue-performance
spec:
params:
- name: revision
type: string
- name: app-image
type: string
default: oven/bun:1-debian
workspaces:
- name: source
steps:
- name: start-read-service
image: "$(params.app-image)"
imagePullPolicy: Never
env:
- name: HTTP_PROXY
value: ""
- name: HTTPS_PROXY
value: ""
- name: ALL_PROXY
value: ""
- name: NO_PROXY
value: "localhost,127.0.0.1,::1,kubernetes,kubernetes.default,kubernetes.default.svc,kubernetes.default.svc.cluster.local"
- name: http_proxy
value: ""
- name: https_proxy
value: ""
- name: all_proxy
value: ""
- name: no_proxy
value: "localhost,127.0.0.1,::1,kubernetes,kubernetes.default,kubernetes.default.svc,kubernetes.default.svc.cluster.local"
script: |
#!/bin/bash
set -euo pipefail
kube_api="https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT_HTTPS}"
kube_token="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
kube_ca="/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
kube_namespace="$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)"
kube() {
local method="$1"
shift
curl -fsS --cacert "$kube_ca" -H "Authorization: Bearer $kube_token" -X "$method" "$@"
}
delete_if_exists() {
local path="$1"
local code
code="$(curl -sS -o /tmp/unidesk-ci-delete-response -w "%{http_code}" --cacert "$kube_ca" -H "Authorization: Bearer $kube_token" -X DELETE "$kube_api/$path")"
if [ "$code" = "200" ] || [ "$code" = "202" ] || [ "$code" = "404" ]; then
return 0
fi
cat /tmp/unidesk-ci-delete-response >&2
return 1
}
wait_deleted() {
local path="$1"
local deadline=$((SECONDS + 120))
local code
while [ "$SECONDS" -lt "$deadline" ]; do
code="$(curl -sS -o /tmp/unidesk-ci-get-response -w "%{http_code}" --cacert "$kube_ca" -H "Authorization: Bearer $kube_token" "$kube_api/$path")"
if [ "$code" = "404" ]; then
return 0
fi
if [ "$code" != "200" ]; then
cat /tmp/unidesk-ci-get-response >&2
return 1
fi
sleep 2
done
echo "timeout waiting for $path deletion" >&2
return 1
}
delete_if_exists "apis/apps/v1/namespaces/$kube_namespace/deployments/code-queue-ci-read"
delete_if_exists "api/v1/namespaces/$kube_namespace/services/code-queue-ci-read"
wait_deleted "apis/apps/v1/namespaces/$kube_namespace/deployments/code-queue-ci-read"
cat >/tmp/code-queue-ci-read-deployment.yaml <<YAML
apiVersion: apps/v1
kind: Deployment
metadata:
name: code-queue-ci-read
namespace: unidesk-ci
labels:
app.kubernetes.io/name: code-queue
app.kubernetes.io/component: ci-read
app.kubernetes.io/part-of: unidesk
unidesk.ai/ci-revision: "$(params.revision)"
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: code-queue
app.kubernetes.io/component: ci-read
strategy:
type: Recreate
template:
metadata:
labels:
app.kubernetes.io/name: code-queue
app.kubernetes.io/component: ci-read
app.kubernetes.io/part-of: unidesk
unidesk.ai/node-id: D601
unidesk.ai/ci-task-run: "$(context.taskRun.name)"
spec:
nodeSelector:
unidesk.ai/node-id: D601
terminationGracePeriodSeconds: 10
containers:
- name: code-queue
image: "$(params.app-image)"
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 4222
envFrom:
- secretRef:
name: code-queue-env
optional: true
env:
- name: HOST
value: "0.0.0.0"
- name: PORT
value: "4222"
- name: DATABASE_URL
value: "postgres://unidesk:unidesk_dev_password@d601-tcp-egress-gateway.unidesk.svc.cluster.local:15432/unidesk"
- name: CODE_QUEUE_INSTANCE_ID
value: "CI-read"
- name: CODE_QUEUE_SERVICE_ROLE
value: "read"
- name: CODE_QUEUE_SCHEDULER_ENABLED
value: "false"
- name: CODE_QUEUE_STARTUP_OA_BACKFILL_ENABLED
value: "false"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_ENABLED
value: "false"
- name: CODE_QUEUE_CODEX_SQLITE_LOG_EXPORT_ENABLED
value: "false"
- name: CODE_QUEUE_EGRESS_PROXY_ENABLED
value: "true"
- name: CODE_QUEUE_EGRESS_PROXY_URL
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: CODE_QUEUE_EGRESS_PROXY_NO_PROXY
value: "localhost,127.0.0.1,::1,code-queue-ci-read,code-queue-ci-read.unidesk-ci,code-queue-ci-read.unidesk-ci.svc,code-queue-ci-read.unidesk-ci.svc.cluster.local,d601-provider-egress-proxy,d601-provider-egress-proxy.unidesk,d601-provider-egress-proxy.unidesk.svc,d601-provider-egress-proxy.unidesk.svc.cluster.local,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,backend-core,oa-event-flow,database,hyueapi.com,.hyueapi.com"
- name: HTTP_PROXY
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: HTTPS_PROXY
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: ALL_PROXY
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: NO_PROXY
value: "localhost,127.0.0.1,::1,code-queue-ci-read,code-queue-ci-read.unidesk-ci,code-queue-ci-read.unidesk-ci.svc,code-queue-ci-read.unidesk-ci.svc.cluster.local,d601-provider-egress-proxy,d601-provider-egress-proxy.unidesk,d601-provider-egress-proxy.unidesk.svc,d601-provider-egress-proxy.unidesk.svc.cluster.local,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,backend-core,oa-event-flow,database,hyueapi.com,.hyueapi.com"
- name: http_proxy
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: https_proxy
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: all_proxy
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: no_proxy
value: "localhost,127.0.0.1,::1,code-queue-ci-read,code-queue-ci-read.unidesk-ci,code-queue-ci-read.unidesk-ci.svc,code-queue-ci-read.unidesk-ci.svc.cluster.local,d601-provider-egress-proxy,d601-provider-egress-proxy.unidesk,d601-provider-egress-proxy.unidesk.svc,d601-provider-egress-proxy.unidesk.svc.cluster.local,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,backend-core,oa-event-flow,database,hyueapi.com,.hyueapi.com"
- name: CODE_QUEUE_DATA_DIR
value: "/var/lib/unidesk/code-queue-ci"
- name: CODE_QUEUE_WORKDIR
value: "/workspace"
- name: CODE_QUEUE_CODEX_HOME
value: "/var/lib/unidesk/code-queue-ci/codex-home"
- name: CODE_QUEUE_OPENCODE_XDG_DIR
value: "/var/lib/unidesk/code-queue-ci/opencode-xdg"
- name: CODE_QUEUE_DEFAULT_MODEL
value: "gpt-5.5"
- name: CODE_QUEUE_MODELS
value: "gpt-5.5,gpt-5.4-mini,gpt-5.4,minimax-m2.7"
- name: CODE_QUEUE_DATABASE_POOL_MAX
value: "4"
- name: CODE_QUEUE_IN_MEMORY_OUTPUT_RECORDS
value: "5"
- name: CODE_QUEUE_IN_MEMORY_EVENT_RECORDS
value: "5"
- name: OA_EVENT_FLOW_BASE_URL
value: "http://d601-tcp-egress-gateway.unidesk.svc.cluster.local:4255"
- name: LOG_FILE
value: "/var/log/unidesk/code-queue-ci-read.jsonl"
- name: NODE_OPTIONS
value: "--max-old-space-size=512"
readinessProbe:
httpGet:
path: /live
port: http
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 20
startupProbe:
httpGet:
path: /live
port: http
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 84
livenessProbe:
httpGet:
path: /live
port: http
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 6
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 1Gi
volumeMounts:
- name: source
mountPath: /app
- name: state
mountPath: /var/lib/unidesk/code-queue-ci
- name: logs
mountPath: /var/log/unidesk
volumes:
- name: source
hostPath:
path: "$(workspaces.source.path)/repo"
type: Directory
- name: state
emptyDir: {}
- name: logs
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: code-queue-ci-read
namespace: unidesk-ci
labels:
app.kubernetes.io/name: code-queue
app.kubernetes.io/component: ci-read
app.kubernetes.io/part-of: unidesk
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: code-queue
app.kubernetes.io/component: ci-read
ports:
- name: http
port: 4222
targetPort: http
YAML
csplit -s -f /tmp/code-queue-ci-read- /tmp/code-queue-ci-read-deployment.yaml '/^---$/' '{*}'
kube PATCH \
-H "Content-Type: application/apply-patch+yaml" \
--data-binary @/tmp/code-queue-ci-read-00 \
"$kube_api/apis/apps/v1/namespaces/$kube_namespace/deployments/code-queue-ci-read?fieldManager=unidesk-ci&force=true" >/dev/null
kube PATCH \
-H "Content-Type: application/apply-patch+yaml" \
--data-binary @/tmp/code-queue-ci-read-01 \
"$kube_api/api/v1/namespaces/$kube_namespace/services/code-queue-ci-read?fieldManager=unidesk-ci&force=true" >/dev/null
deadline=$((SECONDS + 420))
while [ "$SECONDS" -lt "$deadline" ]; do
status="$(kube GET "$kube_api/apis/apps/v1/namespaces/$kube_namespace/deployments/code-queue-ci-read")"
replicas="$(printf '%s' "$status" | jq -r '.spec.replicas // 1')"
available="$(printf '%s' "$status" | jq -r '.status.availableReplicas // 0')"
updated="$(printf '%s' "$status" | jq -r '.status.updatedReplicas // 0')"
observed="$(printf '%s' "$status" | jq -r '.status.observedGeneration // 0')"
generation="$(printf '%s' "$status" | jq -r '.metadata.generation // 0')"
if [ "$available" -ge "$replicas" ] && [ "$updated" -ge "$replicas" ] && [ "$observed" -ge "$generation" ]; then
echo "code_queue_ci_read_rollout=available replicas=$available generation=$generation"
exit 0
fi
sleep 2
done
echo "code_queue_ci_read_rollout=timeout" >&2
kube GET "$kube_api/apis/apps/v1/namespaces/$kube_namespace/deployments/code-queue-ci-read" >&2
exit 1
- name: measure
image: "$(params.app-image)"
imagePullPolicy: Never
workingDir: "$(workspaces.source.path)/repo"
env:
- name: CI_CODE_QUEUE_URL
value: "http://code-queue-ci-read.unidesk-ci.svc.cluster.local:4222"
- name: HTTP_PROXY
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: HTTPS_PROXY
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: ALL_PROXY
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: NO_PROXY
value: "localhost,127.0.0.1,::1,code-queue-ci-read,code-queue-ci-read.unidesk-ci,code-queue-ci-read.unidesk-ci.svc,code-queue-ci-read.unidesk-ci.svc.cluster.local,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,d601-provider-egress-proxy,d601-provider-egress-proxy.unidesk,d601-provider-egress-proxy.unidesk.svc,d601-provider-egress-proxy.unidesk.svc.cluster.local"
- name: http_proxy
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: https_proxy
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: all_proxy
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: no_proxy
value: "localhost,127.0.0.1,::1,code-queue-ci-read,code-queue-ci-read.unidesk-ci,code-queue-ci-read.unidesk-ci.svc,code-queue-ci-read.unidesk-ci.svc.cluster.local,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,d601-provider-egress-proxy,d601-provider-egress-proxy.unidesk,d601-provider-egress-proxy.unidesk.svc,d601-provider-egress-proxy.unidesk.svc.cluster.local"
- name: FIRST_PAINT_BUDGET_MS
valueFrom:
configMapKeyRef:
name: unidesk-ci-budgets
key: firstPaintMs
- name: TRACE_SUMMARY_BUDGET_MS
valueFrom:
configMapKeyRef:
name: unidesk-ci-budgets
key: traceSummaryMs
- name: TRACE_STEPS_BUDGET_MS
valueFrom:
configMapKeyRef:
name: unidesk-ci-budgets
key: traceStepsMs
- name: TRACE_STEP_DETAIL_BUDGET_MS
valueFrom:
configMapKeyRef:
name: unidesk-ci-budgets
key: traceStepDetailMs
- name: OVERVIEW_P95_BUDGET_MS
valueFrom:
configMapKeyRef:
name: unidesk-ci-budgets
key: overviewP95Ms
script: |
#!/usr/bin/env bash
set -euo pipefail
bun scripts/ci-code-queue-read-perf.ts
- name: cleanup
image: "$(params.app-image)"
imagePullPolicy: Never
env:
- name: HTTP_PROXY
value: ""
- name: HTTPS_PROXY
value: ""
- name: ALL_PROXY
value: ""
- name: NO_PROXY
value: "localhost,127.0.0.1,::1,kubernetes,kubernetes.default,kubernetes.default.svc,kubernetes.default.svc.cluster.local"
- name: http_proxy
value: ""
- name: https_proxy
value: ""
- name: all_proxy
value: ""
- name: no_proxy
value: "localhost,127.0.0.1,::1,kubernetes,kubernetes.default,kubernetes.default.svc,kubernetes.default.svc.cluster.local"
script: |
#!/bin/bash
set -euo pipefail
kube_api="https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT_HTTPS}"
kube_token="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
kube_ca="/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
kube_namespace="$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)"
delete_resource() {
local path="$1"
local code
code="$(curl -sS -o /tmp/unidesk-ci-delete-response -w "%{http_code}" --cacert "$kube_ca" -H "Authorization: Bearer $kube_token" -X DELETE "$kube_api/$path")"
if [ "$code" = "200" ] || [ "$code" = "202" ] || [ "$code" = "404" ]; then
return 0
fi
cat /tmp/unidesk-ci-delete-response >&2
return 1
}
delete_resource "apis/apps/v1/namespaces/$kube_namespace/deployments/code-queue-ci-read"
delete_resource "api/v1/namespaces/$kube_namespace/services/code-queue-ci-read"
---
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: unidesk-dev-namespace-e2e
namespace: unidesk-ci
labels:
app.kubernetes.io/name: unidesk-ci
app.kubernetes.io/component: dev-namespace-e2e
spec:
params:
- name: repo-url
type: string
default: https://github.com/pikasTech/unidesk
- name: desired-ref
type: string
default: master
- name: deploy-commit
type: string
- name: environment
type: string
default: dev
- name: run-id
type: string
- name: keep-namespace
type: string
default: "false"
- name: app-image
type: string
default: unidesk-code-queue:dev
- name: backend-core-commit
type: string
default: unknown
- name: frontend-commit
type: string
default: unknown
- name: code-queue-commit
type: string
default: unknown
- name: deploy-json-b64
type: string
default: ""
workspaces:
- name: source
steps:
- name: namespace-smoke-e2e
image: "$(params.app-image)"
imagePullPolicy: Never
env:
- name: HTTP_PROXY
value: ""
- name: HTTPS_PROXY
value: ""
- name: ALL_PROXY
value: ""
- name: NO_PROXY
value: "localhost,127.0.0.1,::1,kubernetes,kubernetes.default,kubernetes.default.svc,kubernetes.default.svc.cluster.local"
- name: http_proxy
value: ""
- name: https_proxy
value: ""
- name: all_proxy
value: ""
- name: no_proxy
value: "localhost,127.0.0.1,::1,kubernetes,kubernetes.default,kubernetes.default.svc,kubernetes.default.svc.cluster.local"
script: |
#!/usr/bin/env bash
set -euo pipefail
ns="unidesk-ci-e2e-$(params.run-id)"
keep="$(params.keep-namespace)"
run_dir="$(workspaces.source.path)/dev-e2e-$(params.run-id)"
mkdir -p "$run_dir"
result_json="$run_dir/dev-e2e-result.json"
deploy_json_b64="$(params.deploy-json-b64)"
backend_commit="$(params.backend-core-commit)"
frontend_commit="$(params.frontend-commit)"
code_queue_commit="$(params.code-queue-commit)"
kube_api="https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT_HTTPS}"
kube_token="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
kube_ca="/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
kube() {
local method="$1"
shift
curl -fsS --cacert "$kube_ca" -H "Authorization: Bearer $kube_token" -X "$method" "$@"
}
delete_path() {
local path="$1"
local code
code="$(curl -sS -o /tmp/unidesk-dev-e2e-delete-response -w "%{http_code}" --cacert "$kube_ca" -H "Authorization: Bearer $kube_token" -X DELETE "$kube_api/$path")"
if [ "$code" = "200" ] || [ "$code" = "202" ] || [ "$code" = "404" ]; then
return 0
fi
cat /tmp/unidesk-dev-e2e-delete-response >&2
return 1
}
cleanup() {
if [ "$keep" = "true" ]; then
echo "dev_e2e_namespace_retained=$ns"
return 0
fi
delete_path "api/v1/namespaces/$ns" || true
echo "dev_e2e_namespace_deleted=$ns"
}
trap cleanup EXIT
delete_path "api/v1/namespaces/$ns"
cat >/tmp/dev-e2e-namespace.yaml <<YAML
apiVersion: v1
kind: Namespace
metadata:
name: $ns
labels:
app.kubernetes.io/part-of: unidesk
unidesk.ai/purpose: ci-dev-e2e
unidesk.ai/deploy-ref: master-deploy-json-dev
YAML
kube PATCH \
-H "Content-Type: application/apply-patch+yaml" \
--data-binary @/tmp/dev-e2e-namespace.yaml \
"$kube_api/api/v1/namespaces/$ns?fieldManager=unidesk-ci&force=true" >/dev/null
cat >/tmp/dev-e2e-configmap.yaml <<YAML
apiVersion: v1
kind: ConfigMap
metadata:
name: desired-manifest
namespace: $ns
labels:
app.kubernetes.io/name: unidesk-dev-namespace-e2e
app.kubernetes.io/part-of: unidesk
data:
deployCommit: "$(params.deploy-commit)"
environment: "$(params.environment)"
backendCoreCommit: "$backend_commit"
frontendCommit: "$frontend_commit"
codeQueueCommit: "$code_queue_commit"
deploy.json.b64: "$deploy_json_b64"
YAML
kube PATCH \
-H "Content-Type: application/apply-patch+yaml" \
--data-binary @/tmp/dev-e2e-configmap.yaml \
"$kube_api/api/v1/namespaces/$ns/configmaps/desired-manifest?fieldManager=unidesk-ci&force=true" >/dev/null
cat >/tmp/dev-e2e-target.yaml <<YAML
apiVersion: apps/v1
kind: Deployment
metadata:
name: dev-e2e-target
namespace: $ns
labels:
app.kubernetes.io/name: unidesk-dev-namespace-e2e
app.kubernetes.io/component: smoke-target
app.kubernetes.io/part-of: unidesk
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: unidesk-dev-namespace-e2e
app.kubernetes.io/component: smoke-target
template:
metadata:
labels:
app.kubernetes.io/name: unidesk-dev-namespace-e2e
app.kubernetes.io/component: smoke-target
app.kubernetes.io/part-of: unidesk
spec:
nodeSelector:
unidesk.ai/node-id: D601
terminationGracePeriodSeconds: 5
containers:
- name: smoke-target
image: "$(params.app-image)"
imagePullPolicy: IfNotPresent
command:
- bun
- -e
- |
const port = Number(process.env.PORT || 8080);
const payload = {
ok: true,
environment: "dev",
namespace: process.env.CI_E2E_NAMESPACE,
deployCommit: process.env.CI_E2E_DEPLOY_COMMIT,
backendCoreCommit: process.env.BACKEND_CORE_COMMIT,
frontendCommit: process.env.FRONTEND_COMMIT,
codeQueueCommit: process.env.CODE_QUEUE_COMMIT
};
Bun.serve({
hostname: "0.0.0.0",
port,
fetch(req) {
const url = new URL(req.url);
if (url.pathname === "/health" || url.pathname === "/") {
return Response.json(payload);
}
return new Response("not found", { status: 404 });
}
});
console.log(JSON.stringify({ listening: port, ...payload }));
await new Promise(() => {});
ports:
- name: http
containerPort: 8080
env:
- name: PORT
value: "8080"
- name: CI_E2E_NAMESPACE
value: "$ns"
- name: CI_E2E_DEPLOY_COMMIT
value: "$(params.deploy-commit)"
- name: BACKEND_CORE_COMMIT
value: "$backend_commit"
- name: FRONTEND_COMMIT
value: "$frontend_commit"
- name: CODE_QUEUE_COMMIT
value: "$code_queue_commit"
readinessProbe:
httpGet:
path: /health
port: http
periodSeconds: 3
timeoutSeconds: 2
failureThreshold: 20
resources:
requests:
cpu: 20m
memory: 64Mi
limits:
memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
name: dev-e2e-target
namespace: $ns
labels:
app.kubernetes.io/name: unidesk-dev-namespace-e2e
app.kubernetes.io/component: smoke-target
app.kubernetes.io/part-of: unidesk
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: unidesk-dev-namespace-e2e
app.kubernetes.io/component: smoke-target
ports:
- name: http
port: 8080
targetPort: http
YAML
csplit -s -f /tmp/dev-e2e-target- /tmp/dev-e2e-target.yaml '/^---$/' '{*}'
kube PATCH \
-H "Content-Type: application/apply-patch+yaml" \
--data-binary @/tmp/dev-e2e-target-00 \
"$kube_api/apis/apps/v1/namespaces/$ns/deployments/dev-e2e-target?fieldManager=unidesk-ci&force=true" >/dev/null
kube PATCH \
-H "Content-Type: application/apply-patch+yaml" \
--data-binary @/tmp/dev-e2e-target-01 \
"$kube_api/api/v1/namespaces/$ns/services/dev-e2e-target?fieldManager=unidesk-ci&force=true" >/dev/null
deadline=$((SECONDS + 180))
while [ "$SECONDS" -lt "$deadline" ]; do
status="$(kube GET "$kube_api/apis/apps/v1/namespaces/$ns/deployments/dev-e2e-target")"
available="$(printf '%s' "$status" | jq -r '.status.availableReplicas // 0')"
observed="$(printf '%s' "$status" | jq -r '.status.observedGeneration // 0')"
generation="$(printf '%s' "$status" | jq -r '.metadata.generation // 0')"
if [ "$available" -ge 1 ] && [ "$observed" -ge "$generation" ]; then
echo "dev_e2e_target_rollout=available namespace=$ns"
break
fi
sleep 2
done
if [ "$SECONDS" -ge "$deadline" ]; then
echo "dev_e2e_target_rollout=timeout namespace=$ns" >&2
kube GET "$kube_api/apis/apps/v1/namespaces/$ns/deployments/dev-e2e-target" >&2
exit 1
fi
bun - "$ns" "$(params.deploy-commit)" "$backend_commit" "$frontend_commit" "$code_queue_commit" "$result_json" <<'BUN'
const [ns, deployCommit, backendCommit, frontendCommit, codeQueueCommit, resultPath] = process.argv.slice(2);
const url = `http://dev-e2e-target.${ns}.svc.cluster.local:8080/health`;
const started = performance.now();
const response = await fetch(url);
const elapsedMs = Math.round(performance.now() - started);
const body = await response.json();
const checks = [
response.ok,
body.ok === true,
body.environment === "dev",
body.namespace === ns,
body.deployCommit === deployCommit,
body.backendCoreCommit === backendCommit,
body.frontendCommit === frontendCommit,
body.codeQueueCommit === codeQueueCommit
];
const result = { ok: checks.every(Boolean), elapsedMs, url, body };
await Bun.write(resultPath, JSON.stringify(result, null, 2) + "\n");
console.log(JSON.stringify(result));
if (!result.ok) process.exit(1);
BUN
---
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
name: unidesk-dev-namespace-e2e
namespace: unidesk-ci
labels:
app.kubernetes.io/name: unidesk-ci
app.kubernetes.io/component: dev-namespace-e2e
app.kubernetes.io/part-of: unidesk
spec:
params:
- name: repo-url
type: string
default: https://github.com/pikasTech/unidesk
- name: desired-ref
type: string
default: master
- name: deploy-commit
type: string
- name: environment
type: string
default: dev
- name: run-id
type: string
- name: keep-namespace
type: string
default: "false"
- name: app-image
type: string
default: unidesk-code-queue:dev
- name: backend-core-commit
type: string
default: unknown
- name: frontend-commit
type: string
default: unknown
- name: code-queue-commit
type: string
default: unknown
- name: deploy-json-b64
type: string
default: ""
workspaces:
- name: shared-workspace
tasks:
- name: dev-namespace-e2e
taskRef:
name: unidesk-dev-namespace-e2e
params:
- name: repo-url
value: "$(params.repo-url)"
- name: desired-ref
value: "$(params.desired-ref)"
- name: deploy-commit
value: "$(params.deploy-commit)"
- name: environment
value: "$(params.environment)"
- name: run-id
value: "$(params.run-id)"
- name: keep-namespace
value: "$(params.keep-namespace)"
- name: app-image
value: "$(params.app-image)"
- name: backend-core-commit
value: "$(params.backend-core-commit)"
- name: frontend-commit
value: "$(params.frontend-commit)"
- name: code-queue-commit
value: "$(params.code-queue-commit)"
- name: deploy-json-b64
value: "$(params.deploy-json-b64)"
workspaces:
- name: source
workspace: shared-workspace
---
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
name: unidesk-ci
namespace: unidesk-ci
labels:
app.kubernetes.io/name: unidesk-ci
app.kubernetes.io/part-of: unidesk
spec:
params:
- name: repo-url
type: string
default: https://github.com/pikasTech/unidesk
- name: revision
type: string
- name: check-image
type: string
default: unidesk-code-queue:dev
- name: code-queue-image
type: string
default: unidesk-code-queue:dev
workspaces:
- name: shared-workspace
tasks:
- name: repo-check
taskRef:
name: unidesk-repo-check
params:
- name: repo-url
value: "$(params.repo-url)"
- name: revision
value: "$(params.revision)"
- name: image
value: "$(params.check-image)"
workspaces:
- name: source
workspace: shared-workspace
- name: code-queue-read-perf
runAfter:
- repo-check
taskRef:
name: unidesk-code-queue-read-perf
params:
- name: revision
value: "$(params.revision)"
- name: app-image
value: "$(params.code-queue-image)"
workspaces:
- name: source
workspace: shared-workspace