ymal: compose repeated node lane templates

This commit is contained in:
root
2026-07-08 06:34:23 +02:00
parent 0cea74367a
commit d083e88bb9
13 changed files with 1232 additions and 1585 deletions
+131 -253
View File
@@ -2,11 +2,9 @@ version: 1
kind: AgentRunConfig kind: AgentRunConfig
metadata: metadata:
name: agentrun name: agentrun
manager: manager:
baseUrl: https://agentrun.74-48-78-17.nip.io/ baseUrl: https://agentrun.74-48-78-17.nip.io/
timeoutMs: 15000 timeoutMs: 15000
publicExposure: publicExposure:
enabled: true enabled: true
proxyName: agentrun-v01-frpc proxyName: agentrun-v01-frpc
@@ -23,13 +21,11 @@ publicExposure:
serviceName: caddy serviceName: caddy
upstreamBaseUrl: http://127.0.0.1:22880 upstreamBaseUrl: http://127.0.0.1:22880
responseHeaderTimeoutSeconds: 60 responseHeaderTimeoutSeconds: 60
auth: auth:
env: HWLAB_API_KEY env: HWLAB_API_KEY
file: /root/.config/hwlab-v02/master-server-admin-api-key.env file: /root/.config/hwlab-v02/master-server-admin-api-key.env
header: Authorization header: Authorization
scheme: Bearer scheme: Bearer
client: client:
role: render-only role: render-only
transport: direct-http transport: direct-http
@@ -40,7 +36,7 @@ client:
backendProfile: codex backendProfile: codex
workspaceRef: workspaceRef:
kind: opaque kind: opaque
path: . path: "."
executionPolicy: executionPolicy:
sandbox: workspace-write sandbox: workspace-write
approval: never approval: never
@@ -48,12 +44,10 @@ client:
network: enabled network: enabled
secretScope: secretScope:
allowCredentialEcho: false allowCredentialEcho: false
controlPlane: controlPlane:
default: default:
node: G14 node: G14
lane: v01 lane: v01
nodes: nodes:
G14: G14:
route: G14 route: G14
@@ -70,7 +64,6 @@ controlPlane:
NC01: NC01:
route: NC01 route: NC01
kubeRoute: NC01:k3s kubeRoute: NC01:k3s
lanes: lanes:
v01: v01:
node: G14 node: G14
@@ -120,7 +113,7 @@ controlPlane:
value: 74.48.78.17 value: 74.48.78.17
bootRepoUrl: http://git-mirror-http.devops-infra.svc.cluster.local/pikasTech/agentrun.git bootRepoUrl: http://git-mirror-http.devops-infra.svc.cluster.local/pikasTech/agentrun.git
imageBuild: imageBuild:
context: . context: "."
containerfile: deploy/container/Containerfile containerfile: deploy/container/Containerfile
repository: agentrun-mgr-env repository: agentrun-mgr-env
network: host network: host
@@ -131,7 +124,7 @@ controlPlane:
noProxy: noProxy:
- localhost - localhost
- 127.0.0.1 - 127.0.0.1
- ::1 - "::1"
- 127.0.0.1:5000 - 127.0.0.1:5000
- localhost:5000 - localhost:5000
- .svc - .svc
@@ -145,7 +138,7 @@ controlPlane:
noProxy: noProxy:
- localhost - localhost
- 127.0.0.1 - 127.0.0.1
- ::1 - "::1"
- 127.0.0.1:5000 - 127.0.0.1:5000
- localhost:5000 - localhost:5000
- .svc - .svc
@@ -275,49 +268,7 @@ controlPlane:
key: config.toml key: config.toml
providerCredential: providerCredential:
profile: codex profile: codex
v02: v02:
node: D601
version: v0.2
source:
statusMode: k3s-git-mirror
repository: pikasTech/agentrun
branch: v0.2
sourceAuthority:
mode: gitMirrorSnapshot
resolver: k8s-git-mirror
allowHostGit: false
allowHostWorkspace: false
allowGithubDirectInPipeline: false
sourceSnapshot:
stageRefPrefix: refs/unidesk/snapshots/agentrun-yaml-lane/{branch}
missingObjectPolicy: fail-fast
refreshPolicy: sync-before-snapshot
bootstrapFromBranch: v0.1
bootstrapTimeoutSeconds: 900
bootstrapPollSeconds: 15
remote: git@github.com:pikasTech/agentrun.git
workspace: /home/ubuntu/workspace/agentrun-v02
runtime:
namespace: agentrun-v02
managerDeployment: agentrun-mgr
managerService: agentrun-mgr
managerPort: 8080
internalBaseUrl: http://agentrun-mgr.agentrun-v02.svc.cluster.local:8080
ci:
namespace: agentrun-ci
pipeline: agentrun-v02-ci-image-publish
pipelineRunPrefix: agentrun-v02-ci
serviceAccountName: agentrun-v02-tekton-runner
registryPrefix: 127.0.0.1:5000/agentrun
toolsImage: 127.0.0.1:5000/hwlab/hwlab-ci-node-tools:node22-alpine-bun-v1
buildkitImage: 127.0.0.1:5000/hwlab/buildkit:rootless
gitops:
branch: v0.2-gitops
path: deploy/gitops/node/d601/runtime-v02
argoNamespace: argocd
argoApplication: agentrun-d601-v02
repoURL: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/agentrun.git
deployment: deployment:
format: unidesk-yaml-only format: unidesk-yaml-only
gitopsRoot: deploy/gitops/node/d601 gitopsRoot: deploy/gitops/node/d601
@@ -345,7 +296,7 @@ controlPlane:
value: 74.48.78.17 value: 74.48.78.17
bootRepoUrl: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/agentrun.git bootRepoUrl: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/agentrun.git
imageBuild: imageBuild:
context: . context: "."
containerfile: deploy/container/Containerfile containerfile: deploy/container/Containerfile
repository: agentrun-mgr-env repository: agentrun-mgr-env
network: host network: host
@@ -356,7 +307,7 @@ controlPlane:
noProxy: noProxy:
- localhost - localhost
- 127.0.0.1 - 127.0.0.1
- ::1 - "::1"
- 127.0.0.1:5000 - 127.0.0.1:5000
- localhost:5000 - localhost:5000
- .svc - .svc
@@ -370,7 +321,7 @@ controlPlane:
noProxy: noProxy:
- localhost - localhost
- 127.0.0.1 - 127.0.0.1
- ::1 - "::1"
- 127.0.0.1:5000 - 127.0.0.1:5000
- localhost:5000 - localhost:5000
- .svc - .svc
@@ -564,64 +515,20 @@ controlPlane:
key: model-catalog.json key: model-catalog.json
providerCredential: providerCredential:
profile: dsflash-go profile: dsflash-go
- id: tool-github-pr-token - extends: controlPlane.templates.secrets.githubPrRawToken
sourceRef: /root/unidesk/.env/gh_token.txt - extends: controlPlane.templates.secrets.unideskSshToken
sourceKey: GH_TOKEN extends: controlPlane.templates.agentrunV02Lane
sourceFormat: raw-token variables:
targetRef: NODE: D601
namespace: agentrun-v02
name: agentrun-v01-tool-github-pr
key: GH_TOKEN
- id: tool-unidesk-ssh-token
sourceRef: /root/unidesk/.state/docker-compose.env
sourceKey: UNIDESK_SSH_CLIENT_TOKEN
targetRef:
namespace: agentrun-v02
name: agentrun-v01-tool-unidesk-ssh
key: UNIDESK_SSH_CLIENT_TOKEN
jd01-v02:
node: JD01
version: v0.2
source:
statusMode: k3s-git-mirror
repository: pikasTech/agentrun
branch: v0.2
sourceAuthority:
mode: gitMirrorSnapshot
resolver: k8s-git-mirror
allowHostGit: false
allowHostWorkspace: false
allowGithubDirectInPipeline: false
sourceSnapshot:
stageRefPrefix: refs/unidesk/snapshots/agentrun-yaml-lane/{branch}
missingObjectPolicy: fail-fast
refreshPolicy: sync-before-snapshot
bootstrapFromBranch: v0.1
bootstrapTimeoutSeconds: 900
bootstrapPollSeconds: 15
remote: git@github.com:pikasTech/agentrun.git remote: git@github.com:pikasTech/agentrun.git
workspace: /root/workspace/agentrun-v02 workspace: /home/ubuntu/workspace/agentrun-v02
runtime: pipeline: agentrun-v02-ci-image-publish
namespace: agentrun-v02 pipelineRunPrefix: agentrun-v02-ci
managerDeployment: agentrun-mgr serviceAccountName: agentrun-v02-tekton-runner
managerService: agentrun-mgr gitopsBranch: v0.2-gitops
managerPort: 8080 gitopsPath: deploy/gitops/node/d601/runtime-v02
internalBaseUrl: http://agentrun-mgr.agentrun-v02.svc.cluster.local:8080 argoApplication: agentrun-d601-v02
ci: jd01-v02:
namespace: agentrun-ci
pipeline: agentrun-jd01-v02-ci-image-publish
pipelineRunPrefix: agentrun-jd01-v02-ci
serviceAccountName: agentrun-jd01-v02-tekton-runner
registryPrefix: 127.0.0.1:5000/agentrun
toolsImage: 127.0.0.1:5000/hwlab/hwlab-ci-node-tools:node22-alpine-bun-v1
buildkitImage: 127.0.0.1:5000/hwlab/buildkit:rootless
gitops:
branch: jd01-v0.2-gitops
path: deploy/gitops/node/jd01/runtime-v02
argoNamespace: argocd
argoApplication: agentrun-jd01-v02
repoURL: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/agentrun.git
deployment: deployment:
format: unidesk-yaml-only format: unidesk-yaml-only
gitopsRoot: deploy/gitops/node/jd01 gitopsRoot: deploy/gitops/node/jd01
@@ -649,7 +556,7 @@ controlPlane:
value: 74.48.78.17 value: 74.48.78.17
bootRepoUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git bootRepoUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git
imageBuild: imageBuild:
context: . context: "."
containerfile: deploy/container/Containerfile containerfile: deploy/container/Containerfile
repository: agentrun-mgr-env repository: agentrun-mgr-env
network: host network: host
@@ -660,7 +567,7 @@ controlPlane:
noProxy: noProxy:
- localhost - localhost
- 127.0.0.1 - 127.0.0.1
- ::1 - "::1"
- 127.0.0.1:5000 - 127.0.0.1:5000
- localhost:5000 - localhost:5000
- .svc - .svc
@@ -674,7 +581,7 @@ controlPlane:
noProxy: noProxy:
- localhost - localhost
- 127.0.0.1 - 127.0.0.1
- ::1 - "::1"
- 127.0.0.1:5000 - 127.0.0.1:5000
- localhost:5000 - localhost:5000
- .svc - .svc
@@ -716,7 +623,7 @@ controlPlane:
noProxyExtra: noProxyExtra:
- localhost - localhost
- 127.0.0.1 - 127.0.0.1
- ::1 - "::1"
- .svc - .svc
- .svc.cluster.local - .svc.cluster.local
- .cluster.local - .cluster.local
@@ -864,64 +771,20 @@ controlPlane:
key: model-catalog.json key: model-catalog.json
providerCredential: providerCredential:
profile: dsflash-go profile: dsflash-go
- id: tool-github-pr-token - extends: controlPlane.templates.secrets.githubPrRawToken
sourceRef: /root/unidesk/.env/gh_token.txt - extends: controlPlane.templates.secrets.unideskSshToken
sourceKey: GH_TOKEN extends: controlPlane.templates.agentrunV02Lane
sourceFormat: raw-token variables:
targetRef: NODE: JD01
namespace: agentrun-v02 remote: git@github.com:pikasTech/agentrun.git
name: agentrun-v01-tool-github-pr workspace: /root/workspace/agentrun-v02
key: GH_TOKEN pipeline: agentrun-jd01-v02-ci-image-publish
- id: tool-unidesk-ssh-token pipelineRunPrefix: agentrun-jd01-v02-ci
sourceRef: /root/unidesk/.state/docker-compose.env serviceAccountName: agentrun-jd01-v02-tekton-runner
sourceKey: UNIDESK_SSH_CLIENT_TOKEN gitopsBranch: jd01-v0.2-gitops
targetRef: gitopsPath: deploy/gitops/node/jd01/runtime-v02
namespace: agentrun-v02 argoApplication: agentrun-jd01-v02
name: agentrun-v01-tool-unidesk-ssh
key: UNIDESK_SSH_CLIENT_TOKEN
nc01-v02: nc01-v02:
node: NC01
version: v0.2
source:
statusMode: k3s-git-mirror
repository: pikasTech/agentrun
branch: v0.2
sourceAuthority:
mode: gitMirrorSnapshot
resolver: k8s-git-mirror
allowHostGit: false
allowHostWorkspace: false
allowGithubDirectInPipeline: false
sourceSnapshot:
stageRefPrefix: refs/unidesk/snapshots/agentrun-yaml-lane/{branch}
missingObjectPolicy: fail-fast
refreshPolicy: sync-before-snapshot
bootstrapFromBranch: v0.1
bootstrapTimeoutSeconds: 900
bootstrapPollSeconds: 15
remote: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git
workspace: /root/agentrun
runtime:
namespace: agentrun-v02
managerDeployment: agentrun-mgr
managerService: agentrun-mgr
managerPort: 8080
internalBaseUrl: http://agentrun-mgr.agentrun-v02.svc.cluster.local:8080
ci:
namespace: agentrun-ci
pipeline: agentrun-nc01-v02-ci-image-publish
pipelineRunPrefix: agentrun-nc01-v02-ci
serviceAccountName: agentrun-nc01-v02-tekton-runner
registryPrefix: 127.0.0.1:5000/agentrun
toolsImage: 127.0.0.1:5000/hwlab/hwlab-ci-node-tools:node22-alpine-bun-v1
buildkitImage: 127.0.0.1:5000/hwlab/buildkit:rootless
gitops:
branch: nc01-v0.2-gitops
path: deploy/gitops/node/nc01/runtime-v02
argoNamespace: argocd
argoApplication: agentrun-nc01-v02
repoURL: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/agentrun.git
deployment: deployment:
format: unidesk-yaml-only format: unidesk-yaml-only
gitopsRoot: deploy/gitops/node/nc01 gitopsRoot: deploy/gitops/node/nc01
@@ -949,7 +812,7 @@ controlPlane:
value: 152.53.229.148 value: 152.53.229.148
bootRepoUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git bootRepoUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git
imageBuild: imageBuild:
context: . context: "."
containerfile: deploy/container/Containerfile containerfile: deploy/container/Containerfile
repository: agentrun-mgr-env repository: agentrun-mgr-env
network: host network: host
@@ -960,7 +823,7 @@ controlPlane:
noProxy: noProxy:
- localhost - localhost
- 127.0.0.1 - 127.0.0.1
- ::1 - "::1"
- 127.0.0.1:5000 - 127.0.0.1:5000
- localhost:5000 - localhost:5000
- .svc - .svc
@@ -974,7 +837,7 @@ controlPlane:
noProxy: noProxy:
- localhost - localhost
- 127.0.0.1 - 127.0.0.1
- ::1 - "::1"
- 127.0.0.1:5000 - 127.0.0.1:5000
- localhost:5000 - localhost:5000
- .svc - .svc
@@ -1016,7 +879,7 @@ controlPlane:
noProxyExtra: noProxyExtra:
- localhost - localhost
- 127.0.0.1 - 127.0.0.1
- ::1 - "::1"
- .svc - .svc
- .svc.cluster.local - .svc.cluster.local
- .cluster.local - .cluster.local
@@ -1137,64 +1000,20 @@ controlPlane:
key: config.toml key: config.toml
providerCredential: providerCredential:
profile: codex profile: codex
- id: tool-github-pr-token - extends: controlPlane.templates.secrets.githubPrRawToken
sourceRef: /root/unidesk/.env/gh_token.txt - extends: controlPlane.templates.secrets.unideskSshToken
sourceKey: GH_TOKEN extends: controlPlane.templates.agentrunV02Lane
sourceFormat: raw-token variables:
targetRef: NODE: NC01
namespace: agentrun-v02 remote: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git
name: agentrun-v01-tool-github-pr workspace: /root/agentrun
key: GH_TOKEN pipeline: agentrun-nc01-v02-ci-image-publish
- id: tool-unidesk-ssh-token pipelineRunPrefix: agentrun-nc01-v02-ci
sourceRef: /root/unidesk/.state/docker-compose.env serviceAccountName: agentrun-nc01-v02-tekton-runner
sourceKey: UNIDESK_SSH_CLIENT_TOKEN gitopsBranch: nc01-v0.2-gitops
targetRef: gitopsPath: deploy/gitops/node/nc01/runtime-v02
namespace: agentrun-v02 argoApplication: agentrun-nc01-v02
name: agentrun-v01-tool-unidesk-ssh
key: UNIDESK_SSH_CLIENT_TOKEN
d518-v02: d518-v02:
node: D518
version: v0.2
source:
statusMode: k3s-git-mirror
repository: pikasTech/agentrun
branch: v0.2
sourceAuthority:
mode: gitMirrorSnapshot
resolver: k8s-git-mirror
allowHostGit: false
allowHostWorkspace: false
allowGithubDirectInPipeline: false
sourceSnapshot:
stageRefPrefix: refs/unidesk/snapshots/agentrun-yaml-lane/{branch}
missingObjectPolicy: fail-fast
refreshPolicy: sync-before-snapshot
bootstrapFromBranch: v0.1
bootstrapTimeoutSeconds: 900
bootstrapPollSeconds: 15
remote: git@github.com:pikasTech/agentrun.git
workspace: /home/ubuntu/workspace/agentrun-v02
runtime:
namespace: agentrun-v02
managerDeployment: agentrun-mgr
managerService: agentrun-mgr
managerPort: 8080
internalBaseUrl: http://agentrun-mgr.agentrun-v02.svc.cluster.local:8080
ci:
namespace: agentrun-ci
pipeline: agentrun-d518-v02-ci-image-publish
pipelineRunPrefix: agentrun-d518-v02-ci
serviceAccountName: agentrun-d518-v02-tekton-runner
registryPrefix: 127.0.0.1:5000/agentrun
toolsImage: 127.0.0.1:5000/hwlab/hwlab-ci-node-tools:node22-alpine-bun-v1
buildkitImage: 127.0.0.1:5000/hwlab/buildkit:rootless
gitops:
branch: d518-v0.2-gitops
path: deploy/gitops/node/d518/runtime-v02
argoNamespace: argocd
argoApplication: agentrun-d518-v02
repoURL: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/agentrun.git
deployment: deployment:
format: unidesk-yaml-only format: unidesk-yaml-only
gitopsRoot: deploy/gitops/node/d518 gitopsRoot: deploy/gitops/node/d518
@@ -1227,7 +1046,7 @@ controlPlane:
value: 74.48.78.17 value: 74.48.78.17
bootRepoUrl: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/agentrun.git bootRepoUrl: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/agentrun.git
imageBuild: imageBuild:
context: . context: "."
containerfile: deploy/container/Containerfile containerfile: deploy/container/Containerfile
repository: agentrun-mgr-env repository: agentrun-mgr-env
network: host network: host
@@ -1238,7 +1057,7 @@ controlPlane:
noProxy: noProxy:
- localhost - localhost
- 127.0.0.1 - 127.0.0.1
- ::1 - "::1"
- 127.0.0.1:5000 - 127.0.0.1:5000
- localhost:5000 - localhost:5000
- .svc - .svc
@@ -1252,7 +1071,7 @@ controlPlane:
noProxy: noProxy:
- localhost - localhost
- 127.0.0.1 - 127.0.0.1
- ::1 - "::1"
- 127.0.0.1:5000 - 127.0.0.1:5000
- localhost:5000 - localhost:5000
- .svc - .svc
@@ -1465,18 +1284,77 @@ controlPlane:
key: config.toml key: config.toml
providerCredential: providerCredential:
profile: fake-echo profile: fake-echo
- id: tool-github-pr-token - extends: controlPlane.templates.secrets.githubPrRawToken
sourceRef: /root/unidesk/.env/gh_token.txt - extends: controlPlane.templates.secrets.unideskSshToken
sourceKey: GH_TOKEN extends: controlPlane.templates.agentrunV02Lane
sourceFormat: raw-token variables:
targetRef: NODE: D518
namespace: agentrun-v02 remote: git@github.com:pikasTech/agentrun.git
name: agentrun-v01-tool-github-pr workspace: /home/ubuntu/workspace/agentrun-v02
key: GH_TOKEN pipeline: agentrun-d518-v02-ci-image-publish
- id: tool-unidesk-ssh-token pipelineRunPrefix: agentrun-d518-v02-ci
sourceRef: /root/unidesk/.state/docker-compose.env serviceAccountName: agentrun-d518-v02-tekton-runner
sourceKey: UNIDESK_SSH_CLIENT_TOKEN gitopsBranch: d518-v0.2-gitops
targetRef: gitopsPath: deploy/gitops/node/d518/runtime-v02
namespace: agentrun-v02 argoApplication: agentrun-d518-v02
name: agentrun-v01-tool-unidesk-ssh templates:
key: UNIDESK_SSH_CLIENT_TOKEN agentrunV02Lane:
version: v0.2
node: "${NODE}"
source:
statusMode: k3s-git-mirror
repository: pikasTech/agentrun
branch: v0.2
sourceAuthority:
mode: gitMirrorSnapshot
resolver: k8s-git-mirror
allowHostGit: false
allowHostWorkspace: false
allowGithubDirectInPipeline: false
sourceSnapshot:
stageRefPrefix: "refs/unidesk/snapshots/agentrun-yaml-lane/{branch}"
missingObjectPolicy: fail-fast
refreshPolicy: sync-before-snapshot
bootstrapFromBranch: v0.1
bootstrapTimeoutSeconds: 900
bootstrapPollSeconds: 15
remote: "${remote}"
workspace: "${workspace}"
runtime:
namespace: agentrun-v02
managerDeployment: agentrun-mgr
managerService: agentrun-mgr
managerPort: 8080
internalBaseUrl: http://agentrun-mgr.agentrun-v02.svc.cluster.local:8080
ci:
namespace: agentrun-ci
pipeline: "${pipeline}"
pipelineRunPrefix: "${pipelineRunPrefix}"
serviceAccountName: "${serviceAccountName}"
registryPrefix: 127.0.0.1:5000/agentrun
toolsImage: 127.0.0.1:5000/hwlab/hwlab-ci-node-tools:node22-alpine-bun-v1
buildkitImage: 127.0.0.1:5000/hwlab/buildkit:rootless
gitops:
branch: "${gitopsBranch}"
path: "${gitopsPath}"
argoNamespace: argocd
argoApplication: "${argoApplication}"
repoURL: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/agentrun.git
secrets:
githubPrRawToken:
id: tool-github-pr-token
sourceRef: /root/unidesk/.env/gh_token.txt
sourceKey: GH_TOKEN
sourceFormat: raw-token
targetRef:
namespace: agentrun-v02
name: agentrun-v01-tool-github-pr
key: GH_TOKEN
unideskSshToken:
id: tool-unidesk-ssh-token
sourceRef: /root/unidesk/.state/docker-compose.env
sourceKey: UNIDESK_SSH_CLIENT_TOKEN
targetRef:
namespace: agentrun-v02
name: agentrun-v01-tool-unidesk-ssh
key: UNIDESK_SSH_CLIENT_TOKEN
File diff suppressed because it is too large Load Diff
+293 -261
View File
@@ -7,22 +7,20 @@ metadata:
composition: composition:
mode: yaml-anchors-and-merge mode: yaml-anchors-and-merge
intent: node overlays inherit common web-probe sentinel baselines and render node/lane identity from variables. intent: node overlays inherit common web-probe sentinel baselines and render node/lane identity from variables.
baselines: baselines:
sentinel: &sentinel-base sentinel:
enabled: true enabled: true
mode: web-probe-observe-wrapper mode: web-probe-observe-wrapper
runtime: runtime:
common: &runtime-common common:
namespace: hwlab-${lane} namespace: "hwlab-${lane}"
listenHost: 0.0.0.0 listenHost: 0.0.0.0
servicePort: 8080 servicePort: 8080
pvcStorage: 10Gi pvcStorage: 10Gi
replicas: 1 replicas: 1
healthPath: /api/health healthPath: /api/health
metricsPath: /metrics metricsPath: /metrics
scheduler: &scheduler-10m scheduler:
intervalMs: 600000 intervalMs: 600000
heartbeatStaleSeconds: 900 heartbeatStaleSeconds: 900
maxConcurrentRuns: 1 maxConcurrentRuns: 1
@@ -30,11 +28,12 @@ baselines:
observability: observability:
otel: otel:
enabled: true enabled: true
serviceName: hwlab-web-probe-sentinel-${nodeLower} serviceName: "hwlab-web-probe-sentinel-${nodeLower}"
tracesEndpoint: http://otel-collector.platform-infra.svc.cluster.local:4318/v1/traces tracesEndpoint: http://otel-collector.platform-infra.svc.cluster.local:4318/v1/traces
sampler: parentbased_traceidratio sampler: parentbased_traceidratio
samplerArg: "1" samplerArg: "1"
kubernetesApi: kubernetesApi:
&kubernetesApi
endpoint: endpoint:
host: 172.16.0.5 host: 172.16.0.5
port: 6443 port: 6443
@@ -45,20 +44,19 @@ baselines:
port: 443 port: 443
- cidr: 172.16.0.5/32 - cidr: 172.16.0.5/32
port: 6443 port: 6443
scheduler15m: &scheduler-15m scheduler15m:
intervalMs: 900000 intervalMs: 900000
heartbeatStaleSeconds: 900 heartbeatStaleSeconds: 900
maxConcurrentRuns: 1 maxConcurrentRuns: 1
sqlite: &sqlite-common sqlite:
busyTimeoutMs: 2000 busyTimeoutMs: 2000
cicd: cicd:
source: &cicd-source source:
repository: pikasTech/unidesk repository: pikasTech/unidesk
branch: master branch: master
gitSshUrl: ssh://git@ssh.github.com:443/pikasTech/unidesk.git gitSshUrl: ssh://git@ssh.github.com:443/pikasTech/unidesk.git
gitMirrorReadUrl: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/unidesk.git gitMirrorReadUrl: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/unidesk.git
buildContext: . buildContext: "."
entrypoint: scripts/web-probe-sentinel-service.ts entrypoint: scripts/web-probe-sentinel-service.ts
checkoutPaths: checkoutPaths:
- scripts - scripts
@@ -68,23 +66,23 @@ baselines:
- package.json - package.json
- bun.lock - bun.lock
- bun.lockb - bun.lockb
sourceAuthority: &cicd-source-authority sourceAuthority:
mode: gitMirrorSnapshot mode: gitMirrorSnapshot
resolver: k8s-git-mirror resolver: k8s-git-mirror
allowHostGit: false allowHostGit: false
allowGithubDirectInPipeline: false allowGithubDirectInPipeline: false
sourceSnapshot: &cicd-source-snapshot sourceSnapshot:
stageRefPrefix: refs/unidesk/snapshots/web-probe-sentinel/{branch} stageRefPrefix: "refs/unidesk/snapshots/web-probe-sentinel/{branch}"
missingObjectPolicy: fail-fast missingObjectPolicy: fail-fast
refreshPolicy: sync-before-snapshot refreshPolicy: sync-before-snapshot
cacheRef: source.gitMirrorReadUrl cacheRef: source.gitMirrorReadUrl
builder: &cicd-builder builder:
namespace: devops-infra namespace: devops-infra
sourceMode: sparse-git-checkout sourceMode: sparse-git-checkout
gitSshSecretName: git-mirror-github-ssh gitSshSecretName: git-mirror-github-ssh
activeDeadlineSeconds: 900 activeDeadlineSeconds: 900
ttlSecondsAfterFinished: 3600 ttlSecondsAfterFinished: 3600
monitorWeb: &monitor-web monitorWeb:
frontendStack: vue3-vendored-browser-build frontendStack: vue3-vendored-browser-build
runtimeMode: runner-served-bridge runtimeMode: runner-served-bridge
assetRoot: scripts/assets/web-probe-sentinel-monitor-web assetRoot: scripts/assets/web-probe-sentinel-monitor-web
@@ -99,7 +97,7 @@ baselines:
verifyPhase: pre-image-build verifyPhase: pre-image-build
buildkitState: buildkitState:
mode: hostPath mode: hostPath
path: /var/lib/unidesk/web-probe-sentinel/buildkit-${nodeLower} path: "/var/lib/unidesk/web-probe-sentinel/buildkit-${nodeLower}"
type: DirectoryOrCreate type: DirectoryOrCreate
gitMirror: gitMirror:
source: source.gitMirrorReadUrl source: source.gitMirrorReadUrl
@@ -107,12 +105,12 @@ baselines:
postFlush: required postFlush: required
ciBudget: ciBudget:
maxSeconds: 120 maxSeconds: 120
maintenance: &maintenance maintenance:
startCommand: sentinel maintenance start startCommand: sentinel maintenance start
stopCommand: sentinel maintenance stop stopCommand: sentinel maintenance stop
confirmWait: &confirm-wait confirmWait:
maxSeconds: 120 maxSeconds: 120
publishCurrent: &publish-current publishCurrent:
endToEndBudget: endToEndBudget:
maxSeconds: 120 maxSeconds: 120
stageBudgets: stageBudgets:
@@ -131,14 +129,13 @@ baselines:
waitTimeoutMs: 60000 waitTimeoutMs: 60000
commandTimeoutSeconds: 90 commandTimeoutSeconds: 90
fullPage: false fullPage: false
publicExposure: publicExposure:
common: &public-exposure-common common:
enabled: true enabled: true
mode: pk01-caddy-frp-path mode: pk01-caddy-frp-path
hostname: monitor.pikapython.com hostname: monitor.pikapython.com
expectedA: 82.156.23.220 expectedA: 82.156.23.220
frpc: &frpc-common frpc:
image: 127.0.0.1:5000/hwlab/frpc:v0.68.1 image: 127.0.0.1:5000/hwlab/frpc:v0.68.1
serverAddr: 82.156.23.220 serverAddr: 82.156.23.220
serverPort: 22000 serverPort: 22000
@@ -146,144 +143,57 @@ baselines:
tokenSourceKey: FRP_TOKEN tokenSourceKey: FRP_TOKEN
secretKey: frpc.toml secretKey: frpc.toml
tokenKey: token tokenKey: token
caddy: &caddy-common caddy:
route: PK01 route: PK01
configPath: /etc/caddy/Caddyfile configPath: /etc/caddy/Caddyfile
serviceName: caddy serviceName: caddy
email: ops@pikapython.com email: ops@pikapython.com
tls: auto tls: auto
responseHeaderTimeoutSeconds: 600 responseHeaderTimeoutSeconds: 600
secrets: secrets:
jd01BootstrapSource: &jd01-bootstrap-source jd01BootstrapSource:
purpose: bootstrap-admin purpose: bootstrap-admin
sourceRef: .env/HWLAB_admin.txt sourceRef: .env/HWLAB_admin.txt
sourceKey: HWLAB_ADMIN_PASSWORD sourceKey: HWLAB_ADMIN_PASSWORD
sourceLine: 2 sourceLine: 2
dsflashPromptSource: &dsflash-prompt-source dsflashPromptSource:
purpose: prompt-set purpose: prompt-set
sourceRef: hwlab/web-probe-sentinel-dsflash-go.env sourceRef: hwlab/web-probe-sentinel-dsflash-go.env
sourceKey: DSFLASH_GO_TOOL_CALL_10X_PROMPTS_JSON sourceKey: DSFLASH_GO_TOOL_CALL_10X_PROMPTS_JSON
frpTokenSource: &frp-token-source frpTokenSource:
purpose: frp-token purpose: frp-token
sourceRef: platform-infra/pk01-frp.env sourceRef: platform-infra/pk01-frp.env
sourceKey: FRP_TOKEN sourceKey: FRP_TOKEN
nodes: nodes:
JD01: JD01:
target: &jd01-target target:
node: ${NODE} extends: templates.webProbeSentinelTarget
lane: ${LANE} cicdCommon:
publicOriginRef: config/hwlab-node-lanes.yaml#lanes.${LANE}.targets.${NODE}.public.webUrl extends: templates.webProbeSentinelCicdCommon
cicdCommon: &jd01-cicd-common
controlPlaneConfigRef: config/hwlab-node-control-plane.yaml#targets[1]
source:
<<: *cicd-source
gitMirrorReadUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-unidesk.git
sourceAuthority:
<<: *cicd-source-authority
mode: giteaSnapshot
resolver: gitea-mirror
sourceSnapshot:
<<: *cicd-source-snapshot
stageRefPrefix: refs/unidesk/snapshots/gitea-actions/unidesk-master
refreshPolicy: gitea-controlled-snapshot
argo: &jd01-argo
namespace: argocd
projectName: hwlab-jd01
repoURL: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/HWLAB.git
targetRevision: v0.3-gitops
maintenance:
<<: *maintenance
monitorWeb:
<<: *monitor-web
gitMirror:
source: source.gitMirrorReadUrl
preSync: not-required
postFlush: not-required
confirmWait:
<<: *confirm-wait
publishCurrent:
<<: *publish-current
sentinels: sentinels:
jd01-web-probe-sentinel: jd01-web-probe-sentinel:
sentinel: sentinel:
<<: *sentinel-base extends: templates.webProbeSentinelSentinel
id: jd01-web-probe-sentinel
configRefs:
runtime: config/hwlab-web-probe-sentinel/profiles.yaml#nodes.${NODE}.sentinels.${nodeLower}-web-probe-sentinel.runtime
scenarios: config/hwlab-web-probe-sentinel/scenarios.multi-sentinel.yaml#sentinel.scenarios
promptSet: config/hwlab-web-probe-sentinel/prompt-set.dsflash-go.yaml#sentinel.promptSet
reportViews: config/hwlab-web-probe-sentinel/report-views.multi-sentinel.yaml#sentinel.reportViews
publicExposure: config/hwlab-web-probe-sentinel/profiles.yaml#nodes.${NODE}.sentinels.${nodeLower}-web-probe-sentinel.publicExposure
cicd: config/hwlab-web-probe-sentinel/profiles.yaml#nodes.${NODE}.sentinels.${nodeLower}-web-probe-sentinel.cicd
secrets: config/hwlab-web-probe-sentinel/profiles.yaml#nodes.${NODE}.sentinels.${nodeLower}-web-probe-sentinel.secrets
runtime: runtime:
<<: *runtime-common extends: templates.webProbeSentinelRuntime
target: kubernetesApi:
<<: *jd01-target *kubernetesApi
observeWrapperRef: config/hwlab-node-lanes.yaml#lanes.${LANE}.targets.${NODE}.observability.webProbe.sentinels[0]
serviceAccountName: hwlab-web-probe-sentinel-${nodeLower}
deploymentName: hwlab-web-probe-sentinel-${nodeLower}
serviceName: hwlab-web-probe-sentinel-${nodeLower}
pvcName: hwlab-web-probe-sentinel-${nodeLower}-state
stateRoot: /var/lib/web-probe-sentinel-${nodeLower}
imageRef: 127.0.0.1:5000/hwlab/web-probe-sentinel-${nodeLower}:source-commit
scheduler:
<<: *scheduler-10m
sqlite:
<<: *sqlite-common
path: /var/lib/web-probe-sentinel-${nodeLower}/index.sqlite
publicExposure: publicExposure:
<<: *public-exposure-common extends: templates.webProbeSentinelPublicExposure
publicBaseUrl: https://monitor.pikapython.com/sentinels/${nodeLower}-web-probe-sentinel
routePrefix: /sentinels/${nodeLower}-web-probe-sentinel
frpc: frpc:
<<: *frpc-common
deploymentName: hwlab-web-probe-sentinel-${nodeLower}-frpc
secretName: hwlab-web-probe-sentinel-${nodeLower}-frpc
httpProxy: httpProxy:
name: hwlab-${nodeLower}-${lane}-web-probe-sentinel
remotePort: 22098 remotePort: 22098
localIP: hwlab-web-probe-sentinel-${nodeLower}.hwlab-${lane}.svc.cluster.local
localPort: 8080
caddy:
<<: *caddy-common
managedBlockOwner: hwlab-web-probe-sentinel-${nodeLower}-${lane}
cicd: cicd:
<<: *jd01-cicd-common extends: templates.webProbeSentinelCicd
builder:
<<: *cicd-builder
jobPrefix: web-probe-sentinel-${nodeLower}-publish
gitopsPath: deploy/gitops/node/${nodeLower}/web-probe-sentinel
argo:
<<: *jd01-argo
applicationName: hwlab-web-probe-sentinel-${nodeLower}
image:
repository: 127.0.0.1:5000/hwlab/web-probe-sentinel-${nodeLower}
tagSource: source-commit
baseImageRef: config/hwlab-node-control-plane.yaml#targets[1].tekton.toolsImage.output
envRecipeRef: config/hwlab-web-probe-sentinel/profiles.yaml#nodes.${NODE}.sentinels.${nodeLower}-web-probe-sentinel.runtime
targetValidation:
scenarioId: workbench-dsflash-go-hwpod-two-turn-freeze-repro
maxSeconds: 600
serviceUnavailablePolicy: structured-failure
cadenceScheduler:
enabled: true
reason: k8s-native-periodic-quick-verify
concurrencyPolicy: Forbid
startingDeadlineSeconds: 600
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 5
activeDeadlineSlackSeconds: 60
ttlSecondsAfterFinished: 86400
backoffLimit: 0
secrets: secrets:
sources: sources:
- <<: *jd01-bootstrap-source - sourceLine: 2
- <<: *dsflash-prompt-source sourceKey: HWLAB_ADMIN_PASSWORD
sourceRef: .env/HWLAB_admin.txt
purpose: bootstrap-admin
- sourceKey: DSFLASH_GO_TOOL_CALL_10X_PROMPTS_JSON
sourceRef: hwlab/web-probe-sentinel-dsflash-go.env
purpose: prompt-set
- purpose: account-a - purpose: account-a
sourceRef: .env/HWLAB_admin.txt sourceRef: .env/HWLAB_admin.txt
sourceKey: HWLAB_BOOTSTRAP_ADMIN_PASSWORD sourceKey: HWLAB_BOOTSTRAP_ADMIN_PASSWORD
@@ -292,102 +202,52 @@ nodes:
usernameSourceRef: .env/HWLAB_admin.txt usernameSourceRef: .env/HWLAB_admin.txt
usernameSourceLine: 1 usernameSourceLine: 1
- purpose: account-b - purpose: account-b
sourceRef: hwlab/${nodeLower}-${lane}-preset-users.env sourceRef: "hwlab/${nodeLower}-${lane}-preset-users.env"
sourceKey: ${NODE}_SECOND_USER_PASSWORD sourceKey: "${NODE}_SECOND_USER_PASSWORD"
format: web-account-json format: web-account-json
username: ${nodeLower}-sentinel@hwlab.local username: "${nodeLower}-sentinel@hwlab.local"
- <<: *frp-token-source - sourceKey: FRP_TOKEN
sourceRef: platform-infra/pk01-frp.env
purpose: frp-token
runtimeSecrets: runtimeSecrets:
- name: hwlab-web-probe-sentinel-${nodeLower}-bootstrap - name: "hwlab-web-probe-sentinel-${nodeLower}-bootstrap"
namespace: hwlab-${lane} namespace: "hwlab-${lane}"
data: data:
- sourcePurpose: bootstrap-admin - sourcePurpose: bootstrap-admin
targetKey: bootstrap-admin-password targetKey: bootstrap-admin-password
- name: hwlab-web-probe-sentinel-${nodeLower}-prompt-set - name: "hwlab-web-probe-sentinel-${nodeLower}-prompt-set"
namespace: hwlab-${lane} namespace: "hwlab-${lane}"
data: data:
- sourcePurpose: prompt-set - sourcePurpose: prompt-set
targetKey: prompts.json targetKey: prompts.json
- name: hwlab-web-probe-sentinel-${nodeLower}-accounts - name: "hwlab-web-probe-sentinel-${nodeLower}-accounts"
namespace: hwlab-${lane} namespace: "hwlab-${lane}"
data: data:
- sourcePurpose: account-a - sourcePurpose: account-a
targetKey: account-a.json targetKey: account-a.json
- sourcePurpose: account-b - sourcePurpose: account-b
targetKey: account-b.json targetKey: account-b.json
- name: hwlab-web-probe-sentinel-${nodeLower}-frpc - name: "hwlab-web-probe-sentinel-${nodeLower}-frpc"
namespace: hwlab-${lane} namespace: "hwlab-${lane}"
data: data:
- sourcePurpose: frp-token - sourcePurpose: frp-token
targetKey: token targetKey: token
variables:
LANE: v03
controlPlaneIndex: "1"
argoProjectName: hwlab-jd01
NODE: JD01
NC01: NC01:
target: &nc01-target target:
node: ${NODE} extends: templates.webProbeSentinelTarget
lane: ${LANE} cicdCommon:
publicOriginRef: config/hwlab-node-lanes.yaml#lanes.${LANE}.targets.${NODE}.public.webUrl extends: templates.webProbeSentinelCicdCommon
cicdCommon: &nc01-cicd-common
controlPlaneConfigRef: config/hwlab-node-control-plane.yaml#targets[2]
source:
<<: *cicd-source
gitSshUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-unidesk.git
gitMirrorReadUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-unidesk.git
sourceAuthority:
<<: *cicd-source-authority
mode: giteaSnapshot
resolver: gitea-mirror
sourceSnapshot:
<<: *cicd-source-snapshot
stageRefPrefix: refs/unidesk/snapshots/gitea-actions/unidesk-master
refreshPolicy: gitea-controlled-snapshot
argo: &nc01-argo
namespace: argocd
projectName: hwlab-v03
repoURL: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/HWLAB.git
targetRevision: v0.3-gitops
maintenance:
<<: *maintenance
monitorWeb:
<<: *monitor-web
gitMirror:
source: source.gitMirrorReadUrl
preSync: not-required
postFlush: not-required
confirmWait:
<<: *confirm-wait
publishCurrent:
<<: *publish-current
sentinels: sentinels:
nc01-web-probe-sentinel: nc01-web-probe-sentinel:
sentinel: sentinel:
<<: *sentinel-base extends: templates.webProbeSentinelSentinel
id: nc01-web-probe-sentinel
configRefs:
runtime: config/hwlab-web-probe-sentinel/profiles.yaml#nodes.${NODE}.sentinels.${nodeLower}-web-probe-sentinel.runtime
scenarios: config/hwlab-web-probe-sentinel/scenarios.multi-sentinel.yaml#sentinel.scenarios
promptSet: config/hwlab-web-probe-sentinel/prompt-set.dsflash-go.yaml#sentinel.promptSet
reportViews: config/hwlab-web-probe-sentinel/report-views.multi-sentinel.yaml#sentinel.reportViews
publicExposure: config/hwlab-web-probe-sentinel/profiles.yaml#nodes.${NODE}.sentinels.${nodeLower}-web-probe-sentinel.publicExposure
cicd: config/hwlab-web-probe-sentinel/profiles.yaml#nodes.${NODE}.sentinels.${nodeLower}-web-probe-sentinel.cicd
secrets: config/hwlab-web-probe-sentinel/profiles.yaml#nodes.${NODE}.sentinels.${nodeLower}-web-probe-sentinel.secrets
runtime: runtime:
<<: *runtime-common extends: templates.webProbeSentinelRuntime
target:
<<: *nc01-target
observeWrapperRef: config/hwlab-node-lanes.yaml#lanes.${LANE}.targets.${NODE}.observability.webProbe.sentinels[0]
serviceAccountName: hwlab-web-probe-sentinel-${nodeLower}
deploymentName: hwlab-web-probe-sentinel-${nodeLower}
serviceName: hwlab-web-probe-sentinel-${nodeLower}
pvcName: hwlab-web-probe-sentinel-${nodeLower}-state
stateRoot: /var/lib/web-probe-sentinel-${nodeLower}
imageRef: 127.0.0.1:5000/hwlab/web-probe-sentinel-${nodeLower}:source-commit
scheduler:
<<: *scheduler-10m
sqlite:
<<: *sqlite-common
path: /var/lib/web-probe-sentinel-${nodeLower}/index.sqlite
kubernetesApi: kubernetesApi:
endpoint: endpoint:
host: 10.43.0.1 host: 10.43.0.1
@@ -398,86 +258,258 @@ nodes:
- cidr: 10.43.0.1/32 - cidr: 10.43.0.1/32
port: 443 port: 443
publicExposure: publicExposure:
<<: *public-exposure-common extends: templates.webProbeSentinelPublicExposure
publicBaseUrl: https://monitor.pikapython.com/sentinels/${nodeLower}-web-probe-sentinel
routePrefix: /sentinels/${nodeLower}-web-probe-sentinel
frpc: frpc:
<<: *frpc-common
deploymentName: hwlab-web-probe-sentinel-${nodeLower}-frpc
secretName: hwlab-web-probe-sentinel-${nodeLower}-frpc
httpProxy: httpProxy:
name: hwlab-${nodeLower}-${lane}-web-probe-sentinel
remotePort: 22084 remotePort: 22084
localIP: hwlab-web-probe-sentinel-${nodeLower}.hwlab-${lane}.svc.cluster.local
localPort: 8080
caddy:
<<: *caddy-common
managedBlockOwner: hwlab-web-probe-sentinel-${nodeLower}-${lane}
cicd: cicd:
<<: *nc01-cicd-common extends: templates.webProbeSentinelCicd
builder:
<<: *cicd-builder
jobPrefix: web-probe-sentinel-${nodeLower}-publish
gitopsPath: deploy/gitops/node/${nodeLower}/web-probe-sentinel
argo:
<<: *nc01-argo
applicationName: hwlab-web-probe-sentinel-${nodeLower}
image:
repository: 127.0.0.1:5000/hwlab/web-probe-sentinel-${nodeLower}
tagSource: source-commit
baseImageRef: config/hwlab-node-control-plane.yaml#targets[2].tekton.toolsImage.output
envRecipeRef: config/hwlab-web-probe-sentinel/profiles.yaml#nodes.${NODE}.sentinels.${nodeLower}-web-probe-sentinel.runtime
targetValidation:
scenarioId: workbench-dsflash-go-hwpod-two-turn-freeze-repro
maxSeconds: 600
serviceUnavailablePolicy: structured-failure
cadenceScheduler:
enabled: true
reason: k8s-native-periodic-quick-verify
concurrencyPolicy: Forbid
startingDeadlineSeconds: 600
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 5
activeDeadlineSlackSeconds: 60
ttlSecondsAfterFinished: 86400
backoffLimit: 0
secrets: secrets:
sources: sources:
- purpose: bootstrap-admin - purpose: bootstrap-admin
sourceRef: hwlab/${nodeLower}-${lane}-bootstrap-admin.env sourceRef: "hwlab/${nodeLower}-${lane}-bootstrap-admin.env"
sourceKey: HWLAB_BOOTSTRAP_ADMIN_PASSWORD sourceKey: HWLAB_BOOTSTRAP_ADMIN_PASSWORD
- <<: *dsflash-prompt-source - sourceKey: DSFLASH_GO_TOOL_CALL_10X_PROMPTS_JSON
sourceRef: hwlab/web-probe-sentinel-dsflash-go.env
purpose: prompt-set
- purpose: account-a - purpose: account-a
sourceRef: hwlab/${nodeLower}-${lane}-bootstrap-admin.env sourceRef: "hwlab/${nodeLower}-${lane}-bootstrap-admin.env"
sourceKey: HWLAB_BOOTSTRAP_ADMIN_PASSWORD sourceKey: HWLAB_BOOTSTRAP_ADMIN_PASSWORD
format: web-account-json format: web-account-json
username: admin username: admin
- purpose: account-b - purpose: account-b
sourceRef: hwlab/${nodeLower}-${lane}-preset-users.env sourceRef: "hwlab/${nodeLower}-${lane}-preset-users.env"
sourceKey: ${NODE}_SECOND_USER_PASSWORD sourceKey: "${NODE}_SECOND_USER_PASSWORD"
format: web-account-json format: web-account-json
username: ${nodeLower}-sentinel@hwlab.local username: "${nodeLower}-sentinel@hwlab.local"
- <<: *frp-token-source - sourceKey: FRP_TOKEN
sourceRef: platform-infra/pk01-frp.env
purpose: frp-token
runtimeSecrets: runtimeSecrets:
- name: hwlab-web-probe-sentinel-${nodeLower}-bootstrap - name: "hwlab-web-probe-sentinel-${nodeLower}-bootstrap"
namespace: hwlab-${lane} namespace: "hwlab-${lane}"
data: data:
- sourcePurpose: bootstrap-admin - sourcePurpose: bootstrap-admin
targetKey: bootstrap-admin-password targetKey: bootstrap-admin-password
- name: hwlab-web-probe-sentinel-${nodeLower}-prompt-set - name: "hwlab-web-probe-sentinel-${nodeLower}-prompt-set"
namespace: hwlab-${lane} namespace: "hwlab-${lane}"
data: data:
- sourcePurpose: prompt-set - sourcePurpose: prompt-set
targetKey: prompts.json targetKey: prompts.json
- name: hwlab-web-probe-sentinel-${nodeLower}-accounts - name: "hwlab-web-probe-sentinel-${nodeLower}-accounts"
namespace: hwlab-${lane} namespace: "hwlab-${lane}"
data: data:
- sourcePurpose: account-a - sourcePurpose: account-a
targetKey: account-a.json targetKey: account-a.json
- sourcePurpose: account-b - sourcePurpose: account-b
targetKey: account-b.json targetKey: account-b.json
- name: hwlab-web-probe-sentinel-${nodeLower}-frpc - name: "hwlab-web-probe-sentinel-${nodeLower}-frpc"
namespace: hwlab-${lane} namespace: "hwlab-${lane}"
data: data:
- sourcePurpose: frp-token - sourcePurpose: frp-token
targetKey: token targetKey: token
variables:
LANE: v03
controlPlaneIndex: "2"
argoProjectName: hwlab-v03
NODE: NC01
templates:
webProbeSentinelTarget:
node: "${NODE}"
lane: "${LANE}"
publicOriginRef: "config/hwlab-node-lanes.yaml#lanes.${LANE}.targets.${NODE}.public.webUrl"
webProbeSentinelCicdCommon:
controlPlaneConfigRef: "config/hwlab-node-control-plane.yaml#targets[${controlPlaneIndex}]"
source:
checkoutPaths:
- scripts
- config
- config.json
- src
- package.json
- bun.lock
- bun.lockb
entrypoint: scripts/web-probe-sentinel-service.ts
buildContext: "."
gitMirrorReadUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-unidesk.git
gitSshUrl: ssh://git@ssh.github.com:443/pikasTech/unidesk.git
branch: master
repository: pikasTech/unidesk
sourceAuthority:
allowGithubDirectInPipeline: false
allowHostGit: false
resolver: gitea-mirror
mode: giteaSnapshot
sourceSnapshot:
cacheRef: source.gitMirrorReadUrl
refreshPolicy: gitea-controlled-snapshot
missingObjectPolicy: fail-fast
stageRefPrefix: refs/unidesk/snapshots/gitea-actions/unidesk-master
argo:
namespace: argocd
projectName: "${argoProjectName}"
repoURL: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/HWLAB.git
targetRevision: v0.3-gitops
maintenance:
stopCommand: sentinel maintenance stop
startCommand: sentinel maintenance start
monitorWeb:
ciBudget:
maxSeconds: 120
gitMirror:
source: source.gitMirrorReadUrl
preSync: not-required
postFlush: not-required
imageBuild:
packageMode: copy-only-containerfile
networkMode: host
proxySource: node.networkProfile.imageBuildProxy
contextIgnore: generated
verifyPhase: pre-image-build
buildkitState:
mode: hostPath
path: "/var/lib/unidesk/web-probe-sentinel/buildkit-${nodeLower}"
type: DirectoryOrCreate
envReuse:
mode: k8s-buildkit-and-ci-node-deps
nodeDepsPath: /opt/hwlab-ci-node-deps/node_modules
assetRoot: scripts/assets/web-probe-sentinel-monitor-web
runtimeMode: runner-served-bridge
frontendStack: vue3-vendored-browser-build
confirmWait:
maxSeconds: 120
publishCurrent:
dashboard:
enabled: true
required: true
viewport: 1440x900
timeoutMs: 30000
waitTimeoutMs: 60000
commandTimeoutSeconds: 90
fullPage: false
stageBudgets:
sourceSyncSeconds: 20
sourceFetchSeconds: 20
monitorWebVerifySeconds: 15
imageBuildSeconds: 45
gitopsSeconds: 15
argoRuntimeSeconds: 30
dashboardVerifySeconds: 30
endToEndBudget:
maxSeconds: 120
webProbeSentinelSentinel:
mode: web-probe-observe-wrapper
enabled: true
id: "${nodeLower}-web-probe-sentinel"
configRefs:
runtime: "config/hwlab-web-probe-sentinel/profiles.yaml#nodes.${NODE}.sentinels.${nodeLower}-web-probe-sentinel.runtime"
scenarios: "config/hwlab-web-probe-sentinel/scenarios.multi-sentinel.yaml#sentinel.scenarios"
promptSet: "config/hwlab-web-probe-sentinel/prompt-set.dsflash-go.yaml#sentinel.promptSet"
reportViews: "config/hwlab-web-probe-sentinel/report-views.multi-sentinel.yaml#sentinel.reportViews"
publicExposure: "config/hwlab-web-probe-sentinel/profiles.yaml#nodes.${NODE}.sentinels.${nodeLower}-web-probe-sentinel.publicExposure"
cicd: "config/hwlab-web-probe-sentinel/profiles.yaml#nodes.${NODE}.sentinels.${nodeLower}-web-probe-sentinel.cicd"
secrets: "config/hwlab-web-probe-sentinel/profiles.yaml#nodes.${NODE}.sentinels.${nodeLower}-web-probe-sentinel.secrets"
webProbeSentinelRuntime:
kubernetesApi:
endpoint:
host: 172.16.0.5
port: 6443
egress:
enabled: true
rules:
- cidr: 10.43.0.1/32
port: 443
- cidr: 172.16.0.5/32
port: 6443
observability:
otel:
enabled: true
serviceName: "hwlab-web-probe-sentinel-${nodeLower}"
tracesEndpoint: http://otel-collector.platform-infra.svc.cluster.local:4318/v1/traces
sampler: parentbased_traceidratio
samplerArg: "1"
scheduler:
freshnessWarningMultiple: 2
maxConcurrentRuns: 1
heartbeatStaleSeconds: 900
intervalMs: 600000
metricsPath: /metrics
healthPath: /api/health
replicas: 1
pvcStorage: 10Gi
servicePort: 8080
listenHost: 0.0.0.0
namespace: "hwlab-${lane}"
target:
extends: templates.webProbeSentinelTarget
observeWrapperRef: "config/hwlab-node-lanes.yaml#lanes.${LANE}.targets.${NODE}.observability.webProbe.sentinels[0]"
serviceAccountName: "hwlab-web-probe-sentinel-${nodeLower}"
deploymentName: "hwlab-web-probe-sentinel-${nodeLower}"
serviceName: "hwlab-web-probe-sentinel-${nodeLower}"
pvcName: "hwlab-web-probe-sentinel-${nodeLower}-state"
stateRoot: "/var/lib/web-probe-sentinel-${nodeLower}"
imageRef: "127.0.0.1:5000/hwlab/web-probe-sentinel-${nodeLower}:source-commit"
sqlite:
busyTimeoutMs: 2000
path: "/var/lib/web-probe-sentinel-${nodeLower}/index.sqlite"
webProbeSentinelPublicExposure:
expectedA: 82.156.23.220
hostname: monitor.pikapython.com
mode: pk01-caddy-frp-path
enabled: true
publicBaseUrl: "https://monitor.pikapython.com/sentinels/${nodeLower}-web-probe-sentinel"
routePrefix: "/sentinels/${nodeLower}-web-probe-sentinel"
frpc:
tokenKey: token
secretKey: frpc.toml
tokenSourceKey: FRP_TOKEN
tokenSourceRef: platform-infra/pk01-frp.env
serverPort: 22000
serverAddr: 82.156.23.220
image: 127.0.0.1:5000/hwlab/frpc:v0.68.1
deploymentName: "hwlab-web-probe-sentinel-${nodeLower}-frpc"
secretName: "hwlab-web-probe-sentinel-${nodeLower}-frpc"
httpProxy:
name: "hwlab-${nodeLower}-${lane}-web-probe-sentinel"
remotePort: 0
localIP: "hwlab-web-probe-sentinel-${nodeLower}.hwlab-${lane}.svc.cluster.local"
localPort: 8080
caddy:
responseHeaderTimeoutSeconds: 600
tls: auto
email: ops@pikapython.com
serviceName: caddy
configPath: /etc/caddy/Caddyfile
route: PK01
managedBlockOwner: "hwlab-web-probe-sentinel-${nodeLower}-${lane}"
webProbeSentinelCicd:
extends: templates.webProbeSentinelCicdCommon
builder:
ttlSecondsAfterFinished: 3600
activeDeadlineSeconds: 900
gitSshSecretName: git-mirror-github-ssh
sourceMode: sparse-git-checkout
namespace: devops-infra
jobPrefix: "web-probe-sentinel-${nodeLower}-publish"
gitopsPath: "deploy/gitops/node/${nodeLower}/web-probe-sentinel"
argo:
applicationName: "hwlab-web-probe-sentinel-${nodeLower}"
image:
repository: "127.0.0.1:5000/hwlab/web-probe-sentinel-${nodeLower}"
tagSource: source-commit
baseImageRef: "config/hwlab-node-control-plane.yaml#targets[${controlPlaneIndex}].tekton.toolsImage.output"
envRecipeRef: "config/hwlab-web-probe-sentinel/profiles.yaml#nodes.${NODE}.sentinels.${nodeLower}-web-probe-sentinel.runtime"
targetValidation:
scenarioId: workbench-dsflash-go-hwpod-two-turn-freeze-repro
maxSeconds: 600
serviceUnavailablePolicy: structured-failure
cadenceScheduler:
enabled: true
reason: k8s-native-periodic-quick-verify
concurrencyPolicy: Forbid
startingDeadlineSeconds: 600
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 5
activeDeadlineSlackSeconds: 60
ttlSecondsAfterFinished: 86400
backoffLimit: 0
+103 -165
View File
@@ -6,16 +6,14 @@ metadata:
- 1148 - 1148
- 1110 - 1110
- 1117 - 1117
defaults: defaults:
targetId: JD01 targetId: JD01
server: server:
id: benchmark-validated-master-shadowsocks-server id: benchmark-validated-master-shadowsocks-server
enabled: true enabled: true
benchmarkRef: pikasTech/unidesk#1110 benchmarkRef: "pikasTech/unidesk#1110"
implementationRef: pikasTech/unidesk#1117 implementationRef: "pikasTech/unidesk#1117"
sourceConfigRef: config/platform-infra/egress-proxy-sources.yaml#sources.master-shadowsocks sourceConfigRef: "config/platform-infra/egress-proxy-sources.yaml#sources.master-shadowsocks"
composeFile: config/platform-infra/sub2api-master-egress-proxy.compose.yaml composeFile: config/platform-infra/sub2api-master-egress-proxy.compose.yaml
serviceName: sub2api-master-egress-proxy serviceName: sub2api-master-egress-proxy
containerName: unidesk-sub2api-master-egress-proxy containerName: unidesk-sub2api-master-egress-proxy
@@ -27,176 +25,116 @@ server:
mode: tcp mode: tcp
host: 127.0.0.1 host: 127.0.0.1
port: 18792 port: 18792
sources: sources:
nc01-vpn-server-shadowsocks: nc01-vpn-server-shadowsocks:
sourceType: vpn-server-shadowsocks extends: templates.sources.singBoxHostClient
serverRef: /root/vpn-server
benchmarkRef: local-vpn-server benchmarkRef: local-vpn-server
implementationRef: /root/vpn-server
sourceConfigRef: config/platform-infra/egress-proxy-sources.yaml#sources.nc01-vpn-server-shadowsocks
client:
mode: trans-static-binary
upstreamUrl: https://github.com/SagerNet/sing-box/releases/download/v1.13.14/sing-box-1.13.14-linux-amd64.tar.gz
version: v1.13.14
archiveCachePath: .state/artifacts/platform-infra/sing-box-1.13.14-linux-amd64.tar.gz
archiveSha256: f48703461a15476951ac4967cdad339d986f4b8096b4eb3ff0829a500502d697
archiveInstallPath: /var/cache/unidesk/host-egress-proxy/sing-box-1.13.14-linux-amd64.tar.gz
binaryMember: sing-box-1.13.14-linux-amd64/sing-box
binaryCachePath: .state/artifacts/platform-infra/sing-box-1.13.14-linux-amd64
binarySha256: 68aeab83cc4ab2659a5b92232261a20746ccdafc3b3d1e19b2d63247eec3bbf7
installPath: /usr/local/bin/sing-box
configPath: /etc/unidesk/host-egress-proxy/sing-box.json
unitPath: /etc/systemd/system/unidesk-host-egress-proxy.service
serviceName: unidesk-host-egress-proxy
listenHost: 127.0.0.1
listenPort: 10808
podAccess:
enabled: true
listenHost: 10.42.0.1
listenPort: 10808
proxyUrl: http://10.42.0.1:10808
clashApiListen: 127.0.0.1:19090
healthUrl: http://127.0.0.1:19090/connections
proxyUrl: http://127.0.0.1:10808
externalProbeUrl: https://www.gstatic.com/generate_204
jd01-real-deps-master-shadowsocks: jd01-real-deps-master-shadowsocks:
sourceType: vpn-server-shadowsocks extends: templates.sources.singBoxHostClient
serverRef: /root/vpn-server benchmarkRef: "pikasTech/unidesk#1110"
benchmarkRef: pikasTech/unidesk#1110
implementationRef: /root/vpn-server
sourceConfigRef: config/platform-infra/egress-proxy-sources.yaml#sources.nc01-vpn-server-shadowsocks
client:
mode: trans-static-binary
upstreamUrl: https://github.com/SagerNet/sing-box/releases/download/v1.13.14/sing-box-1.13.14-linux-amd64.tar.gz
version: v1.13.14
archiveCachePath: .state/artifacts/platform-infra/sing-box-1.13.14-linux-amd64.tar.gz
archiveSha256: f48703461a15476951ac4967cdad339d986f4b8096b4eb3ff0829a500502d697
archiveInstallPath: /var/cache/unidesk/host-egress-proxy/sing-box-1.13.14-linux-amd64.tar.gz
binaryMember: sing-box-1.13.14-linux-amd64/sing-box
binaryCachePath: .state/artifacts/platform-infra/sing-box-1.13.14-linux-amd64
binarySha256: 68aeab83cc4ab2659a5b92232261a20746ccdafc3b3d1e19b2d63247eec3bbf7
installPath: /usr/local/bin/sing-box
configPath: /etc/unidesk/host-egress-proxy/sing-box.json
unitPath: /etc/systemd/system/unidesk-host-egress-proxy.service
serviceName: unidesk-host-egress-proxy
listenHost: 127.0.0.1
listenPort: 10808
podAccess:
enabled: true
listenHost: 10.42.0.1
listenPort: 10808
proxyUrl: http://10.42.0.1:10808
clashApiListen: 127.0.0.1:19090
healthUrl: http://127.0.0.1:19090/connections
proxyUrl: http://127.0.0.1:10808
externalProbeUrl: https://www.gstatic.com/generate_204
targets: targets:
NC01: NC01:
extends: templates.targets.hostProxyClient
route: NC01 route: NC01
enabled: true
sourceRef: sources.nc01-vpn-server-shadowsocks sourceRef: sources.nc01-vpn-server-shadowsocks
env: env:
httpProxy: http://127.0.0.1:10808 noProxyRefs:
httpsProxy: http://127.0.0.1:10808 common: noProxy.common
allProxy: http://127.0.0.1:10808 extras: noProxy.nodeExtras.NC01
noProxy:
- localhost
- 127.0.0.1
- ::1
- host.docker.internal
- 152.53.229.148
- 10.0.0.0/8
- 10.42.0.0/16
- 10.43.0.0/16
- 172.16.0.0/12
- 192.168.0.0/16
- .svc
- .svc.cluster.local
- .cluster.local
- kubernetes
- kubernetes.default
- kubernetes.default.svc
- argocd-repo-server
- argocd-repo-server.argocd
- argocd-redis
- argocd-redis.argocd
- git-mirror-http
- git-mirror-http.devops-infra
- git-mirror-write
- git-mirror-write.devops-infra
- 127.0.0.1:5000
- localhost:5000
- hyueapi.com
- .hyueapi.com
files:
envFile: /etc/unidesk/proxy.env
profile: /etc/profile.d/unidesk-proxy.sh
apt: /etc/apt/apt.conf.d/90unidesk-proxy
dockerSystemdDropIn: /etc/systemd/system/docker.service.d/10-unidesk-proxy.conf
k3sSystemdDropIn: /etc/systemd/system/k3s.service.d/10-unidesk-proxy.conf
trans:
hostProxyEnv:
enabled: true
envFileRef: files.envFile
applyTo: host-posix-commands
apply:
reloadSystemd: true
restartDocker: true
restartK3s: true
JD01: JD01:
extends: templates.targets.hostProxyClient
route: JD01 route: JD01
enabled: true
sourceRef: sources.jd01-real-deps-master-shadowsocks sourceRef: sources.jd01-real-deps-master-shadowsocks
env: env:
httpProxy: http://127.0.0.1:10808 noProxyRefs:
httpsProxy: http://127.0.0.1:10808 common: noProxy.common
allProxy: http://127.0.0.1:10808 extras: noProxy.nodeExtras.JD01
noProxy: templates:
- localhost sources:
- 127.0.0.1 singBoxHostClient:
- ::1 sourceType: vpn-server-shadowsocks
- host.docker.internal serverRef: /root/vpn-server
- 74.48.78.17 implementationRef: /root/vpn-server
- 82.156.23.220 sourceConfigRef: "config/platform-infra/egress-proxy-sources.yaml#sources.nc01-vpn-server-shadowsocks"
- 10.0.0.0/8 client:
- 10.42.0.0/16 mode: trans-static-binary
- 10.43.0.0/16 upstreamUrl: https://github.com/SagerNet/sing-box/releases/download/v1.13.14/sing-box-1.13.14-linux-amd64.tar.gz
- 172.16.0.0/12 version: v1.13.14
- 192.168.0.0/16 archiveCachePath: .state/artifacts/platform-infra/sing-box-1.13.14-linux-amd64.tar.gz
- .svc archiveSha256: f48703461a15476951ac4967cdad339d986f4b8096b4eb3ff0829a500502d697
- .svc.cluster.local archiveInstallPath: /var/cache/unidesk/host-egress-proxy/sing-box-1.13.14-linux-amd64.tar.gz
- .cluster.local binaryMember: sing-box-1.13.14-linux-amd64/sing-box
- kubernetes binaryCachePath: .state/artifacts/platform-infra/sing-box-1.13.14-linux-amd64
- kubernetes.default binarySha256: 68aeab83cc4ab2659a5b92232261a20746ccdafc3b3d1e19b2d63247eec3bbf7
- kubernetes.default.svc installPath: /usr/local/bin/sing-box
- argocd-repo-server configPath: /etc/unidesk/host-egress-proxy/sing-box.json
- argocd-repo-server.argocd unitPath: /etc/systemd/system/unidesk-host-egress-proxy.service
- argocd-redis serviceName: unidesk-host-egress-proxy
- argocd-redis.argocd listenHost: 127.0.0.1
- git-mirror-http listenPort: 10808
- git-mirror-http.devops-infra podAccess:
- git-mirror-write enabled: true
- git-mirror-write.devops-infra listenHost: 10.42.0.1
- 127.0.0.1:5000 listenPort: 10808
- localhost:5000 proxyUrl: http://10.42.0.1:10808
- hyueapi.com clashApiListen: 127.0.0.1:19090
- .hyueapi.com healthUrl: http://127.0.0.1:19090/connections
files: proxyUrl: http://127.0.0.1:10808
envFile: /etc/unidesk/proxy.env externalProbeUrl: https://www.gstatic.com/generate_204
profile: /etc/profile.d/unidesk-proxy.sh targets:
apt: /etc/apt/apt.conf.d/90unidesk-proxy hostProxyClient:
dockerSystemdDropIn: /etc/systemd/system/docker.service.d/10-unidesk-proxy.conf enabled: true
k3sSystemdDropIn: /etc/systemd/system/k3s.service.d/10-unidesk-proxy.conf env:
trans: httpProxy: http://127.0.0.1:10808
hostProxyEnv: httpsProxy: http://127.0.0.1:10808
enabled: true allProxy: http://127.0.0.1:10808
envFileRef: files.envFile files:
applyTo: host-posix-commands envFile: /etc/unidesk/proxy.env
apply: profile: /etc/profile.d/unidesk-proxy.sh
reloadSystemd: true apt: /etc/apt/apt.conf.d/90unidesk-proxy
restartDocker: true dockerSystemdDropIn: /etc/systemd/system/docker.service.d/10-unidesk-proxy.conf
restartK3s: true k3sSystemdDropIn: /etc/systemd/system/k3s.service.d/10-unidesk-proxy.conf
trans:
hostProxyEnv:
enabled: true
envFileRef: files.envFile
applyTo: host-posix-commands
apply:
reloadSystemd: true
restartDocker: true
restartK3s: true
noProxy:
common:
- localhost
- 127.0.0.1
- "::1"
- host.docker.internal
- 10.0.0.0/8
- 10.42.0.0/16
- 10.43.0.0/16
- 172.16.0.0/12
- 192.168.0.0/16
- .svc
- .svc.cluster.local
- .cluster.local
- kubernetes
- kubernetes.default
- kubernetes.default.svc
- argocd-repo-server
- argocd-repo-server.argocd
- argocd-redis
- argocd-redis.argocd
- git-mirror-http
- git-mirror-http.devops-infra
- git-mirror-write
- git-mirror-write.devops-infra
- 127.0.0.1:5000
- localhost:5000
- hyueapi.com
- .hyueapi.com
nodeExtras:
NC01:
- 152.53.229.148
JD01:
- 74.48.78.17
- 82.156.23.220
+157 -212
View File
@@ -1,6 +1,5 @@
version: 1 version: 1
kind: platform-infra-pipelines-as-code kind: platform-infra-pipelines-as-code
metadata: metadata:
id: pac-gitea-consumers id: pac-gitea-consumers
owner: unidesk owner: unidesk
@@ -10,14 +9,11 @@ metadata:
- 1555 - 1555
- 1557 - 1557
- 1560 - 1560
defaults: defaults:
targetId: NC01 targetId: NC01
consumerId: hwlab-nc01-v03 consumerId: hwlab-nc01-v03
display: display:
timeZone: Asia/Shanghai timeZone: Asia/Shanghai
release: release:
version: v0.48.0 version: v0.48.0
manifestUrl: https://github.com/openshift-pipelines/pipelines-as-code/releases/download/v0.48.0/release.k8s.yaml manifestUrl: https://github.com/openshift-pipelines/pipelines-as-code/releases/download/v0.48.0/release.k8s.yaml
@@ -25,13 +21,11 @@ release:
controllerServiceName: pipelines-as-code-controller controllerServiceName: pipelines-as-code-controller
controllerServicePort: 8080 controllerServicePort: 8080
waitTimeoutSeconds: 55 waitTimeoutSeconds: 55
closeout: closeout:
gitOpsMirrorFlush: gitOpsMirrorFlush:
enabled: true enabled: true
waitTimeoutSeconds: 55 waitTimeoutSeconds: 55
maxAttempts: 5 maxAttempts: 5
targets: targets:
- id: JD01 - id: JD01
route: JD01:k3s route: JD01:k3s
@@ -43,9 +37,8 @@ targets:
namespace: agentrun-ci namespace: agentrun-ci
role: active-cicd-trigger-authority role: active-cicd-trigger-authority
enabled: true enabled: true
gitea: gitea:
configRef: config/platform-infra/gitea.yaml#sourceAuthority.repositories configRef: "config/platform-infra/gitea.yaml#sourceAuthority.repositories"
internalBaseUrl: http://gitea-http.devops-infra.svc.cluster.local:3000 internalBaseUrl: http://gitea-http.devops-infra.svc.cluster.local:3000
admin: admin:
sourceRoot: /root/unidesk sourceRoot: /root/unidesk
@@ -60,212 +53,164 @@ gitea:
events: events:
- push - push
branch: params.source_branch branch: params.source_branch
repositories: repositories:
- id: agentrun-jd01-v02 - extends: templates.repositories.agentrunV02
name: agentrun-jd01-v02 variables:
namespace: agentrun-ci NODE: JD01
providerType: gitea LANE: v02
url: https://gitea.pikapython.com/mirrors/pikasTech-agentrun url: https://gitea.pikapython.com/mirrors/pikasTech-agentrun
cloneUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git - extends: templates.repositories.agentrunV02
owner: mirrors variables:
repo: pikasTech-agentrun NODE: NC01
secretName: pac-gitea-agentrun-jd01-v02 LANE: v02
tokenKey: token - extends: templates.repositories.sentinelV03
webhookSecretKey: webhook.secret variables:
concurrencyLimit: 1 NODE: JD01
params: LANE: v03
git_read_url: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git
git_write_url: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git
source_branch: v0.2
gitops_branch: jd01-v0.2-gitops
# Historical prefix name retained for existing snapshot refs; active architecture is Gitea + PaC, not Gitea Actions.
source_snapshot_prefix: refs/unidesk/snapshots/gitea-actions/agentrun-v0.2
pipeline_name: agentrun-jd01-v02-ci-image-publish
pipeline_run_prefix: agentrun-jd01-v02-ci
service_account: agentrun-jd01-v02-tekton-runner
workspace_pvc_size: 2Gi
- id: agentrun-nc01-v02
name: agentrun-nc01-v02
namespace: agentrun-ci
providerType: gitea
url: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun
cloneUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git
owner: mirrors
repo: pikasTech-agentrun
secretName: pac-gitea-agentrun-nc01-v02
tokenKey: token
webhookSecretKey: webhook.secret
concurrencyLimit: 1
params:
git_read_url: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git
git_write_url: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git
source_branch: v0.2
gitops_branch: nc01-v0.2-gitops
# Historical prefix name retained for existing snapshot refs; active architecture is Gitea + PaC, not Gitea Actions.
source_snapshot_prefix: refs/unidesk/snapshots/gitea-actions/agentrun-v0.2
pipeline_name: agentrun-nc01-v02-ci-image-publish
pipeline_run_prefix: agentrun-nc01-v02-ci
service_account: agentrun-nc01-v02-tekton-runner
workspace_pvc_size: 2Gi
- id: sentinel-jd01-v03
name: sentinel-jd01-v03
namespace: devops-infra
providerType: gitea
url: https://gitea.pikapython.com/mirrors/pikasTech-unidesk url: https://gitea.pikapython.com/mirrors/pikasTech-unidesk
cloneUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-unidesk.git - extends: templates.repositories.sentinelV03
owner: mirrors variables:
repo: pikasTech-unidesk NODE: NC01
secretName: pac-gitea-sentinel-jd01-v03 LANE: v03
tokenKey: token - extends: templates.repositories.hwlabV03
webhookSecretKey: webhook.secret variables:
concurrencyLimit: 1 NODE: JD01
params: LANE: v03
git_read_url: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-unidesk.git
source_branch: master
# Historical prefix name retained for existing snapshot refs; active architecture is Gitea + PaC, not Gitea Actions.
source_snapshot_prefix: refs/unidesk/snapshots/gitea-actions/unidesk-master
node: JD01
lane: v03
sentinel_id: jd01-web-probe-sentinel
image_repository: 127.0.0.1:5000/hwlab/web-probe-sentinel-jd01
registry_probe_base: http://127.0.0.1:5000
gitops_branch: v0.3-gitops
gitops_manifest_path: deploy/gitops/node/jd01/web-probe-sentinel/web-probe-sentinel.yaml
pipeline_name: hwlab-web-probe-sentinel-jd01-pac
pipeline_run_prefix: hwlab-web-probe-sentinel-jd01
- id: sentinel-nc01-v03
name: sentinel-nc01-v03
namespace: devops-infra
providerType: gitea
url: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-unidesk
cloneUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-unidesk.git
owner: mirrors
repo: pikasTech-unidesk
secretName: pac-gitea-sentinel-nc01-v03
tokenKey: token
webhookSecretKey: webhook.secret
concurrencyLimit: 1
params:
git_read_url: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-unidesk.git
source_branch: master
# Historical prefix name retained for existing snapshot refs; active architecture is Gitea + PaC, not Gitea Actions.
source_snapshot_prefix: refs/unidesk/snapshots/gitea-actions/unidesk-master
node: NC01
lane: v03
sentinel_id: nc01-web-probe-sentinel
image_repository: 127.0.0.1:5000/hwlab/web-probe-sentinel-nc01
registry_probe_base: http://127.0.0.1:5000
gitops_branch: v0.3-gitops
gitops_manifest_path: deploy/gitops/node/nc01/web-probe-sentinel/web-probe-sentinel.yaml
pipeline_name: hwlab-web-probe-sentinel-nc01-pac
pipeline_run_prefix: hwlab-web-probe-sentinel-nc01
- id: hwlab-jd01-v03
name: hwlab-jd01-v03
namespace: hwlab-ci
providerType: gitea
url: https://gitea.pikapython.com/mirrors/pikasTech-HWLAB url: https://gitea.pikapython.com/mirrors/pikasTech-HWLAB
cloneUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git - extends: templates.repositories.hwlabV03
owner: mirrors variables:
repo: pikasTech-HWLAB NODE: NC01
secretName: pac-gitea-hwlab-jd01-v03 LANE: v03
tokenKey: token
webhookSecretKey: webhook.secret
concurrencyLimit: 1
params:
git_read_url: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git
git_write_url: http://git-mirror-write.devops-infra.svc.cluster.local:8080/pikasTech/HWLAB.git
source_branch: v0.3
gitops_branch: v0.3-gitops
# Historical prefix name retained for existing snapshot refs; active architecture is Gitea + PaC, not Gitea Actions.
source_snapshot_prefix: refs/unidesk/snapshots/gitea-actions/hwlab-node-runtime/v0.3
pipeline_name: hwlab-jd01-v03-ci-image-publish
pipeline_run_prefix: hwlab-jd01-v03-ci-poll
service_account: hwlab-jd01-v03-tekton-runner
node: JD01
lane: v03
runtime_namespace: hwlab-v03
- id: hwlab-nc01-v03
name: hwlab-nc01-v03
namespace: hwlab-ci
providerType: gitea
url: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB
cloneUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git
owner: mirrors
repo: pikasTech-HWLAB
secretName: pac-gitea-hwlab-nc01-v03
tokenKey: token
webhookSecretKey: webhook.secret
concurrencyLimit: 1
params:
git_read_url: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git
git_write_url: http://git-mirror-write.devops-infra.svc.cluster.local:8080/pikasTech/HWLAB.git
source_branch: v0.3
gitops_branch: v0.3-gitops
# Historical prefix name retained for existing snapshot refs; active architecture is Gitea + PaC, not Gitea Actions.
source_snapshot_prefix: refs/unidesk/snapshots/gitea-actions/hwlab-node-runtime/v0.3
pipeline_name: hwlab-nc01-v03-ci-image-publish
pipeline_run_prefix: hwlab-nc01-v03-ci-poll
service_account: hwlab-nc01-v03-tekton-runner
node: NC01
lane: v03
runtime_namespace: hwlab-v03
consumers: consumers:
- id: agentrun-jd01-v02 - extends: templates.consumers.agentrunV02
repositoryRef: agentrun-jd01-v02 variables:
node: JD01 NODE: JD01
lane: jd01-v02 LANE: v02
namespace: agentrun-ci - extends: templates.consumers.agentrunV02
pipeline: agentrun-jd01-v02-ci-image-publish variables:
pipelineRunPrefix: agentrun-jd01-v02-ci NODE: NC01
argoNamespace: argocd LANE: v02
argoApplication: agentrun-jd01-v02 - extends: templates.consumers.sentinelV03
- id: agentrun-nc01-v02 variables:
repositoryRef: agentrun-nc01-v02 NODE: JD01
node: NC01 LANE: v03
lane: nc01-v02 - extends: templates.consumers.sentinelV03
namespace: agentrun-ci variables:
pipeline: agentrun-nc01-v02-ci-image-publish NODE: NC01
pipelineRunPrefix: agentrun-nc01-v02-ci LANE: v03
argoNamespace: argocd - extends: templates.consumers.hwlabV03
argoApplication: agentrun-nc01-v02 variables:
- id: sentinel-jd01-v03 NODE: JD01
repositoryRef: sentinel-jd01-v03 LANE: v03
node: JD01 - extends: templates.consumers.hwlabV03
lane: v03 variables:
namespace: devops-infra NODE: NC01
pipeline: hwlab-web-probe-sentinel-jd01-pac LANE: v03
pipelineRunPrefix: hwlab-web-probe-sentinel-jd01 templates:
argoNamespace: argocd repositories:
argoApplication: hwlab-web-probe-sentinel-jd01 agentrunV02:
- id: sentinel-nc01-v03 id: "agentrun-${nodeLower}-v02"
repositoryRef: sentinel-nc01-v03 name: "agentrun-${nodeLower}-v02"
node: NC01 namespace: agentrun-ci
lane: v03 providerType: gitea
namespace: devops-infra url: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun
pipeline: hwlab-web-probe-sentinel-nc01-pac cloneUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git
pipelineRunPrefix: hwlab-web-probe-sentinel-nc01 owner: mirrors
argoNamespace: argocd repo: pikasTech-agentrun
argoApplication: hwlab-web-probe-sentinel-nc01 secretName: "pac-gitea-agentrun-${nodeLower}-v02"
- id: hwlab-jd01-v03 tokenKey: token
repositoryRef: hwlab-jd01-v03 webhookSecretKey: webhook.secret
node: JD01 concurrencyLimit: 1
lane: v03 params:
namespace: hwlab-ci git_read_url: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git
pipeline: hwlab-jd01-v03-ci-image-publish git_write_url: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git
pipelineRunPrefix: hwlab-jd01-v03-ci-poll source_branch: v0.2
argoNamespace: argocd gitops_branch: "${nodeLower}-v0.2-gitops"
argoApplication: hwlab-node-v03 source_snapshot_prefix: refs/unidesk/snapshots/gitea-actions/agentrun-v0.2
closeoutGitOpsMirrorFlush: true pipeline_name: "agentrun-${nodeLower}-v02-ci-image-publish"
pipeline_run_prefix: "agentrun-${nodeLower}-v02-ci"
- id: hwlab-nc01-v03 service_account: "agentrun-${nodeLower}-v02-tekton-runner"
repositoryRef: hwlab-nc01-v03 workspace_pvc_size: 2Gi
node: NC01 sentinelV03:
lane: v03 id: "sentinel-${nodeLower}-v03"
namespace: hwlab-ci name: "sentinel-${nodeLower}-v03"
pipeline: hwlab-nc01-v03-ci-image-publish namespace: devops-infra
pipelineRunPrefix: hwlab-nc01-v03-ci-poll providerType: gitea
argoNamespace: argocd url: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-unidesk
argoApplication: hwlab-node-v03 cloneUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-unidesk.git
closeoutGitOpsMirrorFlush: true owner: mirrors
repo: pikasTech-unidesk
secretName: "pac-gitea-sentinel-${nodeLower}-v03"
tokenKey: token
webhookSecretKey: webhook.secret
concurrencyLimit: 1
params:
git_read_url: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-unidesk.git
source_branch: master
source_snapshot_prefix: refs/unidesk/snapshots/gitea-actions/unidesk-master
node: "${NODE}"
lane: v03
sentinel_id: "${nodeLower}-web-probe-sentinel"
image_repository: "127.0.0.1:5000/hwlab/web-probe-sentinel-${nodeLower}"
registry_probe_base: http://127.0.0.1:5000
gitops_branch: v0.3-gitops
gitops_manifest_path: "deploy/gitops/node/${nodeLower}/web-probe-sentinel/web-probe-sentinel.yaml"
pipeline_name: "hwlab-web-probe-sentinel-${nodeLower}-pac"
pipeline_run_prefix: "hwlab-web-probe-sentinel-${nodeLower}"
hwlabV03:
id: "hwlab-${nodeLower}-v03"
name: "hwlab-${nodeLower}-v03"
namespace: hwlab-ci
providerType: gitea
url: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB
cloneUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git
owner: mirrors
repo: pikasTech-HWLAB
secretName: "pac-gitea-hwlab-${nodeLower}-v03"
tokenKey: token
webhookSecretKey: webhook.secret
concurrencyLimit: 1
params:
git_read_url: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git
git_write_url: http://git-mirror-write.devops-infra.svc.cluster.local:8080/pikasTech/HWLAB.git
source_branch: v0.3
gitops_branch: v0.3-gitops
source_snapshot_prefix: refs/unidesk/snapshots/gitea-actions/hwlab-node-runtime/v0.3
pipeline_name: "hwlab-${nodeLower}-v03-ci-image-publish"
pipeline_run_prefix: "hwlab-${nodeLower}-v03-ci-poll"
service_account: "hwlab-${nodeLower}-v03-tekton-runner"
node: "${NODE}"
lane: v03
runtime_namespace: hwlab-v03
consumers:
agentrunV02:
id: "agentrun-${nodeLower}-v02"
repositoryRef: "agentrun-${nodeLower}-v02"
node: "${NODE}"
lane: "${nodeLower}-v02"
namespace: agentrun-ci
pipeline: "agentrun-${nodeLower}-v02-ci-image-publish"
pipelineRunPrefix: "agentrun-${nodeLower}-v02-ci"
argoNamespace: argocd
argoApplication: "agentrun-${nodeLower}-v02"
sentinelV03:
id: "sentinel-${nodeLower}-v03"
repositoryRef: "sentinel-${nodeLower}-v03"
node: "${NODE}"
lane: v03
namespace: devops-infra
pipeline: "hwlab-web-probe-sentinel-${nodeLower}-pac"
pipelineRunPrefix: "hwlab-web-probe-sentinel-${nodeLower}"
argoNamespace: argocd
argoApplication: "hwlab-web-probe-sentinel-${nodeLower}"
hwlabV03:
id: "hwlab-${nodeLower}-v03"
repositoryRef: "hwlab-${nodeLower}-v03"
node: "${NODE}"
lane: v03
namespace: hwlab-ci
pipeline: "hwlab-${nodeLower}-v03-ci-image-publish"
pipelineRunPrefix: "hwlab-${nodeLower}-v03-ci-poll"
argoNamespace: argocd
argoApplication: hwlab-node-v03
closeoutGitOpsMirrorFlush: true
+2 -1
View File
@@ -13,6 +13,7 @@ import {
stringArrayField, stringArrayField,
stringField, stringField,
} from "./platform-infra-ops-library"; } from "./platform-infra-ops-library";
import { materializeYamlComposition } from "./yaml-composition";
export const AGENTRUN_CONFIG_PATH = "config/agentrun.yaml"; export const AGENTRUN_CONFIG_PATH = "config/agentrun.yaml";
@@ -464,7 +465,7 @@ export function agentRunSourceSnapshotRef(spec: AgentRunLaneSpec, sourceCommit:
function readAgentRunControlPlaneConfig(env: NodeJS.ProcessEnv): AgentRunControlPlaneConfig { function readAgentRunControlPlaneConfig(env: NodeJS.ProcessEnv): AgentRunControlPlaneConfig {
const configPath = env.AGENTRUN_CONTROL_PLANE_CONFIG ?? rootPath(AGENTRUN_CONFIG_PATH); const configPath = env.AGENTRUN_CONTROL_PLANE_CONFIG ?? rootPath(AGENTRUN_CONFIG_PATH);
const root = readYamlRecord<Record<string, unknown>>(configPath); const root = materializeYamlComposition(readYamlRecord<Record<string, unknown>>(configPath), { label: configPath }).value;
validateConfigEnvelope(root, configPath); validateConfigEnvelope(root, configPath);
const controlPlane = recordField(root, "controlPlane", configPath); const controlPlane = recordField(root, "controlPlane", configPath);
const defaultTarget = recordField(controlPlane, "default", `${configPath}.controlPlane`); const defaultTarget = recordField(controlPlane, "default", `${configPath}.controlPlane`);
+5 -1
View File
@@ -5,6 +5,7 @@
// Responsibility: YAML source-of-truth parsing for HWLAB node/lane Workbench observability. // Responsibility: YAML source-of-truth parsing for HWLAB node/lane Workbench observability.
import { readFileSync } from "node:fs"; import { readFileSync } from "node:fs";
import { rootPath } from "./config"; import { rootPath } from "./config";
import { materializeYamlComposition } from "./yaml-composition";
export type HwlabRuntimeLane = string; export type HwlabRuntimeLane = string;
@@ -1685,7 +1686,10 @@ function runtimeImageBuildsConfig(value: unknown, path: string): HwlabRuntimeIma
function readHwlabNodeLaneConfig(): HwlabNodeLaneConfig { function readHwlabNodeLaneConfig(): HwlabNodeLaneConfig {
const path = rootPath(HWLAB_NODE_LANE_CONFIG_PATH); const path = rootPath(HWLAB_NODE_LANE_CONFIG_PATH);
const raw = readFileSync(path, "utf8"); const raw = readFileSync(path, "utf8");
const parsed = asRecord(Bun.YAML.parse(raw) as unknown, HWLAB_NODE_LANE_CONFIG_PATH); const parsed = asRecord(
materializeYamlComposition(Bun.YAML.parse(raw) as unknown, { label: HWLAB_NODE_LANE_CONFIG_PATH }).value,
HWLAB_NODE_LANE_CONFIG_PATH,
);
validateConfigEnvelope(parsed); validateConfigEnvelope(parsed);
const defaultTarget = parseDefaultTarget(asRecord(parsed.defaults, `${HWLAB_NODE_LANE_CONFIG_PATH}.defaults`)); const defaultTarget = parseDefaultTarget(asRecord(parsed.defaults, `${HWLAB_NODE_LANE_CONFIG_PATH}.defaults`));
const requiredNoProxy = stringArrayField(parsed, "requiredNoProxy", HWLAB_NODE_LANE_CONFIG_PATH); const requiredNoProxy = stringArrayField(parsed, "requiredNoProxy", HWLAB_NODE_LANE_CONFIG_PATH);
@@ -3,6 +3,7 @@
import { createHash } from "node:crypto"; import { createHash } from "node:crypto";
import { existsSync, readFileSync } from "node:fs"; import { existsSync, readFileSync } from "node:fs";
import { rootPath } from "./config"; import { rootPath } from "./config";
import { materializeYamlComposition } from "./yaml-composition";
export interface WebProbeSentinelTemplateContext { export interface WebProbeSentinelTemplateContext {
readonly nodeId: string; readonly nodeId: string;
@@ -34,7 +35,7 @@ export function readWebProbeSentinelConfigRef(context: WebProbeSentinelTemplateC
const absPath = rootPath(parsed.file); const absPath = rootPath(parsed.file);
if (!existsSync(absPath)) throw new Error(`${parsed.file} does not exist`); if (!existsSync(absPath)) throw new Error(`${parsed.file} does not exist`);
const text = readFileSync(absPath, "utf8"); const text = readFileSync(absPath, "utf8");
const doc = Bun.YAML.parse(text) as unknown; const doc = materializeYamlComposition(Bun.YAML.parse(text) as unknown, { label: parsed.file }).value;
const vars = { ...builtinVars, ...documentVars(doc, builtinVars) }; const vars = { ...builtinVars, ...documentVars(doc, builtinVars) };
const path = renderTemplateString(parsed.path, vars, `${parsed.file}#path`); const path = renderTemplateString(parsed.path, vars, `${parsed.file}#path`);
const target = valueAtConfigPath(doc, path); const target = valueAtConfigPath(doc, path);
@@ -4,6 +4,7 @@ import { existsSync, readFileSync } from "node:fs";
import { rootPath } from "./config"; import { rootPath } from "./config";
import { readWebProbeSentinelConfigRefTarget, type WebProbeSentinelTemplateContext } from "./hwlab-node-web-sentinel-config-ref"; import { readWebProbeSentinelConfigRefTarget, type WebProbeSentinelTemplateContext } from "./hwlab-node-web-sentinel-config-ref";
import { HWLAB_WEB_PROBE_SENTINEL_CONFIG_REF_KEYS, type HwlabRuntimeLaneSpec, type HwlabRuntimeWebProbeSentinelConfigRefKey, type HwlabRuntimeWebProbeSentinelRegistryItemSpec } from "./hwlab-node-lanes"; import { HWLAB_WEB_PROBE_SENTINEL_CONFIG_REF_KEYS, type HwlabRuntimeLaneSpec, type HwlabRuntimeWebProbeSentinelConfigRefKey, type HwlabRuntimeWebProbeSentinelRegistryItemSpec } from "./hwlab-node-lanes";
import { materializeYamlComposition } from "./yaml-composition";
export interface ResolvedWebProbeSentinel { export interface ResolvedWebProbeSentinel {
readonly id: string; readonly id: string;
@@ -169,7 +170,7 @@ export function readConfigRefTarget(ref: string, context?: WebProbeSentinelTempl
} }
const absPath = rootPath(file); const absPath = rootPath(file);
if (!existsSync(absPath)) throw new Error(`${file} does not exist`); if (!existsSync(absPath)) throw new Error(`${file} does not exist`);
const doc = Bun.YAML.parse(readFileSync(absPath, "utf8")) as unknown; const doc = materializeYamlComposition(Bun.YAML.parse(readFileSync(absPath, "utf8")) as unknown, { label: file }).value;
return valueAtPath(doc, path); return valueAtPath(doc, path);
} }
+31 -4
View File
@@ -9,6 +9,7 @@ import type { RenderedCliResult } from "./output";
import { shQuote } from "./platform-infra-public-service"; import { shQuote } from "./platform-infra-public-service";
import { fingerprintSecretValues, readEnvSourceFile, requiredEnvValue } from "./secrets"; import { fingerprintSecretValues, readEnvSourceFile, requiredEnvValue } from "./secrets";
import { transHostProxyEnvSummary } from "./trans-host-proxy"; import { transHostProxyEnvSummary } from "./trans-host-proxy";
import { materializeYamlComposition } from "./yaml-composition";
const configPath = "config/platform-infra/host-proxy.yaml"; const configPath = "config/platform-infra/host-proxy.yaml";
@@ -161,7 +162,7 @@ function parseOptions(args: string[]): HostProxyOptions {
} }
function readHostProxyConfig(): HostProxyConfig { function readHostProxyConfig(): HostProxyConfig {
const root = record(Bun.YAML.parse(readFileSync(rootPath(configPath), "utf8")), configPath); const root = record(materializeYamlComposition(Bun.YAML.parse(readFileSync(rootPath(configPath), "utf8")) as unknown, { label: configPath }).value, configPath);
if (root.kind !== "platform-infra-host-proxy") throw new Error(`${configPath}.kind must be platform-infra-host-proxy`); if (root.kind !== "platform-infra-host-proxy") throw new Error(`${configPath}.kind must be platform-infra-host-proxy`);
const defaultsRaw = record(root.defaults, `${configPath}.defaults`); const defaultsRaw = record(root.defaults, `${configPath}.defaults`);
const server = parseServer(record(root.server, `${configPath}.server`), `${configPath}.server`); const server = parseServer(record(root.server, `${configPath}.server`), `${configPath}.server`);
@@ -172,7 +173,7 @@ function readHostProxyConfig(): HostProxyConfig {
})); }));
const targets: Record<string, HostProxyTarget> = {}; const targets: Record<string, HostProxyTarget> = {};
for (const [id, value] of Object.entries(record(root.targets, `${configPath}.targets`))) { for (const [id, value] of Object.entries(record(root.targets, `${configPath}.targets`))) {
targets[id] = parseTarget(id, record(value, `${configPath}.targets.${id}`), sources); targets[id] = parseTarget(id, record(value, `${configPath}.targets.${id}`), sources, root);
} }
return { return {
defaults: { targetId: stringField(defaultsRaw, "targetId", `${configPath}.defaults`) }, defaults: { targetId: stringField(defaultsRaw, "targetId", `${configPath}.defaults`) },
@@ -315,7 +316,7 @@ function podAccessSpec(raw: Record<string, unknown>, label: string): HostProxyPo
return { enabled, listenHost, listenPort, proxyUrl }; return { enabled, listenHost, listenPort, proxyUrl };
} }
function parseTarget(id: string, raw: Record<string, unknown>, sources: Record<string, HostProxySource>): HostProxyTarget { function parseTarget(id: string, raw: Record<string, unknown>, sources: Record<string, HostProxySource>, root: Record<string, unknown>): HostProxyTarget {
const sourceRef = stringField(raw, "sourceRef", `${configPath}.targets.${id}`); const sourceRef = stringField(raw, "sourceRef", `${configPath}.targets.${id}`);
if (!sourceRef.startsWith("sources.")) throw new Error(`${configPath}.targets.${id}.sourceRef must use sources.<id>`); if (!sourceRef.startsWith("sources.")) throw new Error(`${configPath}.targets.${id}.sourceRef must use sources.<id>`);
const sourceId = sourceRef.slice("sources.".length); const sourceId = sourceRef.slice("sources.".length);
@@ -324,7 +325,9 @@ function parseTarget(id: string, raw: Record<string, unknown>, sources: Record<s
const envRaw = record(raw.env, `${configPath}.targets.${id}.env`); const envRaw = record(raw.env, `${configPath}.targets.${id}.env`);
const filesRaw = record(raw.files, `${configPath}.targets.${id}.files`); const filesRaw = record(raw.files, `${configPath}.targets.${id}.files`);
const applyRaw = record(raw.apply, `${configPath}.targets.${id}.apply`); const applyRaw = record(raw.apply, `${configPath}.targets.${id}.apply`);
const noProxy = stringArrayField(envRaw, "noProxy", `${configPath}.targets.${id}.env`); const noProxy = envRaw.noProxy === undefined
? noProxyFromRefs(envRaw, root, `${configPath}.targets.${id}.env`)
: stringArrayField(envRaw, "noProxy", `${configPath}.targets.${id}.env`);
if (!noProxy.includes("hyueapi.com") || !noProxy.includes(".hyueapi.com")) { if (!noProxy.includes("hyueapi.com") || !noProxy.includes(".hyueapi.com")) {
throw new Error(`${configPath}.targets.${id}.env.noProxy must preserve hyueapi.com and .hyueapi.com`); throw new Error(`${configPath}.targets.${id}.env.noProxy must preserve hyueapi.com and .hyueapi.com`);
} }
@@ -359,6 +362,30 @@ function parseTarget(id: string, raw: Record<string, unknown>, sources: Record<s
return target; return target;
} }
function noProxyFromRefs(envRaw: Record<string, unknown>, root: Record<string, unknown>, label: string): string[] {
const refs = record(envRaw.noProxyRefs, `${label}.noProxyRefs`);
const values: string[] = [];
for (const key of ["common", "extras"] as const) {
const ref = stringField(refs, key, `${label}.noProxyRefs`);
values.push(...stringArrayAtPath(root, ref, `${label}.noProxyRefs.${key}`));
}
return [...new Set(values)];
}
function stringArrayAtPath(root: unknown, ref: string, label: string): string[] {
let current: unknown = root;
for (const segment of ref.split(".")) {
if (!/^[A-Za-z0-9_-]+$/u.test(segment) || typeof current !== "object" || current === null || Array.isArray(current)) {
throw new Error(`${label} references invalid path ${ref}`);
}
current = (current as Record<string, unknown>)[segment];
}
if (!Array.isArray(current) || !current.every((item) => typeof item === "string" && item.length > 0)) {
throw new Error(`${label} must reference a string array`);
}
return [...current];
}
function resolveTarget(config: HostProxyConfig, targetId: string): HostProxyTarget { function resolveTarget(config: HostProxyConfig, targetId: string): HostProxyTarget {
const target = config.targets[targetId]; const target = config.targets[targetId];
if (target === undefined) throw new Error(`${configPath}.targets.${targetId} is not defined`); if (target === undefined) throw new Error(`${configPath}.targets.${targetId} is not defined`);
@@ -15,6 +15,7 @@ import {
shQuote, shQuote,
sha256Fingerprint, sha256Fingerprint,
} from "./platform-infra-ops-library"; } from "./platform-infra-ops-library";
import { materializeYamlComposition } from "./yaml-composition";
const configFile = rootPath("config", "platform-infra", "pipelines-as-code.yaml"); const configFile = rootPath("config", "platform-infra", "pipelines-as-code.yaml");
const configLabel = "config/platform-infra/pipelines-as-code.yaml"; const configLabel = "config/platform-infra/pipelines-as-code.yaml";
@@ -213,7 +214,7 @@ function help(): Record<string, unknown> {
} }
function readPacConfig(): PacConfig { function readPacConfig(): PacConfig {
const root = readYamlRecord<Record<string, unknown>>(configFile, "platform-infra-pipelines-as-code"); const root = materializeYamlComposition(readYamlRecord<Record<string, unknown>>(configFile, "platform-infra-pipelines-as-code"), { label: configLabel }).value;
const release = y.objectField(root, "release", ""); const release = y.objectField(root, "release", "");
const closeout = y.objectField(root, "closeout", ""); const closeout = y.objectField(root, "closeout", "");
const gitOpsMirrorFlush = y.objectField(closeout, "gitOpsMirrorFlush", "closeout"); const gitOpsMirrorFlush = y.objectField(closeout, "gitOpsMirrorFlush", "closeout");
+2 -1
View File
@@ -1,6 +1,7 @@
import { existsSync, readFileSync } from "node:fs"; import { existsSync, readFileSync } from "node:fs";
import { join } from "node:path"; import { join } from "node:path";
import { repoRoot } from "./config"; import { repoRoot } from "./config";
import { materializeYamlComposition } from "./yaml-composition";
export const transHostProxyConfigPath = "config/platform-infra/host-proxy.yaml"; export const transHostProxyConfigPath = "config/platform-infra/host-proxy.yaml";
@@ -19,7 +20,7 @@ export interface TransHostProxyEnvRule {
export function readTransHostProxyEnvRule(targetId: string): TransHostProxyEnvRule | null { export function readTransHostProxyEnvRule(targetId: string): TransHostProxyEnvRule | null {
const absolutePath = join(repoRoot, transHostProxyConfigPath); const absolutePath = join(repoRoot, transHostProxyConfigPath);
if (!existsSync(absolutePath)) return null; if (!existsSync(absolutePath)) return null;
const root = record(Bun.YAML.parse(readFileSync(absolutePath, "utf8")), transHostProxyConfigPath); const root = record(materializeYamlComposition(Bun.YAML.parse(readFileSync(absolutePath, "utf8")) as unknown, { label: transHostProxyConfigPath }).value, transHostProxyConfigPath);
if (root.kind !== "platform-infra-host-proxy") throw new Error(`${transHostProxyConfigPath}.kind must be platform-infra-host-proxy`); if (root.kind !== "platform-infra-host-proxy") throw new Error(`${transHostProxyConfigPath}.kind must be platform-infra-host-proxy`);
const targets = record(root.targets, `${transHostProxyConfigPath}.targets`); const targets = record(root.targets, `${transHostProxyConfigPath}.targets`);
const targetRaw = targets[targetId]; const targetRaw = targets[targetId];
+166
View File
@@ -0,0 +1,166 @@
// SPEC: pikasTech/unidesk#1579 YAML-first composition.
// Responsibility: materialize lightweight YAML templates before domain parsers validate shapes.
export interface YamlCompositionResult<T> {
readonly value: T;
readonly traces: readonly YamlCompositionTrace[];
}
export interface YamlCompositionTrace {
readonly path: string;
readonly extends: readonly string[];
readonly overrideKeys: readonly string[];
readonly variables: Record<string, string>;
}
interface CompositionOptions {
readonly label: string;
readonly stripTemplateKeys?: boolean;
}
const COMPOSITION_KEYS = new Set(["extends", "overrides", "variables"]);
const TEMPLATE_ROOT_KEYS = new Set(["templates", "baselines"]);
export function materializeYamlComposition<T>(input: T, options: CompositionOptions): YamlCompositionResult<T> {
const traces: YamlCompositionTrace[] = [];
const root = input as unknown;
const value = materializeValue(root, root, options.label, {}, traces, []);
if (options.stripTemplateKeys === true && isRecord(value)) {
const stripped = { ...value };
for (const key of TEMPLATE_ROOT_KEYS) delete stripped[key];
return { value: stripped as T, traces };
}
return { value: value as T, traces };
}
export function renderYamlTemplateStrings<T>(input: T, variables: Record<string, string>): T {
return renderValue(input as unknown, deriveVariables(variables)) as T;
}
function materializeValue(
value: unknown,
root: unknown,
path: string,
inheritedVariables: Record<string, string>,
traces: YamlCompositionTrace[],
stack: readonly string[],
): unknown {
if (Array.isArray(value)) {
return value.map((item, index) => materializeValue(item, root, `${path}[${index}]`, inheritedVariables, traces, stack));
}
if (!isRecord(value)) return renderValue(value, inheritedVariables);
const localVariables = deriveVariables({ ...inheritedVariables, ...stringRecord(value.variables) });
const refs = extendsRefs(value.extends);
let merged: Record<string, unknown> = {};
if (refs.length > 0) {
for (const ref of refs) {
if (stack.includes(ref)) throw new Error(`${path}.extends has cyclic template reference ${ref}`);
const template = valueAtPath(root, ref);
if (!isRecord(template)) throw new Error(`${path}.extends references missing object ${ref}`);
const renderedTemplate = materializeValue(template, root, ref, localVariables, traces, [...stack, ref]);
merged = deepMerge(merged, asRecord(renderedTemplate, ref));
}
}
const own = stripCompositionFields(value);
const overrides = value.overrides === undefined ? {} : asRecord(value.overrides, `${path}.overrides`);
merged = deepMerge(merged, own);
merged = deepMerge(merged, overrides);
const rendered = renderObjectScalars(merged, deriveVariables({ ...variablesFromRecord(merged), ...localVariables }));
const result = Object.fromEntries(
Object.entries(asRecord(rendered, path)).map(([key, item]) => [
key,
materializeValue(item, root, `${path}.${key}`, deriveVariables({ ...localVariables, ...variablesFromRecord(rendered) }), traces, stack),
]),
);
if (refs.length > 0) {
traces.push({
path,
extends: refs,
overrideKeys: Object.keys(overrides).sort(),
variables: deriveVariables({ ...localVariables, ...variablesFromRecord(result) }),
});
}
return result;
}
function stripCompositionFields(value: Record<string, unknown>): Record<string, unknown> {
return Object.fromEntries(Object.entries(value).filter(([key]) => !COMPOSITION_KEYS.has(key)));
}
function extendsRefs(value: unknown): string[] {
if (value === undefined) return [];
if (typeof value === "string" && value.trim().length > 0) return [value.trim()];
if (Array.isArray(value) && value.every((item) => typeof item === "string" && item.trim().length > 0)) {
return value.map((item) => item.trim());
}
throw new Error("extends must be a non-empty string or string array");
}
function renderValue(value: unknown, variables: Record<string, string>): unknown {
if (typeof value === "string") {
return value.replace(/\$\{([A-Za-z][A-Za-z0-9_]*)\}/gu, (match, name: string) => variables[name] ?? match);
}
if (Array.isArray(value)) return value.map((item) => renderValue(item, variables));
if (!isRecord(value)) return value;
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, renderValue(item, variables)]));
}
function renderObjectScalars(value: Record<string, unknown>, variables: Record<string, string>): Record<string, unknown> {
return Object.fromEntries(Object.entries(value).map(([key, item]) => [
key,
typeof item === "string" ? renderValue(item, variables) : item,
]));
}
function variablesFromRecord(value: unknown): Record<string, string> {
if (!isRecord(value)) return {};
const result: Record<string, string> = {};
if (typeof value.node === "string" && value.node.length > 0) result.NODE = value.node;
if (typeof value.lane === "string" && value.lane.length > 0) result.LANE = value.lane;
if (typeof value.id === "string" && value.id.length > 0) result.targetId = value.id;
return deriveVariables(result);
}
function deriveVariables(input: Record<string, string>): Record<string, string> {
const result = { ...input };
if (result.NODE !== undefined) result.nodeLower = result.NODE.toLowerCase();
if (result.LANE !== undefined) result.lane = result.LANE;
if (result.lane !== undefined && result.LANE === undefined) result.LANE = result.lane;
return result;
}
function stringRecord(value: unknown): Record<string, string> {
if (value === undefined) return {};
const raw = asRecord(value, "variables");
return Object.fromEntries(Object.entries(raw).map(([key, item]) => {
if (typeof item !== "string" || item.length === 0) throw new Error(`variables.${key} must be a non-empty string`);
return [key, item];
}));
}
function deepMerge(base: Record<string, unknown>, override: Record<string, unknown>): Record<string, unknown> {
const result: Record<string, unknown> = { ...base };
for (const [key, value] of Object.entries(override)) {
const existing = result[key];
result[key] = isRecord(existing) && isRecord(value) ? deepMerge(existing, value) : value;
}
return result;
}
function valueAtPath(root: unknown, ref: string): unknown {
let current: unknown = root;
for (const segment of ref.split(".")) {
if (!/^[A-Za-z0-9_-]+$/u.test(segment) || !isRecord(current)) return undefined;
current = current[segment];
}
return current;
}
function asRecord(value: unknown, path: string): Record<string, unknown> {
if (!isRecord(value)) throw new Error(`${path} must be an object`);
return value;
}
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value);
}