refactor: retire git mirror runtime
This commit is contained in:
@@ -1,83 +0,0 @@
|
||||
apiVersion: tekton.dev/v1
|
||||
kind: PipelineRun
|
||||
metadata:
|
||||
generateName: hwlab-jd01-v03-ci-poll-
|
||||
annotations:
|
||||
pipelinesascode.tekton.dev/on-event: "[push]"
|
||||
pipelinesascode.tekton.dev/on-target-branch: "[v0.3]"
|
||||
pipelinesascode.tekton.dev/on-cel-expression: "event == 'push' && target_branch == 'v0.3' && node == 'JD01'"
|
||||
pipelinesascode.tekton.dev/max-keep-runs: "8"
|
||||
pipelinesascode.tekton.dev/pipeline: "ci/pipelines/hwlab-jd01-v03-ci-image-publish.yaml"
|
||||
hwlab.pikastech.local/ci-contract: tekton-native-primitive-tasks
|
||||
hwlab.pikastech.local/download-profile: jd01-node-default
|
||||
hwlab.pikastech.local/gitops-branch: v0.3-gitops
|
||||
hwlab.pikastech.local/network-profile: jd01-node-ci-egress
|
||||
hwlab.pikastech.local/node: JD01
|
||||
hwlab.pikastech.local/policy: native-per-service-taskrun-image-publish
|
||||
hwlab.pikastech.local/runtime-path: deploy/gitops/node/jd01/runtime-v03
|
||||
hwlab.pikastech.local/source-branch: v0.3
|
||||
hwlab.pikastech.local/source-config: .tekton/hwlab-jd01-v03-pac.yaml
|
||||
labels:
|
||||
app.kubernetes.io/name: hwlab-jd01-v03-pac
|
||||
app.kubernetes.io/part-of: hwlab
|
||||
unidesk.ai/source-commit: "{{revision}}"
|
||||
hwlab.pikastech.local/gitops-target: v03
|
||||
hwlab.pikastech.local/source-commit: "{{revision}}"
|
||||
hwlab.pikastech.local/trigger: pipelines-as-code
|
||||
spec:
|
||||
timeouts:
|
||||
pipeline: 1h0m0s
|
||||
taskRunTemplate:
|
||||
serviceAccountName: hwlab-jd01-v03-tekton-runner
|
||||
podTemplate:
|
||||
hostNetwork: true
|
||||
dnsPolicy: ClusterFirstWithHostNet
|
||||
securityContext:
|
||||
fsGroup: 1000
|
||||
pipelineRef:
|
||||
name: hwlab-jd01-v03-ci-image-publish
|
||||
workspaces:
|
||||
- name: source
|
||||
volumeClaimTemplate:
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 8Gi
|
||||
- name: git-ssh
|
||||
secret:
|
||||
secretName: hwlab-git-ssh
|
||||
params:
|
||||
- name: git-url
|
||||
value: git@github.com:pikasTech/HWLAB.git
|
||||
- name: git-read-url
|
||||
value: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git
|
||||
- name: git-write-url
|
||||
value: http://git-mirror-write.devops-infra.svc.cluster.local:8080/pikasTech/HWLAB.git
|
||||
- name: source-branch
|
||||
value: v0.3
|
||||
- name: gitops-branch
|
||||
value: v0.3-gitops
|
||||
- name: lane
|
||||
value: v03
|
||||
- name: catalog-path
|
||||
value: deploy/artifact-catalog.jd01-v03.json
|
||||
- name: image-tag-mode
|
||||
value: full
|
||||
- name: runtime-path
|
||||
value: deploy/gitops/node/jd01/runtime-v03
|
||||
- name: source-commit
|
||||
value: "{{revision}}"
|
||||
- name: revision
|
||||
value: "{{revision}}"
|
||||
- name: registry-prefix
|
||||
value: 127.0.0.1:5000/hwlab
|
||||
- name: services
|
||||
value: hwlab-cloud-api,hwlab-workbench-runtime,hwlab-user-billing,hwlab-project-management,hwlab-cloud-web,hwlab-gateway,hwlab-edge-proxy,hwlab-agent-skills
|
||||
- name: base-image
|
||||
value: 127.0.0.1:5000/hwlab/hwlab-node20-base:20-bookworm-slim
|
||||
- name: build-cache-mode
|
||||
value: registry
|
||||
- name: runtime-ready-timeout-ms
|
||||
value: "60000"
|
||||
@@ -9,7 +9,7 @@ metadata:
|
||||
pipelinesascode.tekton.dev/on-cel-expression: "event == 'push' && target_branch == 'v0.3' && node == 'NC01'"
|
||||
pipelinesascode.tekton.dev/max-keep-runs: "8"
|
||||
unidesk.ai/owning-config-ref: "config/hwlab-node-lanes.yaml#lanes.v03.targets.NC01"
|
||||
unidesk.ai/effective-config-sha256: sha256:01b954f394174302b5ebce2de98a24d091be1c5922fbc188ef5af72ff1bb569c
|
||||
unidesk.ai/effective-config-sha256: sha256:f42181ba9c079806968bb8374967a2bc710c7a87b56030d512cc00c004be126b
|
||||
unidesk.ai/source-artifact-renderer: hwlab-runtime-lane
|
||||
unidesk.ai/source-artifact-mode: remote-pipeline-annotation
|
||||
pipelinesascode.tekton.dev/pipeline: ci/pipelines/hwlab-nc01-v03-ci-image-publish.yaml
|
||||
@@ -52,16 +52,23 @@ spec:
|
||||
resources:
|
||||
requests:
|
||||
storage: 8Gi
|
||||
- name: git-ssh
|
||||
- name: gitea-auth
|
||||
secret:
|
||||
secretName: hwlab-git-ssh
|
||||
secretName: pac-gitea-hwlab-nc01-v03
|
||||
items:
|
||||
- key: token
|
||||
path: token
|
||||
params:
|
||||
- name: git-url
|
||||
value: "{{ repo_url }}"
|
||||
- name: git-read-url
|
||||
value: "{{ git_read_url }}"
|
||||
- name: gitops-read-url
|
||||
value: "{{ gitops_read_url }}"
|
||||
- name: git-write-url
|
||||
value: "{{ git_write_url }}"
|
||||
- name: gitops-username
|
||||
value: "{{ gitops_username }}"
|
||||
- name: source-branch
|
||||
value: "{{ source_branch }}"
|
||||
- name: gitops-branch
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+30
-76
@@ -94,43 +94,20 @@ lanes:
|
||||
node: G14
|
||||
sourceBranch: v0.2
|
||||
gitopsBranch: v0.2-gitops
|
||||
gitMirror:
|
||||
namespace: devops-infra
|
||||
serviceReadName: git-mirror-http
|
||||
serviceWriteName: git-mirror-write
|
||||
cachePvcName: hwlab-git-mirror-cache
|
||||
cachePvcStorage: 20Gi
|
||||
cacheHostPath: /var/lib/rancher/k3s/storage/hwlab-d601-v02-git-mirror-cache
|
||||
servicePort: 8080
|
||||
syncConfigMapName: git-mirror-sync-script
|
||||
egressProxy:
|
||||
mode: node-global
|
||||
required: true
|
||||
namespace: platform-infra
|
||||
serviceName: sub2api-egress-proxy
|
||||
port: 10808
|
||||
clientName: d601-global-proxy
|
||||
noProxy:
|
||||
- localhost
|
||||
- 127.0.0.1
|
||||
- ::1
|
||||
- 127.0.0.1:5000
|
||||
- localhost:5000
|
||||
- .svc
|
||||
- .svc.cluster.local
|
||||
- .cluster.local
|
||||
- kubernetes
|
||||
- kubernetes.default
|
||||
- kubernetes.default.svc
|
||||
- 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
|
||||
- 82.156.23.220
|
||||
- 74.48.78.17
|
||||
- hyueapi.com
|
||||
- .hyueapi.com
|
||||
egressProxy:
|
||||
required: true
|
||||
namespace: platform-infra
|
||||
serviceName: sub2api-egress-proxy
|
||||
port: 10808
|
||||
noProxy:
|
||||
- localhost
|
||||
- 127.0.0.1
|
||||
- ::1
|
||||
- .svc
|
||||
- .svc.cluster.local
|
||||
- .cluster.local
|
||||
- hyueapi.com
|
||||
- .hyueapi.com
|
||||
namespace: hwlab-v02
|
||||
endpoint: https://hwlab.74-48-78-17.nip.io
|
||||
publicEndpoints:
|
||||
@@ -277,49 +254,26 @@ lanes:
|
||||
AGENTRUN_API_KEY: secretRef:hwlab-v02-master-server-admin-api-key/api-key
|
||||
HWLAB_CODE_AGENT_AGENTRUN_RUNNER_NAMESPACE: agentrun-v01
|
||||
HWLAB_CODE_AGENT_AGENTRUN_SECRET_NAMESPACE: agentrun-v01
|
||||
HWLAB_CODE_AGENT_AGENTRUN_REPO_URL: http://git-mirror-http.devops-infra.svc.cluster.local/pikasTech/HWLAB.git
|
||||
HWLAB_CODE_AGENT_AGENTRUN_REPO_URL: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git
|
||||
v03:
|
||||
name: v0.3
|
||||
node: G14
|
||||
sourceBranch: v0.3
|
||||
gitopsBranch: v0.3-gitops
|
||||
gitMirror:
|
||||
namespace: devops-infra
|
||||
serviceReadName: git-mirror-http
|
||||
serviceWriteName: git-mirror-write
|
||||
cachePvcName: hwlab-git-mirror-cache
|
||||
cachePvcStorage: 20Gi
|
||||
cacheHostPath: /var/lib/rancher/k3s/storage/hwlab-d601-v03-git-mirror-cache
|
||||
servicePort: 8080
|
||||
syncConfigMapName: git-mirror-sync-script
|
||||
egressProxy:
|
||||
mode: node-global
|
||||
required: true
|
||||
namespace: platform-infra
|
||||
serviceName: sub2api-egress-proxy
|
||||
port: 10808
|
||||
clientName: d601-global-proxy
|
||||
noProxy:
|
||||
- localhost
|
||||
- 127.0.0.1
|
||||
- ::1
|
||||
- 127.0.0.1:5000
|
||||
- localhost:5000
|
||||
- .svc
|
||||
- .svc.cluster.local
|
||||
- .cluster.local
|
||||
- kubernetes
|
||||
- kubernetes.default
|
||||
- kubernetes.default.svc
|
||||
- 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
|
||||
- 82.156.23.220
|
||||
- 74.48.78.17
|
||||
- hyueapi.com
|
||||
- .hyueapi.com
|
||||
egressProxy:
|
||||
required: true
|
||||
namespace: platform-infra
|
||||
serviceName: sub2api-egress-proxy
|
||||
port: 10808
|
||||
noProxy:
|
||||
- localhost
|
||||
- 127.0.0.1
|
||||
- ::1
|
||||
- .svc
|
||||
- .svc.cluster.local
|
||||
- .cluster.local
|
||||
- hyueapi.com
|
||||
- .hyueapi.com
|
||||
namespace: hwlab-v03
|
||||
endpoint: https://hwlab.pikapython.com
|
||||
publicEndpoints:
|
||||
@@ -1319,7 +1273,7 @@ lanes:
|
||||
sourceBranch: release
|
||||
gitopsBranch: release-gitops
|
||||
gitReadUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git
|
||||
gitWriteUrl: http://git-mirror-write.devops-infra.svc.cluster.local:8080/pikasTech/HWLAB.git
|
||||
gitWriteUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git
|
||||
artifactCatalog: deploy/artifact-catalog.nc01-production.json
|
||||
runtimePath: runtime-production
|
||||
namespace: hwlab-production
|
||||
|
||||
@@ -4,7 +4,7 @@ set -eu
|
||||
export HWLAB_SERVICE_ID="hwlab-agent-skills"
|
||||
export HWLAB_ARTIFACT_KIND="skills-bundle"
|
||||
export HWLAB_SERVICE_ENTRYPOINT="skills/hwlab-agent-runtime/SKILL.md"
|
||||
export HWLAB_RUNTIME_MODE="${HWLAB_RUNTIME_MODE:-env-reuse-git-mirror-checkout}"
|
||||
export HWLAB_RUNTIME_MODE="${HWLAB_RUNTIME_MODE:-env-reuse-gitea-checkout}"
|
||||
export HWLAB_COMMIT_ID="${HWLAB_BOOT_COMMIT:?HWLAB_BOOT_COMMIT is required}"
|
||||
export HWLAB_REVISION="${HWLAB_BOOT_COMMIT}"
|
||||
export HWLAB_SKILLS_COMMIT_ID="${HWLAB_SKILLS_COMMIT_ID:-${HWLAB_BOOT_COMMIT}}"
|
||||
@@ -81,11 +81,11 @@ function healthPayload() {
|
||||
environment,
|
||||
status: "ok",
|
||||
artifactKind: "skills-bundle",
|
||||
runtimeMode: process.env.HWLAB_RUNTIME_MODE || "env-reuse-git-mirror-checkout",
|
||||
runtimeMode: process.env.HWLAB_RUNTIME_MODE || "env-reuse-gitea-checkout",
|
||||
revision: process.env.HWLAB_REVISION || commitId,
|
||||
commit: {
|
||||
id: commitId,
|
||||
source: process.env.HWLAB_BUILD_SOURCE || "git-mirror-runtime-checkout"
|
||||
source: process.env.HWLAB_BUILD_SOURCE || "gitea-runtime-checkout"
|
||||
},
|
||||
image: {
|
||||
reference: imageReference,
|
||||
|
||||
@@ -4,7 +4,7 @@ set -eu
|
||||
export HWLAB_SERVICE_ID="hwlab-cloud-api"
|
||||
export HWLAB_ARTIFACT_KIND="bun-command"
|
||||
export HWLAB_SERVICE_ENTRYPOINT="cmd/hwlab-cloud-api/main.ts"
|
||||
export HWLAB_RUNTIME_MODE="${HWLAB_RUNTIME_MODE:-env-reuse-git-mirror-checkout}"
|
||||
export HWLAB_RUNTIME_MODE="${HWLAB_RUNTIME_MODE:-env-reuse-gitea-checkout}"
|
||||
export HWLAB_COMMIT_ID="${HWLAB_BOOT_COMMIT:?HWLAB_BOOT_COMMIT is required}"
|
||||
export HWLAB_REVISION="${HWLAB_BOOT_COMMIT}"
|
||||
export HWLAB_IMAGE="${HWLAB_ENVIRONMENT_IMAGE:-${HWLAB_IMAGE:-}}"
|
||||
@@ -13,7 +13,7 @@ export PORT="${PORT:-${HWLAB_CLOUD_API_PORT:-${HWLAB_PORT:-6667}}}"
|
||||
export HWLAB_PORT="$PORT"
|
||||
export HWLAB_CLOUD_API_PORT="$PORT"
|
||||
export HWLAB_CODE_AGENT_AGENTRUN_SOURCE_COMMIT="${HWLAB_CODE_AGENT_AGENTRUN_SOURCE_COMMIT:-${HWLAB_BOOT_COMMIT}}"
|
||||
export HWLAB_CODE_AGENT_AGENTRUN_REPO_URL="${HWLAB_CODE_AGENT_AGENTRUN_REPO_URL:-${HWLAB_BOOT_READ_URL:-http://git-mirror-http.devops-infra.svc.cluster.local/pikasTech/HWLAB.git}}"
|
||||
export HWLAB_CODE_AGENT_AGENTRUN_REPO_URL="${HWLAB_CODE_AGENT_AGENTRUN_REPO_URL:-${HWLAB_BOOT_READ_URL:-http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git}}"
|
||||
export HWLAB_CODE_AGENT_WORKSPACE="${HWLAB_CODE_AGENT_WORKSPACE:-$PWD}"
|
||||
export HWLAB_CODE_AGENT_CODEX_WORKSPACE="${HWLAB_CODE_AGENT_CODEX_WORKSPACE:-$HWLAB_CODE_AGENT_WORKSPACE}"
|
||||
export CODEX_HOME="${CODEX_HOME:-/codex-home}"
|
||||
|
||||
@@ -4,7 +4,7 @@ set -eu
|
||||
export HWLAB_SERVICE_ID="hwlab-cloud-web"
|
||||
export HWLAB_ARTIFACT_KIND="cloud-web"
|
||||
export HWLAB_SERVICE_ENTRYPOINT="web/hwlab-cloud-web/index.html"
|
||||
export HWLAB_RUNTIME_MODE="${HWLAB_RUNTIME_MODE:-env-reuse-git-mirror-checkout}"
|
||||
export HWLAB_RUNTIME_MODE="${HWLAB_RUNTIME_MODE:-env-reuse-gitea-checkout}"
|
||||
export HWLAB_COMMIT_ID="${HWLAB_BOOT_COMMIT:?HWLAB_BOOT_COMMIT is required}"
|
||||
export HWLAB_REVISION="${HWLAB_BOOT_COMMIT}"
|
||||
export HWLAB_IMAGE="${HWLAB_ENVIRONMENT_IMAGE:-${HWLAB_IMAGE:-}}"
|
||||
@@ -71,11 +71,11 @@ function healthPayload() {
|
||||
environment,
|
||||
status: "ok",
|
||||
artifactKind: "cloud-web",
|
||||
runtimeMode: process.env.HWLAB_RUNTIME_MODE || "env-reuse-git-mirror-checkout",
|
||||
runtimeMode: process.env.HWLAB_RUNTIME_MODE || "env-reuse-gitea-checkout",
|
||||
revision: process.env.HWLAB_REVISION || commitId,
|
||||
commit: {
|
||||
id: commitId,
|
||||
source: process.env.HWLAB_BUILD_SOURCE || "git-mirror-runtime-checkout"
|
||||
source: process.env.HWLAB_BUILD_SOURCE || "gitea-runtime-checkout"
|
||||
},
|
||||
image: {
|
||||
reference: imageReference,
|
||||
|
||||
@@ -4,7 +4,7 @@ set -eu
|
||||
export HWLAB_SERVICE_ID="hwlab-codex-api-responses-forwarder"
|
||||
export HWLAB_ARTIFACT_KIND="bun-command"
|
||||
export HWLAB_SERVICE_ENTRYPOINT="cmd/hwlab-codex-api-responses-forwarder/main.ts"
|
||||
export HWLAB_RUNTIME_MODE="${HWLAB_RUNTIME_MODE:-env-reuse-git-mirror-checkout}"
|
||||
export HWLAB_RUNTIME_MODE="${HWLAB_RUNTIME_MODE:-env-reuse-gitea-checkout}"
|
||||
export HWLAB_COMMIT_ID="${HWLAB_BOOT_COMMIT:?HWLAB_BOOT_COMMIT is required}"
|
||||
export HWLAB_REVISION="${HWLAB_BOOT_COMMIT}"
|
||||
export HWLAB_IMAGE="${HWLAB_ENVIRONMENT_IMAGE:-${HWLAB_IMAGE:-}}"
|
||||
|
||||
@@ -4,7 +4,7 @@ set -eu
|
||||
export HWLAB_SERVICE_ID="hwlab-deepseek-responses-bridge"
|
||||
export HWLAB_ARTIFACT_KIND="bun-command"
|
||||
export HWLAB_SERVICE_ENTRYPOINT="cmd/hwlab-deepseek-responses-bridge/main.ts"
|
||||
export HWLAB_RUNTIME_MODE="${HWLAB_RUNTIME_MODE:-env-reuse-git-mirror-checkout}"
|
||||
export HWLAB_RUNTIME_MODE="${HWLAB_RUNTIME_MODE:-env-reuse-gitea-checkout}"
|
||||
export HWLAB_COMMIT_ID="${HWLAB_BOOT_COMMIT:?HWLAB_BOOT_COMMIT is required}"
|
||||
export HWLAB_REVISION="${HWLAB_BOOT_COMMIT}"
|
||||
export HWLAB_IMAGE="${HWLAB_ENVIRONMENT_IMAGE:-${HWLAB_IMAGE:-}}"
|
||||
|
||||
@@ -4,7 +4,7 @@ set -eu
|
||||
export HWLAB_SERVICE_ID="hwlab-edge-proxy"
|
||||
export HWLAB_ARTIFACT_KIND="node-command"
|
||||
export HWLAB_SERVICE_ENTRYPOINT="cmd/hwlab-edge-proxy/main.mjs"
|
||||
export HWLAB_RUNTIME_MODE="${HWLAB_RUNTIME_MODE:-env-reuse-git-mirror-checkout}"
|
||||
export HWLAB_RUNTIME_MODE="${HWLAB_RUNTIME_MODE:-env-reuse-gitea-checkout}"
|
||||
export HWLAB_COMMIT_ID="${HWLAB_BOOT_COMMIT:?HWLAB_BOOT_COMMIT is required}"
|
||||
export HWLAB_REVISION="${HWLAB_BOOT_COMMIT}"
|
||||
export HWLAB_IMAGE="${HWLAB_ENVIRONMENT_IMAGE:-${HWLAB_IMAGE:-}}"
|
||||
|
||||
@@ -4,7 +4,7 @@ set -eu
|
||||
export HWLAB_SERVICE_ID="hwlab-gateway"
|
||||
export HWLAB_ARTIFACT_KIND="bun-command"
|
||||
export HWLAB_SERVICE_ENTRYPOINT="cmd/hwlab-gateway/main.ts"
|
||||
export HWLAB_RUNTIME_MODE="${HWLAB_RUNTIME_MODE:-env-reuse-git-mirror-checkout}"
|
||||
export HWLAB_RUNTIME_MODE="${HWLAB_RUNTIME_MODE:-env-reuse-gitea-checkout}"
|
||||
export HWLAB_COMMIT_ID="${HWLAB_BOOT_COMMIT:?HWLAB_BOOT_COMMIT is required}"
|
||||
export HWLAB_REVISION="${HWLAB_BOOT_COMMIT}"
|
||||
export HWLAB_IMAGE="${HWLAB_ENVIRONMENT_IMAGE:-${HWLAB_IMAGE:-}}"
|
||||
|
||||
@@ -4,7 +4,7 @@ set -eu
|
||||
export HWLAB_SERVICE_ID="hwlab-project-management"
|
||||
export HWLAB_ARTIFACT_KIND="bun-command"
|
||||
export HWLAB_SERVICE_ENTRYPOINT="cmd/hwlab-project-management/main.ts"
|
||||
export HWLAB_RUNTIME_MODE="${HWLAB_RUNTIME_MODE:-env-reuse-git-mirror-checkout}"
|
||||
export HWLAB_RUNTIME_MODE="${HWLAB_RUNTIME_MODE:-env-reuse-gitea-checkout}"
|
||||
export HWLAB_COMMIT_ID="${HWLAB_BOOT_COMMIT:?HWLAB_BOOT_COMMIT is required}"
|
||||
export HWLAB_REVISION="${HWLAB_BOOT_COMMIT}"
|
||||
export HWLAB_IMAGE="${HWLAB_ENVIRONMENT_IMAGE:-${HWLAB_IMAGE:-}}"
|
||||
|
||||
@@ -17,7 +17,7 @@ if (
|
||||
bootRef.includes("..")
|
||||
) fail("HWLAB_BOOT_REF must be a safe branch or ref name");
|
||||
|
||||
const readUrl = process.env.HWLAB_BOOT_READ_URL || mirrorReadUrl(bootRepo);
|
||||
const readUrl = process.env.HWLAB_BOOT_READ_URL || giteaReadUrl(bootRepo);
|
||||
process.env.HWLAB_BUN_COMMAND ||= process.execPath;
|
||||
mkdirSync(path.dirname(checkoutDir), { recursive: true });
|
||||
rmSync(checkoutDir, { recursive: true, force: true });
|
||||
@@ -37,11 +37,11 @@ function requiredEnv(name: string): string {
|
||||
return value;
|
||||
}
|
||||
|
||||
function mirrorReadUrl(repo: string): string {
|
||||
function giteaReadUrl(repo: string): string {
|
||||
if (/github\.com[:/]pikasTech\/HWLAB(?:\.git)?$/u.test(repo)) {
|
||||
return "http://git-mirror-http.devops-infra.svc.cluster.local/pikasTech/HWLAB.git";
|
||||
return "http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git";
|
||||
}
|
||||
fail("no mirror resolver for HWLAB_BOOT_REPO; refusing direct runtime GitHub fallback");
|
||||
fail("no Gitea resolver for HWLAB_BOOT_REPO; refusing direct runtime GitHub fallback");
|
||||
}
|
||||
|
||||
function linkNodeModules(): void {
|
||||
|
||||
@@ -14,7 +14,7 @@ if (!/^[A-Za-z0-9._/-]+$/u.test(bootRef) || bootRef.startsWith("-") || bootRef.i
|
||||
fail("HWLAB_BOOT_REF must be a safe branch or ref name");
|
||||
}
|
||||
|
||||
const readUrl = process.env.HWLAB_BOOT_READ_URL || mirrorReadUrl(bootRepo);
|
||||
const readUrl = process.env.HWLAB_BOOT_READ_URL || giteaReadUrl(bootRepo);
|
||||
mkdirSync(path.dirname(checkoutDir), { recursive: true });
|
||||
rmSync(checkoutDir, { recursive: true, force: true });
|
||||
// Go env images avoid npm dependency installation; Go modules stay in Docker/BuildKit layers.
|
||||
@@ -31,11 +31,11 @@ function requiredEnv(name) {
|
||||
return value;
|
||||
}
|
||||
|
||||
function mirrorReadUrl(repo) {
|
||||
function giteaReadUrl(repo) {
|
||||
if (/github\.com[:/]pikasTech\/HWLAB(?:\.git)?$/u.test(repo)) {
|
||||
return "http://git-mirror-http.devops-infra.svc.cluster.local/pikasTech/HWLAB.git";
|
||||
return "http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git";
|
||||
}
|
||||
fail("no mirror resolver for HWLAB_BOOT_REPO; refusing direct runtime GitHub fallback");
|
||||
fail("no Gitea resolver for HWLAB_BOOT_REPO; refusing direct runtime GitHub fallback");
|
||||
}
|
||||
|
||||
function run(command, args, cwd, options = {}) {
|
||||
|
||||
+12
-12
@@ -7,7 +7,7 @@ spec:
|
||||
envArtifactGroups:
|
||||
hwlab-go-runtime-env:
|
||||
enabled: true
|
||||
mode: env-reuse-git-mirror-checkout
|
||||
mode: env-reuse-gitea-checkout
|
||||
buildService: hwlab-user-billing
|
||||
imageRepository: hwlab-go-runtime-env
|
||||
cacheRepository: cache/hwlab-go-runtime-env
|
||||
@@ -16,7 +16,7 @@ spec:
|
||||
- hwlab-workbench-runtime
|
||||
hwlab-ts-runtime-env:
|
||||
enabled: true
|
||||
mode: env-reuse-git-mirror-checkout
|
||||
mode: env-reuse-gitea-checkout
|
||||
buildService: hwlab-cloud-api
|
||||
imageRepository: hwlab-ts-runtime-env
|
||||
cacheRepository: cache/hwlab-ts-runtime-env
|
||||
@@ -55,7 +55,7 @@ spec:
|
||||
- internal/dev-entrypoint/artifact-runtime.mjs
|
||||
envReuse:
|
||||
enabled: true
|
||||
mode: env-reuse-git-mirror-checkout
|
||||
mode: env-reuse-gitea-checkout
|
||||
nodeDepsPath: /opt/hwlab-env/node_modules
|
||||
envIdentityFiles:
|
||||
- package.json
|
||||
@@ -81,7 +81,7 @@ spec:
|
||||
- internal/dev-entrypoint/artifact-runtime.mjs
|
||||
envReuse:
|
||||
enabled: true
|
||||
mode: env-reuse-git-mirror-checkout
|
||||
mode: env-reuse-gitea-checkout
|
||||
nodeDepsPath: /opt/hwlab-env/node_modules
|
||||
envIdentityFiles:
|
||||
- go.mod
|
||||
@@ -108,7 +108,7 @@ spec:
|
||||
- internal/dev-entrypoint/artifact-runtime.mjs
|
||||
envReuse:
|
||||
enabled: true
|
||||
mode: env-reuse-git-mirror-checkout
|
||||
mode: env-reuse-gitea-checkout
|
||||
nodeDepsPath: /opt/hwlab-env/node_modules
|
||||
envIdentityFiles:
|
||||
- go.mod
|
||||
@@ -133,7 +133,7 @@ spec:
|
||||
- internal/dev-entrypoint/artifact-runtime.mjs
|
||||
envReuse:
|
||||
enabled: true
|
||||
mode: env-reuse-git-mirror-checkout
|
||||
mode: env-reuse-gitea-checkout
|
||||
nodeDepsPath: /opt/hwlab-env/node_modules
|
||||
envIdentityFiles:
|
||||
- package.json
|
||||
@@ -157,7 +157,7 @@ spec:
|
||||
- internal/dev-entrypoint/artifact-runtime.mjs
|
||||
envReuse:
|
||||
enabled: true
|
||||
mode: env-reuse-git-mirror-checkout
|
||||
mode: env-reuse-gitea-checkout
|
||||
nodeDepsPath: /opt/hwlab-env/node_modules
|
||||
envIdentityFiles:
|
||||
- package.json
|
||||
@@ -180,7 +180,7 @@ spec:
|
||||
- internal/dev-entrypoint/artifact-runtime.mjs
|
||||
envReuse:
|
||||
enabled: true
|
||||
mode: env-reuse-git-mirror-checkout
|
||||
mode: env-reuse-gitea-checkout
|
||||
nodeDepsPath: /opt/hwlab-env/node_modules
|
||||
envIdentityFiles:
|
||||
- package.json
|
||||
@@ -207,7 +207,7 @@ spec:
|
||||
- internal/dev-entrypoint/artifact-runtime.mjs
|
||||
envReuse:
|
||||
enabled: true
|
||||
mode: env-reuse-git-mirror-checkout
|
||||
mode: env-reuse-gitea-checkout
|
||||
nodeDepsPath: /opt/hwlab-env/node_modules
|
||||
envIdentityFiles:
|
||||
- package.json
|
||||
@@ -230,7 +230,7 @@ spec:
|
||||
- internal/dev-entrypoint/artifact-runtime.mjs
|
||||
envReuse:
|
||||
enabled: true
|
||||
mode: env-reuse-git-mirror-checkout
|
||||
mode: env-reuse-gitea-checkout
|
||||
nodeDepsPath: /opt/hwlab-env/node_modules
|
||||
envIdentityFiles:
|
||||
- package.json
|
||||
@@ -253,7 +253,7 @@ spec:
|
||||
- internal/dev-entrypoint/artifact-runtime.mjs
|
||||
envReuse:
|
||||
enabled: true
|
||||
mode: env-reuse-git-mirror-checkout
|
||||
mode: env-reuse-gitea-checkout
|
||||
nodeDepsPath: /opt/hwlab-env/node_modules
|
||||
envIdentityFiles:
|
||||
- package.json
|
||||
@@ -275,7 +275,7 @@ spec:
|
||||
- internal/dev-entrypoint/artifact-runtime.mjs
|
||||
envReuse:
|
||||
enabled: true
|
||||
mode: env-reuse-git-mirror-checkout
|
||||
mode: env-reuse-gitea-checkout
|
||||
nodeDepsPath: /opt/hwlab-env/node_modules
|
||||
envIdentityFiles:
|
||||
- package.json
|
||||
|
||||
@@ -32,7 +32,7 @@ const defaultRegistryPrefix =
|
||||
const defaultBaseImage = process.env.HWLAB_DEV_BASE_IMAGE || null;
|
||||
const defaultReportPath = tempReportPath("dev-artifacts.json");
|
||||
const buildBackend = "buildkit";
|
||||
const v02EnvReuseRuntimeMode = "env-reuse-git-mirror-checkout";
|
||||
const v02EnvReuseRuntimeMode = "env-reuse-gitea-checkout";
|
||||
const defaultBuildkitCommand = process.env.HWLAB_BUILDKIT_BUILDCTL || "buildctl-daemonless.sh";
|
||||
const defaultBuildkitAddr = process.env.HWLAB_BUILDKIT_ADDR || null;
|
||||
const defaultBuildCacheMode = process.env.HWLAB_BUILDKIT_CACHE_MODE || "registry";
|
||||
@@ -1028,7 +1028,7 @@ function envReuseDockerfile(baseImage, labels = [], recipe, service = null) {
|
||||
: `COPY ${normalizedRecipe.launcherPath} /usr/local/bin/hwlab-env-reuse-launcher.ts`,
|
||||
`RUN ${stepTimingHelpers}; timed_stage "env-readiness" sh -c ${shellQuote(readinessScript)}`,
|
||||
...labels.map(([name, value]) => `LABEL ${name}=${dockerfileQuote(value)}`),
|
||||
"ENV HWLAB_RUNTIME_MODE=env-reuse-git-mirror-checkout",
|
||||
"ENV HWLAB_RUNTIME_MODE=env-reuse-gitea-checkout",
|
||||
...(goCacheEnabled ? [] : [`ENV HWLAB_RUNTIME_NODE_MODULES=${normalizedRecipe.runtimeNodeModulesPath}`]),
|
||||
...goEnv,
|
||||
"ENV PATH=/usr/local/bin:$PATH",
|
||||
|
||||
+1
-1
@@ -97,7 +97,7 @@ function tryCreateNoDepsPlan(options) {
|
||||
affected: false,
|
||||
buildRequired: false,
|
||||
skipImageBuild: true,
|
||||
runtimeMode: "env-reuse-git-mirror-checkout",
|
||||
runtimeMode: "env-reuse-gitea-checkout",
|
||||
envReuse: true,
|
||||
envChanged: false,
|
||||
codeChanged: false,
|
||||
|
||||
+12
-12
@@ -505,7 +505,7 @@ test("v02 planner rolls cloud-api service code changes without rebuilding servic
|
||||
});
|
||||
const cloudApi = plan.services.find((service) => service.serviceId === "hwlab-cloud-api");
|
||||
assert.equal(cloudApi.affected, true);
|
||||
assert.equal(cloudApi.runtimeMode, "env-reuse-git-mirror-checkout");
|
||||
assert.equal(cloudApi.runtimeMode, "env-reuse-gitea-checkout");
|
||||
assert.equal(cloudApi.envChanged, false);
|
||||
assert.equal(cloudApi.codeChanged, true);
|
||||
assert.equal(cloudApi.buildRequired, false);
|
||||
@@ -818,7 +818,7 @@ test("artifact publish ignores stale external reports for envreuse services that
|
||||
ciCdPlan: {},
|
||||
services: [{
|
||||
serviceId: "hwlab-cloud-web",
|
||||
runtimeMode: "env-reuse-git-mirror-checkout",
|
||||
runtimeMode: "env-reuse-gitea-checkout",
|
||||
envReuse: true,
|
||||
affected: false,
|
||||
buildRequired: false,
|
||||
@@ -846,7 +846,7 @@ test("artifact publish ignores stale external reports for envreuse services that
|
||||
imageTag: "env-old",
|
||||
digest,
|
||||
repositoryDigest: `127.0.0.1:5000/hwlab/hwlab-cloud-web-env@${digest}`,
|
||||
runtimeMode: "env-reuse-git-mirror-checkout",
|
||||
runtimeMode: "env-reuse-gitea-checkout",
|
||||
envReuse: true
|
||||
}]
|
||||
}
|
||||
@@ -926,7 +926,7 @@ test("artifact publish accepts stale reused envreuse external reports for unchan
|
||||
ciCdPlan: {},
|
||||
services: [{
|
||||
serviceId: "hwlab-cloud-web",
|
||||
runtimeMode: "env-reuse-git-mirror-checkout",
|
||||
runtimeMode: "env-reuse-gitea-checkout",
|
||||
envReuse: true,
|
||||
affected: false,
|
||||
ciAffected: false,
|
||||
@@ -955,7 +955,7 @@ test("artifact publish accepts stale reused envreuse external reports for unchan
|
||||
imageTag: "env-stable",
|
||||
digest,
|
||||
repositoryDigest: `${image}@${digest}`,
|
||||
runtimeMode: "env-reuse-git-mirror-checkout",
|
||||
runtimeMode: "env-reuse-gitea-checkout",
|
||||
envReuse: true,
|
||||
affected: false,
|
||||
ciAffected: false,
|
||||
@@ -1290,7 +1290,7 @@ test("v02 planner marks cloud-web code-only change as env reuse rollout", async
|
||||
services: ["hwlab-cloud-web"]
|
||||
});
|
||||
const cloudWeb = plan.services.find((service) => service.serviceId === "hwlab-cloud-web");
|
||||
assert.equal(cloudWeb.runtimeMode, "env-reuse-git-mirror-checkout");
|
||||
assert.equal(cloudWeb.runtimeMode, "env-reuse-gitea-checkout");
|
||||
assert.equal(cloudWeb.envChanged, false);
|
||||
assert.equal(cloudWeb.codeChanged, true);
|
||||
assert.equal(cloudWeb.buildRequired, false);
|
||||
@@ -1348,7 +1348,7 @@ test("v02 planner enables env reuse for all retained runtime services", async ()
|
||||
assert.deepEqual(plan.buildServices, []);
|
||||
assert.equal(plan.imageBuildRequired, false);
|
||||
for (const service of plan.services) {
|
||||
assert.equal(service.runtimeMode, "env-reuse-git-mirror-checkout", service.serviceId);
|
||||
assert.equal(service.runtimeMode, "env-reuse-gitea-checkout", service.serviceId);
|
||||
assert.equal(service.envReuse, true, service.serviceId);
|
||||
assert.equal(service.envChanged, false, service.serviceId);
|
||||
assert.equal(service.codeChanged, true, service.serviceId);
|
||||
@@ -1541,7 +1541,7 @@ test("v03 planner reads env reuse declarations and catalog from v03 lane config"
|
||||
assert.deepEqual(plan.compatibility.envReuseServiceIds, ["hwlab-cloud-api", "hwlab-cloud-web"]);
|
||||
assert.equal(plan.services.every((service) => service.envReuseRecipe.downloadStack.npmFetchTimeoutMs === 300000), true);
|
||||
for (const service of plan.services) {
|
||||
assert.equal(service.runtimeMode, "env-reuse-git-mirror-checkout", service.serviceId);
|
||||
assert.equal(service.runtimeMode, "env-reuse-gitea-checkout", service.serviceId);
|
||||
assert.equal(service.envReuse, true, service.serviceId);
|
||||
assert.equal(service.bootRepo, "git@github.com:pikasTech/HWLAB.git", service.serviceId);
|
||||
assert.equal(service.bootSh, `deploy/runtime/boot/${service.serviceId}.sh`, service.serviceId);
|
||||
@@ -1565,7 +1565,7 @@ test("v03 TaskTree API and worker share one TypeScript environment artifact", as
|
||||
assert.equal(group.services?.includes(serviceId), true, `${serviceId} shared environment membership`);
|
||||
assert.deepEqual(services[serviceId]?.runtimeReuse?.envIdentity?.paths, expectedEnvIdentity, `${serviceId} runtime env identity`);
|
||||
assert.deepEqual(services[serviceId]?.envReuse?.envIdentityFiles, expectedEnvIdentity, `${serviceId} env reuse identity`);
|
||||
assert.equal(services[serviceId]?.envReuse?.mode, "env-reuse-git-mirror-checkout", `${serviceId} runtime mode`);
|
||||
assert.equal(services[serviceId]?.envReuse?.mode, "env-reuse-gitea-checkout", `${serviceId} runtime mode`);
|
||||
}
|
||||
assert.deepEqual(services["hwlab-tasktree-api"].runtimeReuse.codeIdentity.paths, [
|
||||
"cmd/hwlab-tasktree-api",
|
||||
@@ -1874,7 +1874,7 @@ async function addGoEnvReuseFixture(repo) {
|
||||
envArtifactGroups: {
|
||||
"hwlab-go-runtime-env": {
|
||||
enabled: true,
|
||||
mode: "env-reuse-git-mirror-checkout",
|
||||
mode: "env-reuse-gitea-checkout",
|
||||
buildService: "hwlab-user-billing",
|
||||
imageRepository: "hwlab-go-runtime-env",
|
||||
cacheRepository: "cache/hwlab-go-runtime-env",
|
||||
@@ -1889,7 +1889,7 @@ async function addGoEnvReuseFixture(repo) {
|
||||
},
|
||||
envReuse: {
|
||||
enabled: true,
|
||||
mode: "env-reuse-git-mirror-checkout",
|
||||
mode: "env-reuse-gitea-checkout",
|
||||
envIdentityFiles: ["go.mod", "go.sum", "deploy/runtime/launcher/hwlab-go-env-reuse-launcher.mjs"]
|
||||
}
|
||||
}]))
|
||||
@@ -2048,7 +2048,7 @@ function createCatalogFixture(mode, options = {}) {
|
||||
componentInputHash: options.cloudApiComponentInputHash ?? options.componentInputHashes?.[serviceId]
|
||||
} : {}),
|
||||
...(envReuseCatalogServiceIds.has(serviceId) ? {
|
||||
runtimeMode: "env-reuse-git-mirror-checkout",
|
||||
runtimeMode: "env-reuse-gitea-checkout",
|
||||
envReuse: true,
|
||||
environmentImage: `127.0.0.1:5000/hwlab/${serviceId}-env:env-abc1234`,
|
||||
environmentDigest: digest,
|
||||
|
||||
@@ -47,10 +47,7 @@ import {
|
||||
usage,
|
||||
workbenchRuntimeRedisConfigForProfile
|
||||
} from "./src/gitops-render/core.mjs";
|
||||
import {
|
||||
devopsInfraGitMirrorManifest,
|
||||
registryManifest
|
||||
} from "./src/gitops-render/infra-manifests.mjs";
|
||||
import { registryManifest } from "./src/gitops-render/infra-manifests.mjs";
|
||||
import {
|
||||
argoApplication,
|
||||
argoProject,
|
||||
@@ -228,7 +225,6 @@ async function plannedFiles(args) {
|
||||
putJson("source.json", sourceDescriptor);
|
||||
putText("README.md", readme({ source, args, deploy }));
|
||||
putJson("registry/registry.yaml", registryManifest());
|
||||
if (isRuntimeLane(args.lane)) putJson("devops-infra/git-mirror.yaml", devopsInfraGitMirrorManifest(args, deploy));
|
||||
putJson(`${settings.tektonDir}/rbac.yaml`, tektonRbac(args, deploy));
|
||||
putJson(`${settings.tektonDir}/tasks.yaml`, { apiVersion: "v1", kind: "List", items: tektonTasks(args, deploy) });
|
||||
putJson(`${settings.tektonDir}/pipeline.yaml`, tektonPipeline(args, deploy));
|
||||
|
||||
@@ -180,11 +180,11 @@ async function runtimeNoopDecision(gitopsPromoteScript, { oldRuntime, newRuntime
|
||||
}
|
||||
}
|
||||
|
||||
test("opencode APK proxy prefers explicit gitMirror proxyUrl", async () => {
|
||||
test("opencode APK proxy prefers the lane egress proxy URL", async () => {
|
||||
assert.equal(configString(" value "), "value");
|
||||
assert.equal(opencodeEgressProxyUrlForProfile({ lanes: { v03: { gitMirror: { egressProxy: { required: true, proxyUrl: "http://10.42.0.1:10808", namespace: "platform-infra", serviceName: "jd01-host-proxy", port: 10808 } } } } }, "v03"), "http://10.42.0.1:10808");
|
||||
assert.equal(opencodeEgressProxyUrlForProfile({ lanes: { v03: { gitMirror: { egressProxy: { required: true, namespace: "platform-infra", serviceName: "sub2api-egress-proxy", port: 10808 } } } } }, "v03"), "http://sub2api-egress-proxy.platform-infra.svc.cluster.local:10808");
|
||||
assert.equal(opencodeEgressProxyUrlForProfile({ lanes: { v03: { gitMirror: { egressProxy: { required: false, proxyUrl: "http://10.42.0.1:10808" } } } } }, "v03"), "");
|
||||
assert.equal(opencodeEgressProxyUrlForProfile({ lanes: { v03: { egressProxy: { required: true, proxyUrl: "http://10.42.0.1:10808", namespace: "platform-infra", serviceName: "jd01-host-proxy", port: 10808 } } } }, "v03"), "http://10.42.0.1:10808");
|
||||
assert.equal(opencodeEgressProxyUrlForProfile({ lanes: { v03: { egressProxy: { required: true, namespace: "platform-infra", serviceName: "sub2api-egress-proxy", port: 10808 } } } }, "v03"), "http://sub2api-egress-proxy.platform-infra.svc.cluster.local:10808");
|
||||
assert.equal(opencodeEgressProxyUrlForProfile({ lanes: { v03: { egressProxy: { required: false, proxyUrl: "http://10.42.0.1:10808" } } } }, "v03"), "");
|
||||
});
|
||||
|
||||
test("v02 render follows TypeScript runtime checks and does not self-patch bootstrap RBAC", async () => {
|
||||
@@ -235,14 +235,14 @@ test("v02 render follows TypeScript runtime checks and does not self-patch boots
|
||||
const planArtifacts = taskByName(pipelineJson, "plan-artifacts");
|
||||
const planArtifactsScript = planArtifacts.taskSpec.steps[0].script;
|
||||
assert.match(planArtifactsScript, /node scripts\/ci\/restore-artifact-catalog\.mjs/u);
|
||||
assert.match(planArtifactsScript, /HWLAB_GIT_READ_URL="\$\(params\.git-read-url\)"/u);
|
||||
assert.match(planArtifactsScript, /HWLAB_GIT_READ_URL="\$\(params\.gitops-read-url\)"/u);
|
||||
assert.match(planArtifactsScript, /HWLAB_SERVICES="\$\(params\.services\)"/u);
|
||||
assert.match(planArtifactsScript, /rolloutWithoutImageBuildServices/u);
|
||||
assert.match(planArtifactsScript, /serviceReusedCount/u);
|
||||
assert.match(planArtifactsScript, /artifactCatalog: plan\.artifactCatalog/u);
|
||||
assert.match(planArtifactsScript, /--base-ref "\$\(params\.release-base-commit\)"/u);
|
||||
assert.match(planArtifactsScript, /verify-reviewed-plan\.mjs/u);
|
||||
assert.ok(planArtifacts.taskSpec.params.some((param) => param.name === "git-read-url"));
|
||||
assert.ok(planArtifacts.taskSpec.params.some((param) => param.name === "gitops-read-url"));
|
||||
assert.ok(planArtifacts.taskSpec.params.some((param) => param.name === "gitops-branch"));
|
||||
assert.ok(planArtifacts.params.some((param) => param.name === "lane" && param.value === "$(params.lane)"));
|
||||
assert.ok(pipelineJson.spec.params.some((param) => param.name === "runtime-ready-timeout-ms" && param.default === "60000"));
|
||||
@@ -272,12 +272,13 @@ test("v02 render follows TypeScript runtime checks and does not self-patch boots
|
||||
assert.match(gitopsPromoteScript, /ARGO_APPLICATION="hwlab-node-\$lane" ARGO_FIELD_MANAGER="hwlab-\$lane-gitops-promote"/u);
|
||||
assert.match(gitopsPromoteScript, /argocd\.argoproj\.io\/refresh": "hard"/u);
|
||||
assert.match(gitopsPromoteScript, /applications\/" \+ encodeURIComponent\(application\) \+ "\?fieldManager=" \+ encodeURIComponent\(fieldManager\)/u);
|
||||
assert.match(gitopsPromoteScript, /BatchMode=yes/u);
|
||||
assert.match(gitopsPromoteScript, /ConnectTimeout=10/u);
|
||||
assert.match(gitopsPromoteScript, /GIT_ASKPASS_REQUIRE=force/u);
|
||||
assert.match(gitopsPromoteScript, /test -s \/workspace\/gitea-auth\/token/u);
|
||||
assert.match(gitopsPromoteScript, /git_timed "source-head-\$phase" 45 git ls-remote/u);
|
||||
assert.match(gitopsPromoteScript, /"event":"git-ssh-setup","phase":"gitops-promote","status":"skipped"/u);
|
||||
assert.doesNotMatch(gitopsPromoteScript, /git-ssh-setup/u);
|
||||
assert.match(gitopsPromoteScript, /source_head_url="\$\(params\.git-read-url\)"/u);
|
||||
assert.match(gitopsPromoteScript, /gitops_write_url="\$\(params\.git-write-url\)"/u);
|
||||
assert.match(gitopsPromoteScript, /gitops_read_url="\$\(params\.gitops-read-url\)"/u);
|
||||
assert.match(gitopsPromoteScript, /git clone --no-checkout "\$gitops_read_url"/u);
|
||||
assert.match(gitopsPromoteScript, /git_timed gitops-push 120 git push origin/u);
|
||||
assert.doesNotMatch(gitopsPromoteScript, /gitops-promote-proxy-preflight/u);
|
||||
@@ -285,13 +286,14 @@ test("v02 render follows TypeScript runtime checks and does not self-patch boots
|
||||
|
||||
const prepareSource = taskByName(pipelineJson, "prepare-source");
|
||||
assert.ok(prepareSource.taskSpec.params.some((param) => param.name === "git-read-url"));
|
||||
assert.ok(prepareSource.taskSpec.params.some((param) => param.name === "gitops-read-url"));
|
||||
assert.ok(prepareSource.params.some((param) => param.name === "git-read-url" && param.value === "$(params.git-read-url)"));
|
||||
const prepareSourceScript = prepareSource.taskSpec.steps[0].script;
|
||||
assert.match(prepareSourceScript, /git_read_url="\$\(params\.git-read-url\)"/u);
|
||||
assert.match(prepareSourceScript, /"event":"git-ssh-setup","phase":"prepare-source","status":"skipped"/u);
|
||||
assert.doesNotMatch(prepareSourceScript, /git-ssh-setup/u);
|
||||
assert.match(prepareSourceScript, /git_timed source-clone 180 git clone --branch "\$\(params\.source-branch\)" "\$git_read_url"/u);
|
||||
assert.match(prepareSourceScript, /git_timed catalog-ls-remote 45 git ls-remote --exit-code --heads "\$git_read_url"/u);
|
||||
assert.match(prepareSourceScript, /git remote set-url gitops-catalog "\$git_read_url"/u);
|
||||
assert.match(prepareSourceScript, /git_timed catalog-ls-remote 45 git ls-remote --exit-code --heads "\$gitops_read_url"/u);
|
||||
assert.match(prepareSourceScript, /git remote set-url gitops-catalog "\$gitops_read_url"/u);
|
||||
assert.match(prepareSourceScript, /"event":"prepare-source-dependencies","status":"skipped","reason":"renderer-dependency-install-disabled","dependency":"yaml"/u);
|
||||
assert.doesNotMatch(prepareSourceScript, /require\.resolve\("yaml"\)/u);
|
||||
assert.doesNotMatch(prepareSourceScript, /npm ci --ignore-scripts --no-audit --prefer-offline/u);
|
||||
@@ -308,71 +310,17 @@ test("v02 render follows TypeScript runtime checks and does not self-patch boots
|
||||
const pipelineGitReadParam = pipelineJson.spec.params.find((param) => param.name === "git-read-url");
|
||||
assert.equal(pipelineGitReadParam?.default, "http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git");
|
||||
const pipelineGitWriteParam = pipelineJson.spec.params.find((param) => param.name === "git-write-url");
|
||||
assert.equal(pipelineGitWriteParam?.default, "http://git-mirror-write.devops-infra.svc.cluster.local/pikasTech/HWLAB.git");
|
||||
assert.equal(pipelineGitWriteParam?.default, "http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git");
|
||||
const pipelineGitopsReadParam = pipelineJson.spec.params.find((param) => param.name === "gitops-read-url");
|
||||
assert.equal(pipelineGitopsReadParam?.default, pipelineGitReadParam?.default);
|
||||
assert.ok(pipelineJson.spec.workspaces.some((workspace) => workspace.name === "gitea-auth"));
|
||||
assert.ok(!pipelineJson.spec.workspaces.some((workspace) => workspace.name === "git-ssh"));
|
||||
|
||||
const sourceDescriptor = JSON.parse(await readFile(path.join(outDir, "source.json"), "utf8"));
|
||||
assert.equal(sourceDescriptor.gitReadUrl, "http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git");
|
||||
assert.equal(sourceDescriptor.gitWriteUrl, "http://git-mirror-write.devops-infra.svc.cluster.local/pikasTech/HWLAB.git");
|
||||
assert.equal(sourceDescriptor.gitWriteUrl, "http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git");
|
||||
|
||||
const gitMirror = await readFile(path.join(outDir, "devops-infra", "git-mirror.yaml"), "utf8");
|
||||
assert.match(gitMirror, /"name": "devops-infra"/u);
|
||||
assert.match(gitMirror, /"name": "git-mirror-http"/u);
|
||||
assert.match(gitMirror, /"name": "git-mirror-write"/u);
|
||||
assert.match(gitMirror, /"name": "git-mirror-sync-script"/u);
|
||||
assert.match(gitMirror, /git-receive-pack/u);
|
||||
assert.match(gitMirror, /last-flush\.json/u);
|
||||
assert.match(gitMirror, /last-write\.json/u);
|
||||
assert.match(gitMirror, /ssh:\/\/git@ssh\.github\.com:443\/pikasTech\/HWLAB\.git/u);
|
||||
assert.doesNotMatch(gitMirror, /"kind": "CronJob"/u);
|
||||
assert.doesNotMatch(gitMirror, /"name": "git-mirror-hwlab-sync"/u);
|
||||
const gitMirrorJson = JSON.parse(gitMirror);
|
||||
const gitMirrorConfigMap = gitMirrorJson.items.find((item) => item.kind === "ConfigMap" && item.metadata?.name === "git-mirror-sync-script");
|
||||
const gitMirrorScripts = gitMirrorConfigMap?.data ?? {};
|
||||
const gitMirrorScript = gitMirrorScripts["sync.sh"] ?? "";
|
||||
assert.match(gitMirrorScript, /uploadpack\.allowReachableSHA1InWant true/u);
|
||||
assert.match(gitMirrorScript, /uploadpack\.allowAnySHA1InWant true/u);
|
||||
assert.match(gitMirrorScript, /refs\/heads\/v0\.2:refs\/mirror-stage\/heads\/v0\.2/u);
|
||||
assert.match(gitMirrorScript, /refs\/heads\/v0\.2-gitops:refs\/mirror-stage\/heads\/v0\.2-gitops/u);
|
||||
assert.match(gitMirrorScript, /refs\/heads\/v0\.3:refs\/mirror-stage\/heads\/v0\.3/u);
|
||||
assert.match(gitMirrorScript, /refs\/heads\/v0\.3-gitops:refs\/mirror-stage\/heads\/v0\.3-gitops/u);
|
||||
assert.match(gitMirrorScript, /refs\/heads\/release:refs\/mirror-stage\/heads\/release/u);
|
||||
assert.match(gitMirrorScript, /refs\/heads\/release-gitops:refs\/mirror-stage\/heads\/release-gitops/u);
|
||||
assert.doesNotMatch(gitMirrorScript, /refs\/heads\/G14:refs\/mirror-stage\/heads\/G14/u);
|
||||
assert.doesNotMatch(gitMirrorScript, /refs\/heads\/G14-gitops:refs\/mirror-stage\/heads\/G14-gitops/u);
|
||||
assert.doesNotMatch(gitMirrorScript, /refs\/heads\/\*:refs\/mirror-stage\/heads\/\*/u);
|
||||
assert.match(gitMirrorScript, /git -C "\$repo_path" update-ref "refs\/heads\/\$name" "\$sha"/u);
|
||||
assert.match(gitMirrorScript, /source_snapshot_ref_prefix='refs\/unidesk\/snapshots\/hwlab-node-runtime'/u);
|
||||
assert.match(gitMirrorScript, /source_stage_ref="\$\{source_snapshot_ref_prefix%\/\}\/\$source_branch\/\$source_sha"/u);
|
||||
assert.match(gitMirrorScript, /git -C "\$repo_path" update-ref "\$source_stage_ref" "\$source_sha"/u);
|
||||
assert.match(gitMirrorScript, /git-mirror-sync-timing/u);
|
||||
assert.match(gitMirrorScript, /emit_timing fetch succeeded/u);
|
||||
assert.match(gitMirrorScript, /emit_timing total succeeded/u);
|
||||
assert.match(gitMirrorScript, /sourceInSync/u);
|
||||
assert.match(gitMirrorScript, /sourceSnapshots/u);
|
||||
assert.match(gitMirrorScript, /refs\/unidesk\/snapshots\/hwlab-node-runtime/u);
|
||||
assert.match(gitMirrorScript, /refs\/mirror-stage\/heads\/v0\.2/u);
|
||||
assert.match(gitMirrorScript, /refs\/mirror-stage\/heads\/v0\.3/u);
|
||||
assert.match(gitMirrorScript, /for gitops_branch in 'release-gitops' 'v0\.2-gitops' 'v0\.3-gitops'/u);
|
||||
assert.match(gitMirrorScript, /keeps local \$name ahead of GitHub/u);
|
||||
assert.doesNotMatch(gitMirror, /not allowlisted/u);
|
||||
assert.doesNotMatch(gitMirror, /path allowlist/u);
|
||||
assert.doesNotMatch(gitMirror, /outside .* GitOps outputs/u);
|
||||
assert.ok((gitMirrorJson.items || []).every((item) => item.kind !== "Secret"));
|
||||
assert.ok((gitMirrorJson.items || []).every((item) => item.kind !== "CronJob"));
|
||||
assert.ok((gitMirrorJson.items || []).every((item) => !item.data?.["ssh-privatekey"]));
|
||||
|
||||
const scriptCheckDir = path.join(outDir, "script-check");
|
||||
await mkdir(scriptCheckDir, { recursive: true });
|
||||
for (const scriptName of ["http.mjs", "sync.sh", "install-hooks.sh", "flush.sh"]) {
|
||||
assert.ok(gitMirrorScripts[scriptName], `missing git mirror script ${scriptName}`);
|
||||
await writeFile(path.join(scriptCheckDir, scriptName), gitMirrorScripts[scriptName]);
|
||||
}
|
||||
const httpCheck = spawnSync("node", ["--check", path.join(scriptCheckDir, "http.mjs")], { encoding: "utf8" });
|
||||
assert.equal(httpCheck.status, 0, httpCheck.stderr || httpCheck.stdout);
|
||||
for (const scriptName of ["sync.sh", "install-hooks.sh", "flush.sh"]) {
|
||||
const shellCheck = spawnSync("sh", ["-n", path.join(scriptCheckDir, scriptName)], { encoding: "utf8" });
|
||||
assert.equal(shellCheck.status, 0, `${scriptName}: ${shellCheck.stderr || shellCheck.stdout}`);
|
||||
}
|
||||
await assert.rejects(() => readFile(path.join(outDir, "devops-infra", "git-mirror.yaml"), "utf8"), { code: "ENOENT" });
|
||||
|
||||
const removedServiceIds = [
|
||||
"hwlab-agent-mgr",
|
||||
@@ -501,11 +449,11 @@ test("v02 render follows TypeScript runtime checks and does not self-patch boots
|
||||
const cloudApiEnv = cloudApiContainer.env;
|
||||
const cloudApiCommit = cloudApiEnv.find((entry) => entry.name === "HWLAB_COMMIT_ID")?.value;
|
||||
const cloudApiBootEnv = new Map(cloudApiEnv.map((entry) => [entry.name, entry.value]));
|
||||
assert.equal(cloudApiBootEnv.get("HWLAB_RUNTIME_MODE"), "env-reuse-git-mirror-checkout");
|
||||
assert.equal(cloudApiBootEnv.get("HWLAB_RUNTIME_MODE"), "env-reuse-gitea-checkout");
|
||||
assert.equal(cloudApiBootEnv.get("HWLAB_BOOT_SH"), "deploy/runtime/boot/hwlab-cloud-api.sh");
|
||||
const codexForwarderEnv = new Map(codexForwarder.env.map((entry) => [entry.name, entry.value]));
|
||||
assert.equal(codexForwarder.command, undefined);
|
||||
assert.equal(codexForwarderEnv.get("HWLAB_RUNTIME_MODE"), "env-reuse-git-mirror-checkout");
|
||||
assert.equal(codexForwarderEnv.get("HWLAB_RUNTIME_MODE"), "env-reuse-gitea-checkout");
|
||||
assert.equal(codexForwarderEnv.get("HWLAB_BOOT_SH"), "deploy/runtime/boot/hwlab-codex-api-responses-forwarder.sh");
|
||||
assert.equal(codexForwarderEnv.get("HWLAB_BOOT_COMMIT"), cloudApiCommit);
|
||||
assert.equal(codexForwarderEnv.get("HWLAB_BOOT_READ_URL"), "http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git");
|
||||
@@ -527,7 +475,7 @@ test("v02 render follows TypeScript runtime checks and does not self-patch boots
|
||||
assert.ok(deepseekResponsesBridge, "expected DeepSeek responses bridge container");
|
||||
const deepseekBridgeEnv = new Map(deepseekResponsesBridge.env.map((entry) => [entry.name, entry.value]));
|
||||
assert.equal(deepseekResponsesBridge.command, undefined);
|
||||
assert.equal(deepseekBridgeEnv.get("HWLAB_RUNTIME_MODE"), "env-reuse-git-mirror-checkout");
|
||||
assert.equal(deepseekBridgeEnv.get("HWLAB_RUNTIME_MODE"), "env-reuse-gitea-checkout");
|
||||
assert.equal(deepseekBridgeEnv.get("HWLAB_BOOT_SH"), "deploy/runtime/boot/hwlab-deepseek-responses-bridge.sh");
|
||||
assert.equal(deepseekBridgeEnv.get("HWLAB_BOOT_COMMIT"), cloudApiCommit);
|
||||
assert.equal(deepseekBridgeEnv.get("HWLAB_BOOT_READ_URL"), "http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git");
|
||||
@@ -620,7 +568,7 @@ test("v02 render follows TypeScript runtime checks and does not self-patch boots
|
||||
|
||||
const pipelineRunSample = await readFile(path.join(outDir, "tekton-v02", "pipelinerun.sample.yaml"), "utf8");
|
||||
assert.match(pipelineRunSample, /"name": "git-read-url"[\s\S]{0,180}gitea-http\.devops-infra\.svc\.cluster\.local:3000\/mirrors\/pikasTech-HWLAB\.git/u);
|
||||
assert.match(pipelineRunSample, /"name": "git-write-url"[\s\S]{0,140}git-mirror-write\.devops-infra\.svc\.cluster\.local/u);
|
||||
assert.match(pipelineRunSample, /"name": "git-write-url"[\s\S]{0,180}gitea-http\.devops-infra\.svc\.cluster\.local:3000\/mirrors\/pikasTech-HWLAB\.git/u);
|
||||
assert.match(pipelineRunSample, /"name": "revision"[\s\S]{0,80}"value": "[0-9a-f]{40}"/u);
|
||||
assert.match(pipelineRunSample, /"name": "source-branch"[\s\S]{0,80}"value": "v0\.2"/u);
|
||||
} finally {
|
||||
@@ -648,7 +596,7 @@ test("v03 render keeps node identity as data instead of generated structure", as
|
||||
artifactState: "ready",
|
||||
services: [{
|
||||
serviceId: "hwlab-cloud-api",
|
||||
runtimeMode: "env-reuse-git-mirror-checkout",
|
||||
runtimeMode: "env-reuse-gitea-checkout",
|
||||
envReuse: true,
|
||||
sourceCommitId: staleRevision,
|
||||
commitId: staleRevision,
|
||||
@@ -848,7 +796,7 @@ test("v03 render includes JD01 secret-plane smoke on JD01 gitops root", { timeou
|
||||
artifactState: "ready",
|
||||
services: [{
|
||||
serviceId: "hwlab-cloud-api",
|
||||
runtimeMode: "env-reuse-git-mirror-checkout",
|
||||
runtimeMode: "env-reuse-gitea-checkout",
|
||||
envReuse: true,
|
||||
sourceCommitId: staleRevision,
|
||||
commitId: staleRevision,
|
||||
|
||||
@@ -26,7 +26,7 @@ const commitPattern = /^[a-f0-9]{7,40}$/;
|
||||
const runtimeArtifactLanePattern = /^[a-z][a-z0-9-]*$/u;
|
||||
|
||||
const publishReadyStatuses = new Set(["published", "reused"]);
|
||||
const v02EnvReuseRuntimeMode = "env-reuse-git-mirror-checkout";
|
||||
const v02EnvReuseRuntimeMode = "env-reuse-gitea-checkout";
|
||||
|
||||
function isRuntimeArtifactLane(lane) {
|
||||
return runtimeArtifactLanePattern.test(String(lane ?? ""));
|
||||
|
||||
@@ -431,7 +431,7 @@ test("v03 refresh accepts runtime lane config and env-reuse image tags", async (
|
||||
serviceId,
|
||||
status: "published",
|
||||
artifactRequired: true,
|
||||
runtimeMode: "env-reuse-git-mirror-checkout",
|
||||
runtimeMode: "env-reuse-gitea-checkout",
|
||||
envReuse: true,
|
||||
commitId,
|
||||
sourceCommitId: commitId,
|
||||
@@ -476,7 +476,7 @@ test("v03 refresh accepts runtime lane config and env-reuse image tags", async (
|
||||
assert.equal(payload.endpoint, "https://hwlab-v03.74-48-78-17.nip.io");
|
||||
assert.equal(payload.requiredServiceCount, serviceIds.length);
|
||||
assert.deepEqual(payload.services.map((service) => service.serviceId), serviceIds);
|
||||
assert.equal(payload.services.every((service) => service.runtimeMode === "env-reuse-git-mirror-checkout"), true);
|
||||
assert.equal(payload.services.every((service) => service.runtimeMode === "env-reuse-gitea-checkout"), true);
|
||||
assert.equal(payload.services.every((service) => service.imageTag.startsWith("env-")), true);
|
||||
});
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import { parseStructuredConfig, readStructuredFileIfPresent } from "./structured
|
||||
const execFileAsync = promisify(execFile);
|
||||
|
||||
export const CI_PLAN_VERSION = "v1";
|
||||
export const ENV_REUSE_RUNTIME_MODE = "env-reuse-git-mirror-checkout";
|
||||
export const ENV_REUSE_RUNTIME_MODE = "env-reuse-gitea-checkout";
|
||||
export const V02_ENV_REUSE_RUNTIME_MODE = ENV_REUSE_RUNTIME_MODE;
|
||||
|
||||
export const DEFAULT_RUNTIME_DEP_PATHS = Object.freeze([
|
||||
|
||||
@@ -29,10 +29,10 @@ const defaultOutDir = "deploy/gitops/node";
|
||||
const defaultRegistryPrefix = process.env.HWLAB_NODE_REGISTRY_PREFIX || "127.0.0.1:5000/hwlab";
|
||||
const defaultSourceRepo = process.env.HWLAB_NODE_GIT_URL || "git@github.com:pikasTech/HWLAB.git";
|
||||
const defaultGitReadUrl = process.env.HWLAB_NODE_GIT_READ_URL || null;
|
||||
const defaultV02GitReadUrl = process.env.HWLAB_V02_GIT_READ_URL || "http://git-mirror-http.devops-infra.svc.cluster.local/pikasTech/HWLAB.git";
|
||||
const defaultV02GitWriteUrl = process.env.HWLAB_V02_GIT_WRITE_URL || "http://git-mirror-write.devops-infra.svc.cluster.local/pikasTech/HWLAB.git";
|
||||
const defaultV02GitReadUrl = process.env.HWLAB_V02_GIT_READ_URL || "http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git";
|
||||
const defaultV02GitWriteUrl = process.env.HWLAB_V02_GIT_WRITE_URL || defaultV02GitReadUrl;
|
||||
const defaultRuntimeLaneGitReadUrl = process.env.HWLAB_RUNTIME_LANE_GIT_READ_URL || "http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git";
|
||||
const defaultRuntimeLaneGitWriteUrl = process.env.HWLAB_RUNTIME_LANE_GIT_WRITE_URL || defaultV02GitWriteUrl;
|
||||
const defaultRuntimeLaneGitWriteUrl = process.env.HWLAB_RUNTIME_LANE_GIT_WRITE_URL || defaultRuntimeLaneGitReadUrl;
|
||||
const defaultBranch = process.env.HWLAB_NODE_BRANCH || "node";
|
||||
const defaultGitopsBranch = process.env.HWLAB_NODE_GITOPS_BRANCH || "node-gitops";
|
||||
const defaultCatalogPath = process.env.HWLAB_ARTIFACT_CATALOG_PATH || "deploy/artifact-catalog.dev.json";
|
||||
@@ -44,7 +44,7 @@ const defaultV02RuntimeEndpoint = process.env.HWLAB_V02_RUNTIME_ENDPOINT || "htt
|
||||
const defaultV02WebEndpoint = process.env.HWLAB_V02_WEB_ENDPOINT || "https://hwlab.74-48-78-17.nip.io";
|
||||
const defaultProxyUrl = process.env.HWLAB_NODE_PROXY_URL || "http://127.0.0.1:10808";
|
||||
const defaultAllProxyUrl = process.env.HWLAB_NODE_ALL_PROXY_URL || "socks5h://127.0.0.1:10808";
|
||||
const defaultNoProxy = process.env.HWLAB_NODE_NO_PROXY || "hyueapi.com,.hyueapi.com,127.0.0.1,localhost,::1,10.0.0.0/8,10.42.0.0/16,10.43.0.0/16,192.168.0.0/16,.svc,.cluster.local,kubernetes.default.svc,registry.hwlab-ci.svc,hwlab-registry.hwlab-ci.svc,git-mirror-http,git-mirror-http.devops-infra,git-mirror-http.devops-infra.svc,git-mirror-http.devops-infra.svc.cluster.local,git-mirror-write,git-mirror-write.devops-infra,git-mirror-write.devops-infra.svc,git-mirror-write.devops-infra.svc.cluster.local";
|
||||
const defaultNoProxy = process.env.HWLAB_NODE_NO_PROXY || "hyueapi.com,.hyueapi.com,127.0.0.1,localhost,::1,10.0.0.0/8,10.42.0.0/16,10.43.0.0/16,192.168.0.0/16,.svc,.cluster.local,kubernetes.default.svc,registry.hwlab-ci.svc,hwlab-registry.hwlab-ci.svc,gitea-http,gitea-http.devops-infra,gitea-http.devops-infra.svc,gitea-http.devops-infra.svc.cluster.local";
|
||||
const ciToolsRunnerImage = process.env.HWLAB_NODE_CI_TOOLS_IMAGE || "127.0.0.1:5000/hwlab/hwlab-ci-node-tools:node22-alpine-bun-v1";
|
||||
const buildkitRunnerImage = process.env.HWLAB_NODE_BUILDKIT_IMAGE || "moby/buildkit:rootless";
|
||||
const defaultDevBaseImage = process.env.HWLAB_NODE_DEV_BASE_IMAGE || "127.0.0.1:5000/hwlab/hwlab-node20-base:20-bookworm-slim";
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import {
|
||||
ciToolsRunnerImage,
|
||||
configObject,
|
||||
defaultOutDir,
|
||||
label,
|
||||
optionalConfigString,
|
||||
requiredConfigPositiveInteger,
|
||||
requiredConfigString,
|
||||
runtimeLaneMirrorSpecs
|
||||
} from "./core.mjs";
|
||||
import { renderTemplate, shellSingleQuote } from "./tekton-scripts.mjs";
|
||||
|
||||
function registryManifest() {
|
||||
return {
|
||||
apiVersion: "v1",
|
||||
@@ -55,200 +41,6 @@ function registryManifest() {
|
||||
};
|
||||
}
|
||||
|
||||
function uniqueStrings(values) {
|
||||
return Array.from(new Set(values.filter((value) => typeof value === "string" && value.length > 0)));
|
||||
}
|
||||
|
||||
function renderGitMirrorSshPrelude({ direct, proxySummary, proxyCommand, proxyUrl, proxyNoProxy }) {
|
||||
if (direct) {
|
||||
return renderTemplate("git-mirror-ssh-direct.sh", {
|
||||
"__HWLAB_PROXY_SUMMARY_SHELL__": shellSingleQuote(proxySummary)
|
||||
});
|
||||
}
|
||||
return renderTemplate("git-mirror-ssh-proxied.sh", {
|
||||
"// __HWLAB_GIT_MIRROR_PROXY_CONNECT_MJS__": renderTemplate("git-mirror-proxy-connect.mjs"),
|
||||
"__HWLAB_PROXY_SUMMARY_SHELL__": shellSingleQuote(proxySummary),
|
||||
"__HWLAB_PROXY_COMMAND_SHELL__": shellSingleQuote(proxyCommand),
|
||||
"__HWLAB_PROXY_URL_SHELL__": shellSingleQuote(proxyUrl),
|
||||
"__HWLAB_PROXY_NO_PROXY_SHELL__": shellSingleQuote(proxyNoProxy)
|
||||
});
|
||||
}
|
||||
|
||||
function gitMirrorConfigScripts({
|
||||
fetchConfigCommands,
|
||||
gitMirrorSshPrelude,
|
||||
gitopsBranchArgs,
|
||||
gitopsBranchesJson,
|
||||
mirrorBranchesJson,
|
||||
requiredRefArgs,
|
||||
sourceBranchArgs,
|
||||
sourceBranchesJson,
|
||||
sourceSnapshotRefPrefix
|
||||
}) {
|
||||
const gitopsBranchesJsonShell = shellSingleQuote(gitopsBranchesJson);
|
||||
return {
|
||||
"sync.sh": renderTemplate("git-mirror-sync.sh", {
|
||||
"# __HWLAB_GIT_MIRROR_SSH_PRELUDE__": gitMirrorSshPrelude,
|
||||
"__HWLAB_SOURCE_SNAPSHOT_REF_PREFIX_SHELL__": shellSingleQuote(sourceSnapshotRefPrefix),
|
||||
"# __HWLAB_FETCH_CONFIG_COMMANDS__": fetchConfigCommands,
|
||||
"__HWLAB_REQUIRED_REF_ARGS__": requiredRefArgs,
|
||||
"__HWLAB_SOURCE_BRANCH_ARGS__": sourceBranchArgs,
|
||||
"__HWLAB_GITOPS_BRANCH_ARGS__": gitopsBranchArgs,
|
||||
"__HWLAB_MIRROR_BRANCHES_JSON_SHELL__": shellSingleQuote(mirrorBranchesJson),
|
||||
"__HWLAB_SOURCE_BRANCHES_JSON_SHELL__": shellSingleQuote(sourceBranchesJson),
|
||||
"__HWLAB_GITOPS_BRANCHES_JSON_SHELL__": gitopsBranchesJsonShell
|
||||
}),
|
||||
"install-hooks.sh": renderTemplate("git-mirror-install-hooks.sh", {
|
||||
"__HWLAB_GITOPS_BRANCHES_JSON_SHELL__": gitopsBranchesJsonShell
|
||||
}),
|
||||
"flush.sh": renderTemplate("git-mirror-flush.sh", {
|
||||
"# __HWLAB_GIT_MIRROR_SSH_PRELUDE__": gitMirrorSshPrelude,
|
||||
"__HWLAB_GITOPS_BRANCH_ARGS__": gitopsBranchArgs,
|
||||
"__HWLAB_GITOPS_BRANCHES_JSON_SHELL__": gitopsBranchesJsonShell
|
||||
}),
|
||||
"http.mjs": renderTemplate("git-mirror-http.mjs")
|
||||
};
|
||||
}
|
||||
|
||||
function devopsInfraGitMirrorManifest(args, deploy) {
|
||||
const mirrorSpecs = runtimeLaneMirrorSpecs(deploy, { defaultNodeId: args.nodeId, defaultGitopsRoot: defaultOutDir });
|
||||
assert.ok(mirrorSpecs.length > 0, "runtime lane git mirror requires at least one deploy.lanes entry");
|
||||
const sourceBranches = uniqueStrings(mirrorSpecs.map((spec) => spec.sourceBranch));
|
||||
const gitopsBranches = uniqueStrings(mirrorSpecs.map((spec) => spec.gitopsBranch));
|
||||
const mirrorBranches = uniqueStrings([...sourceBranches, ...gitopsBranches]);
|
||||
const fetchConfigCommands = mirrorBranches
|
||||
.map((branch) => `git -C "$repo_path" config --add remote.origin.fetch '+refs/heads/${branch}:refs/mirror-stage/heads/${branch}'`)
|
||||
.join("\n");
|
||||
const requiredRefArgs = mirrorBranches.map((branch) => shellSingleQuote(`refs/mirror-stage/heads/${branch}`)).join(" ");
|
||||
const sourceBranchArgs = sourceBranches.map((branch) => shellSingleQuote(branch)).join(" ");
|
||||
const gitopsBranchArgs = gitopsBranches.map((branch) => shellSingleQuote(branch)).join(" ");
|
||||
const mirrorBranchesJson = JSON.stringify(mirrorBranches);
|
||||
const sourceBranchesJson = JSON.stringify(sourceBranches);
|
||||
const gitopsBranchesJson = JSON.stringify(gitopsBranches);
|
||||
const sourceSnapshotRefPrefix = "refs/unidesk/snapshots/hwlab-node-runtime";
|
||||
const laneConfig = configObject(configObject(deploy.lanes, "deploy.lanes")[args.lane], `deploy.lanes.${args.lane}`);
|
||||
const gitMirrorConfig = configObject(laneConfig.gitMirror, `deploy.lanes.${args.lane}.gitMirror`);
|
||||
const gitMirrorProxy = configObject(gitMirrorConfig.egressProxy, `deploy.lanes.${args.lane}.gitMirror.egressProxy`);
|
||||
const gitMirrorProxyMode = requiredConfigString(gitMirrorProxy, "mode", `deploy.lanes.${args.lane}.gitMirror.egressProxy`);
|
||||
assert.ok(gitMirrorProxyMode === "node-global" || gitMirrorProxyMode === "host-proxy-client" || gitMirrorProxyMode === "direct", `deploy.lanes.${args.lane}.gitMirror.egressProxy.mode must be node-global, host-proxy-client, or direct`);
|
||||
const useDirectGitMirrorProxy = gitMirrorProxyMode === "direct";
|
||||
const useHostGitMirrorProxy = gitMirrorProxyMode === "host-proxy-client";
|
||||
const gitMirrorNamespace = requiredConfigString(gitMirrorConfig, "namespace", `deploy.lanes.${args.lane}.gitMirror`);
|
||||
const gitMirrorReadName = requiredConfigString(gitMirrorConfig, "serviceReadName", `deploy.lanes.${args.lane}.gitMirror`);
|
||||
const gitMirrorWriteName = requiredConfigString(gitMirrorConfig, "serviceWriteName", `deploy.lanes.${args.lane}.gitMirror`);
|
||||
const gitMirrorCachePvcName = requiredConfigString(gitMirrorConfig, "cachePvcName", `deploy.lanes.${args.lane}.gitMirror`);
|
||||
const gitMirrorCachePvcStorage = requiredConfigString(gitMirrorConfig, "cachePvcStorage", `deploy.lanes.${args.lane}.gitMirror`);
|
||||
const gitMirrorCacheHostPath = optionalConfigString(gitMirrorConfig, "cacheHostPath", `deploy.lanes.${args.lane}.gitMirror`);
|
||||
const gitMirrorServicePort = requiredConfigPositiveInteger(gitMirrorConfig, "servicePort", `deploy.lanes.${args.lane}.gitMirror`);
|
||||
const gitMirrorConfigMapName = requiredConfigString(gitMirrorConfig, "syncConfigMapName", `deploy.lanes.${args.lane}.gitMirror`);
|
||||
const proxyNamespace = useDirectGitMirrorProxy || useHostGitMirrorProxy ? "" : requiredConfigString(gitMirrorProxy, "namespace", `deploy.lanes.${args.lane}.gitMirror.egressProxy`);
|
||||
const proxyServiceName = useDirectGitMirrorProxy || useHostGitMirrorProxy ? "" : requiredConfigString(gitMirrorProxy, "serviceName", `deploy.lanes.${args.lane}.gitMirror.egressProxy`);
|
||||
const proxyPort = useDirectGitMirrorProxy ? 0 : requiredConfigPositiveInteger(gitMirrorProxy, "port", `deploy.lanes.${args.lane}.gitMirror.egressProxy`);
|
||||
const proxyClientName = useDirectGitMirrorProxy ? "" : requiredConfigString(gitMirrorProxy, "clientName", `deploy.lanes.${args.lane}.gitMirror.egressProxy`);
|
||||
const proxyNoProxy = !useDirectGitMirrorProxy && Array.isArray(gitMirrorProxy.noProxy) ? gitMirrorProxy.noProxy.filter((value) => typeof value === "string" && value.length > 0).join(",") : "";
|
||||
const proxyHost = useHostGitMirrorProxy
|
||||
? requiredConfigString(gitMirrorProxy, "host", `deploy.lanes.${args.lane}.gitMirror.egressProxy`)
|
||||
: `${proxyServiceName}.${proxyNamespace}.svc.cluster.local`;
|
||||
const proxyUrl = `http://${proxyHost}:${proxyPort}`;
|
||||
const proxySummary = useDirectGitMirrorProxy
|
||||
? "git-mirror-egress-proxy mode=direct required=false transport=ssh source=yaml"
|
||||
: `git-mirror-egress-proxy client=${proxyClientName} mode=${gitMirrorProxyMode} required=true host=${proxyHost} port=${proxyPort} ssh=GIT_SSH-wrapper source=yaml`;
|
||||
const proxyCommand = useDirectGitMirrorProxy ? "" : `ProxyCommand=node /tmp/hwlab-github-proxy-connect.mjs ${proxyHost} ${proxyPort} %h %p`;
|
||||
const gitMirrorSshPrelude = renderGitMirrorSshPrelude({
|
||||
direct: useDirectGitMirrorProxy,
|
||||
proxySummary,
|
||||
proxyCommand,
|
||||
proxyUrl,
|
||||
proxyNoProxy
|
||||
});
|
||||
const cacheVolume = gitMirrorCacheHostPath === null
|
||||
? { name: "cache", persistentVolumeClaim: { claimName: gitMirrorCachePvcName } }
|
||||
: { name: "cache", hostPath: { path: gitMirrorCacheHostPath, type: "DirectoryOrCreate" } };
|
||||
const labels = {
|
||||
"app.kubernetes.io/part-of": "hwlab-node-control-plane",
|
||||
"hwlab.pikastech.local/node": args.nodeId,
|
||||
"hwlab.pikastech.local/lane": args.lane
|
||||
};
|
||||
const configLabels = { ...labels, "app.kubernetes.io/name": "git-mirror" };
|
||||
const readLabels = { ...labels, "app.kubernetes.io/name": gitMirrorReadName, "hwlab.pikastech.local/git-mirror-mode": "read" };
|
||||
const writeLabels = { ...labels, "app.kubernetes.io/name": gitMirrorWriteName, "hwlab.pikastech.local/git-mirror-mode": "write" };
|
||||
return {
|
||||
apiVersion: "v1",
|
||||
kind: "List",
|
||||
items: [
|
||||
{ apiVersion: "v1", kind: "Namespace", metadata: { name: gitMirrorNamespace } },
|
||||
...(gitMirrorCacheHostPath === null ? [{
|
||||
apiVersion: "v1",
|
||||
kind: "PersistentVolumeClaim",
|
||||
metadata: { name: gitMirrorCachePvcName, namespace: gitMirrorNamespace, labels: configLabels },
|
||||
spec: { accessModes: ["ReadWriteOnce"], resources: { requests: { storage: gitMirrorCachePvcStorage } } }
|
||||
}] : []),
|
||||
{
|
||||
apiVersion: "v1",
|
||||
kind: "ConfigMap",
|
||||
metadata: { name: gitMirrorConfigMapName, namespace: gitMirrorNamespace, labels: configLabels },
|
||||
data: gitMirrorConfigScripts({
|
||||
fetchConfigCommands,
|
||||
gitMirrorSshPrelude,
|
||||
gitopsBranchArgs,
|
||||
gitopsBranchesJson,
|
||||
mirrorBranchesJson,
|
||||
requiredRefArgs,
|
||||
sourceBranchArgs,
|
||||
sourceBranchesJson,
|
||||
sourceSnapshotRefPrefix
|
||||
})
|
||||
},
|
||||
{
|
||||
apiVersion: "apps/v1",
|
||||
kind: "Deployment",
|
||||
metadata: { name: gitMirrorReadName, namespace: gitMirrorNamespace, labels: readLabels },
|
||||
spec: {
|
||||
replicas: 1,
|
||||
selector: { matchLabels: { "app.kubernetes.io/name": gitMirrorReadName } },
|
||||
template: {
|
||||
metadata: { labels: readLabels },
|
||||
spec: {
|
||||
containers: [{
|
||||
name: "git-mirror",
|
||||
image: ciToolsRunnerImage,
|
||||
imagePullPolicy: "IfNotPresent",
|
||||
command: ["node"],
|
||||
args: ["/etc/git-mirror/http.mjs"],
|
||||
ports: [{ name: "http", containerPort: 8080 }],
|
||||
readinessProbe: { httpGet: { path: "/pikasTech/HWLAB.git/HEAD", port: "http" }, initialDelaySeconds: 5, periodSeconds: 10 },
|
||||
livenessProbe: { httpGet: { path: "/", port: "http" }, initialDelaySeconds: 10, periodSeconds: 30 },
|
||||
volumeMounts: [
|
||||
{ name: "cache", mountPath: "/cache" },
|
||||
{ name: "config", mountPath: "/etc/git-mirror", readOnly: true }
|
||||
]
|
||||
}],
|
||||
volumes: [
|
||||
cacheVolume,
|
||||
{ name: "config", configMap: { name: gitMirrorConfigMapName, defaultMode: 0o555 } }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
apiVersion: "v1",
|
||||
kind: "Service",
|
||||
metadata: { name: gitMirrorReadName, namespace: gitMirrorNamespace, labels: readLabels },
|
||||
spec: { selector: { "app.kubernetes.io/name": gitMirrorReadName }, ports: [{ name: "http", port: gitMirrorServicePort, targetPort: "http" }] }
|
||||
},
|
||||
{
|
||||
apiVersion: "v1",
|
||||
kind: "Service",
|
||||
metadata: { name: gitMirrorWriteName, namespace: gitMirrorNamespace, labels: writeLabels },
|
||||
spec: { selector: { "app.kubernetes.io/name": gitMirrorReadName }, ports: [{ name: "http", port: gitMirrorServicePort, targetPort: "http" }] }
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
export {
|
||||
devopsInfraGitMirrorManifest,
|
||||
registryManifest,
|
||||
uniqueStrings
|
||||
registryManifest
|
||||
};
|
||||
|
||||
@@ -1237,7 +1237,7 @@ function opencodeConfigBoolean(value, fallback, label) {
|
||||
}
|
||||
|
||||
function opencodeEgressProxyUrlForProfile(deploy, profile) {
|
||||
const proxy = deploy?.lanes?.[profile]?.gitMirror?.egressProxy;
|
||||
const proxy = deploy?.lanes?.[profile]?.egressProxy;
|
||||
if (!proxy || proxy.required === false) return "";
|
||||
const proxyUrl = configString(proxy.proxyUrl);
|
||||
if (proxyUrl) return proxyUrl;
|
||||
@@ -1249,7 +1249,7 @@ function opencodeEgressProxyUrlForProfile(deploy, profile) {
|
||||
}
|
||||
|
||||
function opencodeEgressNoProxyForProfile(deploy, profile) {
|
||||
const proxy = deploy?.lanes?.[profile]?.gitMirror?.egressProxy;
|
||||
const proxy = deploy?.lanes?.[profile]?.egressProxy;
|
||||
const entries = Array.isArray(proxy?.noProxy) ? proxy.noProxy.map(configString).filter(Boolean) : [];
|
||||
return entries.length > 0 ? entries.join(",") : "localhost,127.0.0.1,::1,.svc,.svc.cluster.local,.cluster.local";
|
||||
}
|
||||
|
||||
@@ -307,7 +307,7 @@ function planArtifactsTask({ serviceIds = defaultServiceIds } = {}) {
|
||||
taskSpec: {
|
||||
params: [
|
||||
{ name: "git-url" },
|
||||
{ name: "git-read-url" },
|
||||
{ name: "gitops-read-url" },
|
||||
{ name: "gitops-branch" },
|
||||
{ name: "lane" },
|
||||
{ name: "revision" },
|
||||
@@ -338,7 +338,7 @@ function planArtifactsTask({ serviceIds = defaultServiceIds } = {}) {
|
||||
},
|
||||
params: [
|
||||
{ name: "git-url", value: "$(params.git-url)" },
|
||||
{ name: "git-read-url", value: "$(params.git-read-url)" },
|
||||
{ name: "gitops-read-url", value: "$(params.gitops-read-url)" },
|
||||
{ name: "gitops-branch", value: "$(params.gitops-branch)" },
|
||||
{ name: "lane", value: "$(params.lane)" },
|
||||
{ name: "revision", value: "$(params.revision)" },
|
||||
@@ -516,11 +516,11 @@ function tektonTasks(args = { lane: "node" }, deploy = null) {
|
||||
name: "prepare-source",
|
||||
taskSpec: {
|
||||
params: [
|
||||
{ name: "git-url" }, { name: "git-read-url" }, { name: "source-branch" },
|
||||
{ name: "git-url" }, { name: "git-read-url" }, { name: "gitops-read-url" }, { name: "source-branch" },
|
||||
{ name: "gitops-branch" }, { name: "lane" }, { name: "catalog-path" },
|
||||
{ name: "image-tag-mode" }, { name: "registry-prefix" }, { name: "services" }, { name: "revision" }
|
||||
],
|
||||
workspaces: [{ name: "source" }, { name: "git-ssh" }],
|
||||
workspaces: [{ name: "source" }],
|
||||
steps: [{ name: "prepare-source", image: ciToolsRunnerImage, env: proxyEnv(), script: prepareSourceScript() }]
|
||||
}
|
||||
};
|
||||
@@ -532,13 +532,13 @@ function tektonTasks(args = { lane: "node" }, deploy = null) {
|
||||
name: "gitops-promote",
|
||||
taskSpec: {
|
||||
params: [
|
||||
{ name: "git-url" }, { name: "git-read-url" }, { name: "git-write-url" },
|
||||
{ name: "git-url" }, { name: "git-read-url" }, { name: "gitops-read-url" }, { name: "git-write-url" }, { name: "gitops-username" },
|
||||
{ name: "source-branch" }, { name: "gitops-branch" }, { name: "lane" },
|
||||
{ name: "catalog-path" }, { name: "image-tag-mode" }, { name: "runtime-path" },
|
||||
{ name: "revision" }, { name: "registry-prefix" }
|
||||
],
|
||||
results: [{ name: "runtime-ready-required", description: "true when GitOps promotion changed runtime desired state and runtime readiness must be observed" }],
|
||||
workspaces: [{ name: "source" }, { name: "git-ssh" }],
|
||||
workspaces: [{ name: "source" }, { name: "gitea-auth" }],
|
||||
steps: [{ name: "promote", image: ciToolsRunnerImage, env: proxyEnv(), script: gitopsPromoteScript() }]
|
||||
}
|
||||
},
|
||||
@@ -576,7 +576,9 @@ function tektonPipeline(args = { lane: "node" }, deploy = null) {
|
||||
params: [
|
||||
{ name: "git-url", type: "string", default: defaultSourceRepo },
|
||||
{ name: "git-read-url", type: "string", default: args.gitReadUrl },
|
||||
{ name: "gitops-read-url", type: "string", default: args.gitReadUrl },
|
||||
{ name: "git-write-url", type: "string", default: args.gitWriteUrl },
|
||||
{ name: "gitops-username", type: "string", default: "unidesk-admin" },
|
||||
{ name: "source-branch", type: "string", default: args.sourceBranch },
|
||||
{ name: "gitops-branch", type: "string", default: args.gitopsBranch },
|
||||
{ name: "lane", type: "string", default: settings.lane },
|
||||
@@ -596,19 +598,19 @@ function tektonPipeline(args = { lane: "node" }, deploy = null) {
|
||||
],
|
||||
workspaces: [
|
||||
{ name: "source" },
|
||||
{ name: "git-ssh" }
|
||||
{ name: "gitea-auth" }
|
||||
],
|
||||
tasks: [
|
||||
{
|
||||
name: "prepare-source",
|
||||
workspaces: [
|
||||
{ name: "source", workspace: "source" },
|
||||
{ name: "git-ssh", workspace: "git-ssh" }
|
||||
{ name: "source", workspace: "source" }
|
||||
],
|
||||
taskSpec: {
|
||||
params: [
|
||||
{ name: "git-url" },
|
||||
{ name: "git-read-url" },
|
||||
{ name: "gitops-read-url" },
|
||||
{ name: "source-branch" },
|
||||
{ name: "gitops-branch" },
|
||||
{ name: "lane" },
|
||||
@@ -618,12 +620,13 @@ function tektonPipeline(args = { lane: "node" }, deploy = null) {
|
||||
{ name: "services" },
|
||||
{ name: "revision" }
|
||||
],
|
||||
workspaces: [{ name: "source" }, { name: "git-ssh" }],
|
||||
workspaces: [{ name: "source" }],
|
||||
steps: [{ name: "prepare-source", image: ciToolsRunnerImage, env: proxyEnv(), script: prepareSourceScript() }]
|
||||
},
|
||||
params: [
|
||||
{ name: "git-url", value: "$(params.git-url)" },
|
||||
{ name: "git-read-url", value: "$(params.git-read-url)" },
|
||||
{ name: "gitops-read-url", value: "$(params.gitops-read-url)" },
|
||||
{ name: "source-branch", value: "$(params.source-branch)" },
|
||||
{ name: "gitops-branch", value: "$(params.gitops-branch)" },
|
||||
{ name: "lane", value: "$(params.lane)" },
|
||||
@@ -641,13 +644,15 @@ function tektonPipeline(args = { lane: "node" }, deploy = null) {
|
||||
runAfter: ["collect-artifacts"],
|
||||
workspaces: [
|
||||
{ name: "source", workspace: "source" },
|
||||
{ name: "git-ssh", workspace: "git-ssh" }
|
||||
{ name: "gitea-auth", workspace: "gitea-auth" }
|
||||
],
|
||||
taskSpec: {
|
||||
params: [
|
||||
{ name: "git-url" },
|
||||
{ name: "git-read-url" },
|
||||
{ name: "gitops-read-url" },
|
||||
{ name: "git-write-url" },
|
||||
{ name: "gitops-username" },
|
||||
{ name: "source-branch" },
|
||||
{ name: "gitops-branch" },
|
||||
{ name: "lane" },
|
||||
@@ -658,13 +663,15 @@ function tektonPipeline(args = { lane: "node" }, deploy = null) {
|
||||
{ name: "registry-prefix" }
|
||||
],
|
||||
results: [{ name: "runtime-ready-required", description: "true when GitOps promotion changed runtime desired state and runtime readiness must be observed" }],
|
||||
workspaces: [{ name: "source" }, { name: "git-ssh" }],
|
||||
workspaces: [{ name: "source" }, { name: "gitea-auth" }],
|
||||
steps: [{ name: "promote", image: ciToolsRunnerImage, env: proxyEnv(), script: gitopsPromoteScript() }]
|
||||
},
|
||||
params: [
|
||||
{ name: "git-url", value: "$(params.git-url)" },
|
||||
{ name: "git-read-url", value: "$(params.git-read-url)" },
|
||||
{ name: "gitops-read-url", value: "$(params.gitops-read-url)" },
|
||||
{ name: "git-write-url", value: "$(params.git-write-url)" },
|
||||
{ name: "gitops-username", value: "$(params.gitops-username)" },
|
||||
{ name: "source-branch", value: "$(params.source-branch)" },
|
||||
{ name: "gitops-branch", value: "$(params.gitops-branch)" },
|
||||
{ name: "lane", value: "$(params.lane)" },
|
||||
@@ -709,7 +716,9 @@ function tektonPipelineRunTemplate({ source, args, deploy = null }) {
|
||||
params: [
|
||||
{ name: "git-url", value: args.sourceRepo },
|
||||
{ name: "git-read-url", value: args.gitReadUrl },
|
||||
{ name: "gitops-read-url", value: args.gitReadUrl },
|
||||
{ name: "git-write-url", value: args.gitWriteUrl },
|
||||
{ name: "gitops-username", value: "unidesk-admin" },
|
||||
{ name: "source-branch", value: args.sourceBranch },
|
||||
{ name: "gitops-branch", value: args.gitopsBranch },
|
||||
{ name: "lane", value: settings.lane },
|
||||
@@ -723,7 +732,7 @@ function tektonPipelineRunTemplate({ source, args, deploy = null }) {
|
||||
],
|
||||
workspaces: [
|
||||
{ name: "source", volumeClaimTemplate: { spec: { accessModes: ["ReadWriteOnce"], resources: { requests: { storage: "8Gi" } } } } },
|
||||
{ name: "git-ssh", secret: { secretName: "hwlab-git-ssh" } }
|
||||
{ name: "gitea-auth", secret: { secretName: "pac-gitea-hwlab", items: [{ key: "token", path: "token" }] } }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
@@ -63,7 +63,6 @@ function gitSshShellFunction() {
|
||||
function prepareSourceScript() {
|
||||
return renderTemplate("prepare-source.sh", {
|
||||
"# __HWLAB_CI_TIMING_SHELL__\n": ciTimingShellFunction(),
|
||||
"# __HWLAB_GIT_SSH_SHELL__\n": gitSshShellFunction(),
|
||||
"__HWLAB_CI_TOOLS_IMAGE__": ciToolsRunnerImage,
|
||||
"__HWLAB_V02_RUNTIME_ENDPOINT__": JSON.stringify(defaultV02RuntimeEndpoint).slice(1, -1),
|
||||
"__HWLAB_VALIDATION_TASK_COUNT__": primitiveValidationTasks.length
|
||||
@@ -140,7 +139,6 @@ function collectArtifactsScript() {
|
||||
function gitopsPromoteScript() {
|
||||
return renderTemplate("gitops-promote.sh", {
|
||||
"# __HWLAB_CI_TIMING_SHELL__\n": ciTimingShellFunction(),
|
||||
"# __HWLAB_GIT_SSH_SHELL__\n": gitSshShellFunction(),
|
||||
"__HWLAB_CI_TOOLS_IMAGE__": ciToolsRunnerImage
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
repo_url="ssh://git@ssh.github.com:443/pikasTech/HWLAB.git"
|
||||
repo_path="/cache/pikasTech/HWLAB.git"
|
||||
lock_dir="/cache/.hwlab-flush.lock"
|
||||
started_ms=$(node -e 'console.log(Date.now())')
|
||||
now_ms() { node -e 'console.log(Date.now())'; }
|
||||
emit_timing() {
|
||||
phase="$1"
|
||||
status="$2"
|
||||
started="$3"
|
||||
finished=$(now_ms)
|
||||
duration=$((finished - started))
|
||||
printf '{"event":"git-mirror-flush-timing","phase":"%s","status":"%s","durationMs":%s,"repository":"pikasTech/HWLAB"}
|
||||
' "$phase" "$status" "$duration"
|
||||
}
|
||||
if ! mkdir "$lock_dir" 2>/dev/null; then
|
||||
echo "git mirror flush already running"
|
||||
exit 0
|
||||
fi
|
||||
trap 'rmdir "$lock_dir" 2>/dev/null || true' EXIT INT TERM
|
||||
mkdir -p /root/.ssh
|
||||
cp /git-ssh/ssh-privatekey /root/.ssh/id_rsa
|
||||
chmod 0400 /root/.ssh/id_rsa
|
||||
# __HWLAB_GIT_MIRROR_SSH_PRELUDE__
|
||||
/script/install-hooks.sh
|
||||
for gitops_branch in __HWLAB_GITOPS_BRANCH_ARGS__; do
|
||||
local_head=$(git -C "$repo_path" show-ref --verify --hash "refs/heads/$gitops_branch" 2>/dev/null || true)
|
||||
if [ -z "$local_head" ]; then
|
||||
echo "git mirror flush skips missing local refs/heads/$gitops_branch"
|
||||
continue
|
||||
fi
|
||||
fetch_started=$(now_ms)
|
||||
timeout 90 git -C "$repo_path" fetch --quiet "$repo_url" "refs/heads/$gitops_branch:refs/mirror-stage/heads/$gitops_branch"
|
||||
emit_timing "fetch-$gitops_branch" succeeded "$fetch_started"
|
||||
github_head=$(git -C "$repo_path" show-ref --verify --hash "refs/mirror-stage/heads/$gitops_branch" 2>/dev/null || true)
|
||||
if [ -n "$github_head" ] && [ "$github_head" != "$local_head" ] && ! git -C "$repo_path" merge-base --is-ancestor "$github_head" "$local_head"; then
|
||||
echo "git mirror flush rejected divergent $gitops_branch local=$local_head github=$github_head" >&2
|
||||
exit 52
|
||||
fi
|
||||
if [ "$local_head" != "$github_head" ]; then
|
||||
push_started=$(now_ms)
|
||||
timeout 120 git -C "$repo_path" push "$repo_url" "$local_head:refs/heads/$gitops_branch"
|
||||
emit_timing "push-$gitops_branch" succeeded "$push_started"
|
||||
else
|
||||
echo "git mirror flush $gitops_branch already matches GitHub"
|
||||
fi
|
||||
git -C "$repo_path" update-ref "refs/mirror-stage/heads/$gitops_branch" "$local_head"
|
||||
done
|
||||
git -C "$repo_path" update-server-info
|
||||
flushed_at=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
export flushed_at
|
||||
export gitops_branches_json=__HWLAB_GITOPS_BRANCHES_JSON_SHELL__
|
||||
node - <<'NODE' | tee /cache/HWLAB.last-flush.json
|
||||
const { execFileSync } = require("node:child_process");
|
||||
const repo = "/cache/pikasTech/HWLAB.git";
|
||||
const gitopsBranches = JSON.parse(process.env.gitops_branches_json || "[]");
|
||||
function rev(ref) {
|
||||
try { return execFileSync("git", ["-C", repo, "rev-parse", ref], { encoding: "utf8" }).trim() || null; } catch { return null; }
|
||||
}
|
||||
const refs = {};
|
||||
for (const branch of gitopsBranches) {
|
||||
refs["refs/heads/" + branch] = rev("refs/heads/" + branch);
|
||||
refs["refs/mirror-stage/heads/" + branch] = rev("refs/mirror-stage/heads/" + branch);
|
||||
}
|
||||
const pendingFlush = gitopsBranches.some((branch) => refs["refs/heads/" + branch] && refs["refs/mirror-stage/heads/" + branch] && refs["refs/heads/" + branch] !== refs["refs/mirror-stage/heads/" + branch]);
|
||||
console.log(JSON.stringify({
|
||||
event: "git-mirror-flush",
|
||||
status: "flushed",
|
||||
repository: "pikasTech/HWLAB",
|
||||
flushedAt: process.env.flushed_at,
|
||||
pendingFlush,
|
||||
refs
|
||||
}));
|
||||
NODE
|
||||
emit_timing total succeeded "$started_ms"
|
||||
@@ -1,196 +0,0 @@
|
||||
import { createServer } from "node:http";
|
||||
import { spawn } from "node:child_process";
|
||||
import { createReadStream, statSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { createGunzip, createInflate } from "node:zlib";
|
||||
|
||||
const cacheRoot = process.env.GIT_MIRROR_CACHE_ROOT || "/cache";
|
||||
const port = Number(process.env.PORT || 8080);
|
||||
|
||||
createServer((req, res) => {
|
||||
handle(req, res).catch((error) => {
|
||||
if (!res.headersSent) res.writeHead(500, { "content-type": "application/json" });
|
||||
res.end(JSON.stringify({ ok: false, error: error.message }));
|
||||
});
|
||||
}).listen(port, "0.0.0.0", () => {
|
||||
console.log(JSON.stringify({ event: "git-mirror-smart-http-listening", port, cacheRoot }));
|
||||
});
|
||||
|
||||
async function handle(req, res) {
|
||||
const url = new URL(req.url || "/", "http://git-mirror-http");
|
||||
const writeHost = isWriteHost(req.headers.host || "");
|
||||
if (req.method === "GET" && (url.pathname === "/" || url.pathname === "/health")) {
|
||||
res.writeHead(200, { "content-type": "application/json", "cache-control": "no-cache" });
|
||||
res.end(JSON.stringify({ ok: true, service: "git-mirror-smart-http", writeHost }));
|
||||
return;
|
||||
}
|
||||
if (req.method === "GET" && url.pathname.endsWith("/info/refs") && url.searchParams.get("service") === "git-upload-pack") {
|
||||
await runUploadPackAdvertisement(repoPathFromGitServicePath(url.pathname, "/info/refs"), res);
|
||||
return;
|
||||
}
|
||||
if (req.method === "POST" && url.pathname.endsWith("/git-upload-pack")) {
|
||||
await runUploadPackRpc(repoPathFromGitServicePath(url.pathname, "/git-upload-pack"), req, res);
|
||||
return;
|
||||
}
|
||||
if (req.method === "GET" && url.pathname.endsWith("/info/refs") && url.searchParams.get("service") === "git-receive-pack") {
|
||||
if (!writeHost) return rejectReadOnly(res);
|
||||
await runReceivePackAdvertisement(repoPathFromGitServicePath(url.pathname, "/info/refs"), res);
|
||||
return;
|
||||
}
|
||||
if (req.method === "POST" && url.pathname.endsWith("/git-receive-pack")) {
|
||||
if (!writeHost) return rejectReadOnly(res);
|
||||
await runReceivePackRpc(repoPathFromGitServicePath(url.pathname, "/git-receive-pack"), req, res);
|
||||
return;
|
||||
}
|
||||
if (req.method === "GET" || req.method === "HEAD") {
|
||||
serveStaticFile(url.pathname, req, res);
|
||||
return;
|
||||
}
|
||||
res.writeHead(405, { "content-type": "text/plain" });
|
||||
res.end("method not allowed\n");
|
||||
}
|
||||
|
||||
function isWriteHost(hostHeader) {
|
||||
const host = String(hostHeader || "").split(":", 1)[0].toLowerCase();
|
||||
return host === "git-mirror-write" || host.startsWith("git-mirror-write.");
|
||||
}
|
||||
|
||||
function rejectReadOnly(res) {
|
||||
res.writeHead(403, { "content-type": "application/json", "cache-control": "no-cache" });
|
||||
res.end(JSON.stringify({ ok: false, error: "git mirror receive-pack is only available through git-mirror-write" }));
|
||||
}
|
||||
|
||||
function repoPathFromGitServicePath(urlPath, suffix) {
|
||||
const repoUrlPath = urlPath.slice(0, -suffix.length);
|
||||
if (!repoUrlPath.endsWith(".git")) throw new Error(`unsupported git repo path: ${urlPath}`);
|
||||
return safePath(repoUrlPath);
|
||||
}
|
||||
|
||||
function safePath(urlPath) {
|
||||
const decoded = decodeURIComponent(urlPath.replace(/^[/]+/u, ""));
|
||||
const fullPath = path.resolve(cacheRoot, decoded);
|
||||
const normalizedRoot = path.resolve(cacheRoot);
|
||||
if (fullPath !== normalizedRoot && !fullPath.startsWith(`${normalizedRoot}${path.sep}`)) throw new Error("path escapes cache root");
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
function smartHeaders(contentType) {
|
||||
return {
|
||||
"content-type": contentType,
|
||||
"cache-control": "no-cache, max-age=0, must-revalidate",
|
||||
expires: "Fri, 01 Jan 1980 00:00:00 GMT",
|
||||
pragma: "no-cache"
|
||||
};
|
||||
}
|
||||
|
||||
function pktLine(text) {
|
||||
const length = Buffer.byteLength(text) + 4;
|
||||
return `${length.toString(16).padStart(4, "0")}${text}`;
|
||||
}
|
||||
|
||||
function requestBodyStream(req) {
|
||||
const encoding = String(req.headers["content-encoding"] || "identity").toLowerCase();
|
||||
if (encoding === "identity" || encoding === "") return req;
|
||||
if (encoding === "gzip" || encoding === "x-gzip") return req.pipe(createGunzip());
|
||||
if (encoding === "deflate") return req.pipe(createInflate());
|
||||
throw new Error(`unsupported git upload-pack content-encoding: ${encoding}`);
|
||||
}
|
||||
|
||||
function runUploadPackAdvertisement(repoPath, res) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const child = spawn("git-upload-pack", ["--stateless-rpc", "--advertise-refs", repoPath], { stdio: ["ignore", "pipe", "pipe"] });
|
||||
let stderr = "";
|
||||
child.stderr.on("data", (chunk) => { stderr += chunk; process.stderr.write(chunk); });
|
||||
child.on("error", reject);
|
||||
child.on("close", (code) => {
|
||||
if (code !== 0 && !res.headersSent) reject(new Error(`git-upload-pack advertise failed: ${stderr.trim()}`));
|
||||
else resolve();
|
||||
});
|
||||
res.writeHead(200, smartHeaders("application/x-git-upload-pack-advertisement"));
|
||||
res.write(pktLine("# service=git-upload-pack\n"));
|
||||
res.write("0000");
|
||||
child.stdout.pipe(res, { end: false });
|
||||
child.stdout.on("end", () => res.end());
|
||||
});
|
||||
}
|
||||
|
||||
function runUploadPackRpc(repoPath, req, res) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const child = spawn("git-upload-pack", ["--stateless-rpc", repoPath], { stdio: ["pipe", "pipe", "pipe"] });
|
||||
let stderr = "";
|
||||
child.stderr.on("data", (chunk) => { stderr += chunk; process.stderr.write(chunk); });
|
||||
child.on("error", reject);
|
||||
child.on("close", (code) => {
|
||||
if (code !== 0 && !res.headersSent) reject(new Error(`git-upload-pack rpc failed: ${stderr.trim()}`));
|
||||
else resolve();
|
||||
});
|
||||
res.writeHead(200, smartHeaders("application/x-git-upload-pack-result"));
|
||||
const body = requestBodyStream(req);
|
||||
body.on("error", (error) => child.stdin.destroy(error));
|
||||
body.pipe(child.stdin);
|
||||
child.stdout.pipe(res);
|
||||
});
|
||||
}
|
||||
|
||||
function runReceivePackAdvertisement(repoPath, res) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const child = spawn("git-receive-pack", ["--stateless-rpc", "--advertise-refs", repoPath], { stdio: ["ignore", "pipe", "pipe"] });
|
||||
let stderr = "";
|
||||
child.stderr.on("data", (chunk) => { stderr += chunk; process.stderr.write(chunk); });
|
||||
child.on("error", reject);
|
||||
child.on("close", (code) => {
|
||||
if (code !== 0 && !res.headersSent) reject(new Error(`git-receive-pack advertise failed: ${stderr.trim()}`));
|
||||
else resolve();
|
||||
});
|
||||
res.writeHead(200, smartHeaders("application/x-git-receive-pack-advertisement"));
|
||||
res.write(pktLine("# service=git-receive-pack\n"));
|
||||
res.write("0000");
|
||||
child.stdout.pipe(res, { end: false });
|
||||
child.stdout.on("end", () => res.end());
|
||||
});
|
||||
}
|
||||
|
||||
function runReceivePackRpc(repoPath, req, res) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const child = spawn("git-receive-pack", ["--stateless-rpc", repoPath], { stdio: ["pipe", "pipe", "pipe"] });
|
||||
let stderr = "";
|
||||
child.stderr.on("data", (chunk) => { stderr += chunk; process.stderr.write(chunk); });
|
||||
child.on("error", reject);
|
||||
child.on("close", (code) => {
|
||||
if (code !== 0 && !res.headersSent) reject(new Error(`git-receive-pack rpc failed: ${stderr.trim()}`));
|
||||
else resolve();
|
||||
});
|
||||
res.writeHead(200, smartHeaders("application/x-git-receive-pack-result"));
|
||||
const body = requestBodyStream(req);
|
||||
body.on("error", (error) => child.stdin.destroy(error));
|
||||
body.pipe(child.stdin);
|
||||
child.stdout.pipe(res);
|
||||
});
|
||||
}
|
||||
|
||||
function serveStaticFile(urlPath, req, res) {
|
||||
const fullPath = safePath(urlPath);
|
||||
let stat;
|
||||
try { stat = statSync(fullPath); } catch {
|
||||
res.writeHead(404, { "content-type": "text/plain" });
|
||||
res.end("not found\n");
|
||||
return;
|
||||
}
|
||||
if (!stat.isFile()) {
|
||||
res.writeHead(404, { "content-type": "text/plain" });
|
||||
res.end("not found\n");
|
||||
return;
|
||||
}
|
||||
res.writeHead(200, { "content-length": stat.size, "content-type": contentType(fullPath), "cache-control": "no-cache" });
|
||||
if (req.method === "HEAD") {
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
createReadStream(fullPath).pipe(res);
|
||||
}
|
||||
|
||||
function contentType(filePath) {
|
||||
if (filePath.endsWith(".pack")) return "application/x-git-packed-objects";
|
||||
if (filePath.endsWith(".idx")) return "application/x-git-packed-objects-toc";
|
||||
return "text/plain";
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
repo_path="/cache/pikasTech/HWLAB.git"
|
||||
mkdir -p "$repo_path/hooks"
|
||||
cat > "$repo_path/hooks/pre-receive" <<'HOOK'
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
zero="0000000000000000000000000000000000000000"
|
||||
status=0
|
||||
while read -r old new ref; do
|
||||
if [ "$new" = "$zero" ]; then
|
||||
echo "git mirror write rejected: deleting $ref is forbidden" >&2
|
||||
status=1
|
||||
continue
|
||||
fi
|
||||
git cat-file -e "$new^{commit}" || status=1
|
||||
git cat-file -e "$new^{tree}" || status=1
|
||||
if git rev-list --objects --missing=print "$new" | grep -q '^?'; then
|
||||
echo "git mirror write rejected: missing objects for $new" >&2
|
||||
status=1
|
||||
continue
|
||||
fi
|
||||
if [ "$old" != "$zero" ] && ! git merge-base --is-ancestor "$old" "$new"; then
|
||||
echo "git mirror write rejected: non-fast-forward $ref" >&2
|
||||
status=1
|
||||
continue
|
||||
fi
|
||||
done
|
||||
exit "$status"
|
||||
HOOK
|
||||
cat > "$repo_path/hooks/post-receive" <<'HOOK'
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
repo_path=$(git rev-parse --git-dir)
|
||||
git -C "$repo_path" update-server-info
|
||||
written_at=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
export repo_path written_at
|
||||
export gitops_branches_json=__HWLAB_GITOPS_BRANCHES_JSON_SHELL__
|
||||
node - <<'NODE' > /cache/HWLAB.last-write.json
|
||||
const { execFileSync } = require("node:child_process");
|
||||
const repo = process.env.repo_path || "/cache/pikasTech/HWLAB.git";
|
||||
const gitopsBranches = JSON.parse(process.env.gitops_branches_json || "[]");
|
||||
function rev(ref) {
|
||||
try { return execFileSync("git", ["-C", repo, "rev-parse", ref], { encoding: "utf8" }).trim() || null; } catch { return null; }
|
||||
}
|
||||
const refs = {};
|
||||
for (const branch of gitopsBranches) {
|
||||
refs["refs/heads/" + branch] = rev("refs/heads/" + branch);
|
||||
refs["refs/mirror-stage/heads/" + branch] = rev("refs/mirror-stage/heads/" + branch);
|
||||
}
|
||||
const pendingFlush = gitopsBranches.some((branch) => refs["refs/heads/" + branch] && refs["refs/heads/" + branch] !== refs["refs/mirror-stage/heads/" + branch]);
|
||||
console.log(JSON.stringify({
|
||||
event: "git-mirror-write",
|
||||
status: "received",
|
||||
repository: "pikasTech/HWLAB",
|
||||
writtenAt: process.env.written_at,
|
||||
pendingFlush,
|
||||
refs
|
||||
}));
|
||||
NODE
|
||||
HOOK
|
||||
chmod 0755 "$repo_path/hooks/pre-receive" "$repo_path/hooks/post-receive"
|
||||
git -C "$repo_path" config http.receivepack true
|
||||
git -C "$repo_path" config receive.denyDeletes true
|
||||
git -C "$repo_path" config receive.denyNonFastForwards true
|
||||
@@ -1,48 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
import net from "node:net";
|
||||
const [proxyHost, proxyPortRaw, targetHost, targetPortRaw] = process.argv.slice(2);
|
||||
const proxyPort = Number.parseInt(proxyPortRaw || "", 10);
|
||||
const targetPort = Number.parseInt(targetPortRaw || "", 10);
|
||||
if (!proxyHost || !Number.isInteger(proxyPort) || !targetHost || !Number.isInteger(targetPort)) {
|
||||
console.error("hwlab git-mirror proxy-connect: invalid ProxyCommand arguments");
|
||||
process.exit(64);
|
||||
}
|
||||
let settled = false;
|
||||
let tunnelEstablished = false;
|
||||
function finish(code, message) {
|
||||
if (settled) return;
|
||||
settled = true;
|
||||
if (message) console.error("hwlab git-mirror proxy-connect: " + message);
|
||||
process.exit(code);
|
||||
}
|
||||
const socket = net.createConnection({ host: proxyHost, port: proxyPort });
|
||||
let buffer = Buffer.alloc(0);
|
||||
socket.setTimeout(15000, () => { socket.destroy(); finish(65, "timeout connecting via " + proxyHost + ":" + proxyPort + " to " + targetHost + ":" + targetPort); });
|
||||
socket.on("connect", () => socket.write("CONNECT " + targetHost + ":" + targetPort + " HTTP/1.1\r\nHost: " + targetHost + ":" + targetPort + "\r\nProxy-Connection: Keep-Alive\r\n\r\n"));
|
||||
socket.on("error", (error) => finish(tunnelEstablished ? 69 : 66, (tunnelEstablished ? "tunnel socket error: " : "tcp error connecting to proxy: ") + (error && error.message ? error.message : String(error))));
|
||||
socket.on("close", () => { if (!tunnelEstablished) finish(68, "proxy closed before CONNECT completed via " + proxyHost + ":" + proxyPort + " to " + targetHost + ":" + targetPort); else finish(0); });
|
||||
function onData(chunk) {
|
||||
buffer = Buffer.concat([buffer, chunk]);
|
||||
const headerEnd = buffer.indexOf("\r\n\r\n");
|
||||
if (headerEnd === -1 && buffer.length < 8192) return;
|
||||
if (headerEnd === -1) { socket.destroy(); finish(68, "proxy response header exceeded 8192 bytes before CONNECT status via " + proxyHost + ":" + proxyPort + " to " + targetHost + ":" + targetPort); return; }
|
||||
const head = buffer.slice(0, headerEnd + 4).toString("latin1");
|
||||
const statusLine = head.split("\r\n", 1)[0] || "";
|
||||
const statusCode = Number.parseInt(statusLine.split(" ")[1] || "", 10);
|
||||
if (!statusLine.startsWith("HTTP/1.") || !Number.isInteger(statusCode) || statusCode < 200 || statusCode > 299) {
|
||||
const safeStatus = statusLine.replace(/[^\x20-\x7e]/g, "?").slice(0, 160);
|
||||
socket.destroy();
|
||||
finish(67, "proxy CONNECT failed via " + proxyHost + ":" + proxyPort + " to " + targetHost + ":" + targetPort + ": " + safeStatus);
|
||||
return;
|
||||
}
|
||||
socket.off("data", onData);
|
||||
socket.setTimeout(0);
|
||||
tunnelEstablished = true;
|
||||
const rest = buffer.slice(headerEnd + 4);
|
||||
if (rest.length) process.stdout.write(rest);
|
||||
process.stdin.on("error", () => {});
|
||||
process.stdout.on("error", () => {});
|
||||
process.stdin.pipe(socket);
|
||||
socket.pipe(process.stdout);
|
||||
}
|
||||
socket.on("data", onData);
|
||||
@@ -1,11 +0,0 @@
|
||||
printf '%s\n' __HWLAB_PROXY_SUMMARY_SHELL__ >&2
|
||||
cat > /tmp/hwlab-git-ssh-proxy.sh <<'SH_PROXY'
|
||||
#!/bin/sh
|
||||
exec ssh -i /root/.ssh/id_rsa -o IdentitiesOnly=yes -o BatchMode=yes -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=/root/.ssh/known_hosts -o ConnectTimeout=15 -o ServerAliveInterval=5 -o ServerAliveCountMax=1 "$@"
|
||||
SH_PROXY
|
||||
chmod 0700 /tmp/hwlab-git-ssh-proxy.sh
|
||||
unset HTTP_PROXY HTTPS_PROXY ALL_PROXY http_proxy https_proxy all_proxy
|
||||
export NO_PROXY='*'
|
||||
export no_proxy='*'
|
||||
export GIT_SSH=/tmp/hwlab-git-ssh-proxy.sh
|
||||
unset GIT_SSH_COMMAND
|
||||
@@ -1,20 +0,0 @@
|
||||
printf '%s\n' __HWLAB_PROXY_SUMMARY_SHELL__ >&2
|
||||
cat > /tmp/hwlab-github-proxy-connect.mjs <<'NODE_PROXY'
|
||||
// __HWLAB_GIT_MIRROR_PROXY_CONNECT_MJS__
|
||||
NODE_PROXY
|
||||
chmod 0700 /tmp/hwlab-github-proxy-connect.mjs
|
||||
cat > /tmp/hwlab-git-ssh-proxy.sh <<'SH_PROXY'
|
||||
#!/bin/sh
|
||||
exec ssh -i /root/.ssh/id_rsa -o IdentitiesOnly=yes -o BatchMode=yes -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=/root/.ssh/known_hosts -o ConnectTimeout=15 -o ServerAliveInterval=5 -o ServerAliveCountMax=1 -o __HWLAB_PROXY_COMMAND_SHELL__ "$@"
|
||||
SH_PROXY
|
||||
chmod 0700 /tmp/hwlab-git-ssh-proxy.sh
|
||||
export HTTP_PROXY=__HWLAB_PROXY_URL_SHELL__
|
||||
export HTTPS_PROXY=__HWLAB_PROXY_URL_SHELL__
|
||||
export ALL_PROXY=__HWLAB_PROXY_URL_SHELL__
|
||||
export http_proxy=__HWLAB_PROXY_URL_SHELL__
|
||||
export https_proxy=__HWLAB_PROXY_URL_SHELL__
|
||||
export all_proxy=__HWLAB_PROXY_URL_SHELL__
|
||||
export NO_PROXY=__HWLAB_PROXY_NO_PROXY_SHELL__
|
||||
export no_proxy=__HWLAB_PROXY_NO_PROXY_SHELL__
|
||||
export GIT_SSH=/tmp/hwlab-git-ssh-proxy.sh
|
||||
unset GIT_SSH_COMMAND
|
||||
@@ -1,181 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
repo_url="ssh://git@ssh.github.com:443/pikasTech/HWLAB.git"
|
||||
repo_path="/cache/pikasTech/HWLAB.git"
|
||||
source_snapshot_ref_prefix=__HWLAB_SOURCE_SNAPSHOT_REF_PREFIX_SHELL__
|
||||
lock_dir="/cache/.hwlab-sync.lock"
|
||||
sync_started_ms=$(node -e 'console.log(Date.now())')
|
||||
now_ms() { node -e 'console.log(Date.now())'; }
|
||||
emit_timing() {
|
||||
phase="$1"
|
||||
status="$2"
|
||||
started_ms="$3"
|
||||
finished_ms=$(now_ms)
|
||||
duration_ms=$((finished_ms - started_ms))
|
||||
printf '{"event":"git-mirror-sync-timing","phase":"%s","status":"%s","durationMs":%s,"repository":"pikasTech/HWLAB"}
|
||||
' "$phase" "$status" "$duration_ms"
|
||||
}
|
||||
mkdir -p /cache/pikasTech /root/.ssh
|
||||
if ! mkdir "$lock_dir" 2>/dev/null; then
|
||||
echo "git mirror sync already running"
|
||||
exit 0
|
||||
fi
|
||||
trap 'rmdir "$lock_dir" 2>/dev/null || true' EXIT INT TERM
|
||||
cp /git-ssh/ssh-privatekey /root/.ssh/id_rsa
|
||||
chmod 0400 /root/.ssh/id_rsa
|
||||
# __HWLAB_GIT_MIRROR_SSH_PRELUDE__
|
||||
if [ -d "$repo_path/objects" ] && [ -f "$repo_path/HEAD" ]; then
|
||||
git -C "$repo_path" remote set-url origin "$repo_url" || git -C "$repo_path" remote add origin "$repo_url"
|
||||
else
|
||||
rm -rf "$repo_path"
|
||||
git init --bare "$repo_path"
|
||||
git -C "$repo_path" remote add origin "$repo_url"
|
||||
fi
|
||||
/script/install-hooks.sh
|
||||
git -C "$repo_path" config uploadpack.hideRefs refs/mirror-stage
|
||||
git -C "$repo_path" config uploadpack.allowReachableSHA1InWant true
|
||||
git -C "$repo_path" config uploadpack.allowAnySHA1InWant true
|
||||
git -C "$repo_path" config --unset-all remote.origin.fetch 2>/dev/null || true
|
||||
# __HWLAB_FETCH_CONFIG_COMMANDS__
|
||||
fetch_started_ms=$(now_ms)
|
||||
timeout 180 git -C "$repo_path" fetch --quiet --prune origin
|
||||
emit_timing fetch succeeded "$fetch_started_ms"
|
||||
git -C "$repo_path" for-each-ref --format='%(objectname) %(refname)' refs/mirror-stage/heads > /tmp/hwlab-stage-heads
|
||||
git -C "$repo_path" for-each-ref --format='%(refname)' refs/mirror-stage/heads > /tmp/hwlab-stage-head-refs
|
||||
git -C "$repo_path" for-each-ref --format='%(objectname) %(refname)' refs/mirror-stage/tags > /tmp/hwlab-stage-tags
|
||||
git -C "$repo_path" for-each-ref --format='%(refname)' refs/mirror-stage/tags > /tmp/hwlab-stage-tag-refs
|
||||
if [ ! -s /tmp/hwlab-stage-heads ]; then
|
||||
echo "git mirror sync fetched no branch refs" >&2
|
||||
exit 41
|
||||
fi
|
||||
for required_ref in __HWLAB_REQUIRED_REF_ARGS__; do
|
||||
git -C "$repo_path" show-ref --verify --quiet "$required_ref" || { echo "git mirror sync missing required ref $required_ref" >&2; exit 43; }
|
||||
done
|
||||
validate_started_ms=$(now_ms)
|
||||
while read -r sha ref; do
|
||||
[ -n "$sha" ] || continue
|
||||
git -C "$repo_path" cat-file -e "$sha^{commit}"
|
||||
git -C "$repo_path" cat-file -e "$sha^{tree}"
|
||||
if git -C "$repo_path" rev-list --objects --missing=print "$sha" | grep -q '^?'; then
|
||||
echo "git mirror sync found missing objects for $ref $sha" >&2
|
||||
exit 42
|
||||
fi
|
||||
done < /tmp/hwlab-stage-heads
|
||||
emit_timing validate succeeded "$validate_started_ms"
|
||||
publish_started_ms=$(now_ms)
|
||||
while read -r sha ref; do
|
||||
[ -n "$sha" ] || continue
|
||||
name=$(printf '%s
|
||||
' "$ref" | sed 's#^refs/mirror-stage/heads/##')
|
||||
is_gitops_branch=false
|
||||
for gitops_branch in __HWLAB_GITOPS_BRANCH_ARGS__; do
|
||||
if [ "$name" = "$gitops_branch" ]; then is_gitops_branch=true; break; fi
|
||||
done
|
||||
if [ "$is_gitops_branch" = true ]; then
|
||||
local_sha=$(git -C "$repo_path" show-ref --verify --hash "refs/heads/$name" 2>/dev/null || true)
|
||||
if [ -n "$local_sha" ] && [ "$local_sha" != "$sha" ]; then
|
||||
if git -C "$repo_path" merge-base --is-ancestor "$sha" "$local_sha"; then
|
||||
echo "git mirror sync keeps local $name ahead of GitHub"
|
||||
continue
|
||||
fi
|
||||
if ! git -C "$repo_path" merge-base --is-ancestor "$local_sha" "$sha"; then
|
||||
echo "git mirror sync found divergent $name local=$local_sha github=$sha" >&2
|
||||
exit 44
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
git -C "$repo_path" update-ref "refs/heads/$name" "$sha"
|
||||
done < /tmp/hwlab-stage-heads
|
||||
for source_branch in __HWLAB_SOURCE_BRANCH_ARGS__; do
|
||||
source_sha=$(git -C "$repo_path" show-ref --verify --hash "refs/heads/$source_branch" 2>/dev/null || true)
|
||||
if [ -n "$source_sha" ]; then
|
||||
source_stage_ref="${source_snapshot_ref_prefix%/}/$source_branch/$source_sha"
|
||||
git -C "$repo_path" update-ref "$source_stage_ref" "$source_sha"
|
||||
fi
|
||||
done
|
||||
while read -r sha ref; do
|
||||
[ -n "$sha" ] || continue
|
||||
name=$(printf '%s
|
||||
' "$ref" | sed 's#^refs/mirror-stage/tags/##')
|
||||
git -C "$repo_path" update-ref "refs/tags/$name" "$sha"
|
||||
done < /tmp/hwlab-stage-tags
|
||||
git -C "$repo_path" for-each-ref --format='%(refname)' refs/heads > /tmp/hwlab-public-heads
|
||||
while read -r ref; do
|
||||
[ -n "$ref" ] || continue
|
||||
name=$(printf '%s
|
||||
' "$ref" | sed 's#^refs/heads/##')
|
||||
if ! grep -Fxq "refs/mirror-stage/heads/$name" /tmp/hwlab-stage-head-refs; then
|
||||
git -C "$repo_path" update-ref -d "$ref"
|
||||
fi
|
||||
done < /tmp/hwlab-public-heads
|
||||
git -C "$repo_path" for-each-ref --format='%(refname)' refs/tags > /tmp/hwlab-public-tags
|
||||
while read -r ref; do
|
||||
[ -n "$ref" ] || continue
|
||||
name=$(printf '%s
|
||||
' "$ref" | sed 's#^refs/tags/##')
|
||||
if ! grep -Fxq "refs/mirror-stage/tags/$name" /tmp/hwlab-stage-tag-refs; then
|
||||
git -C "$repo_path" update-ref -d "$ref"
|
||||
fi
|
||||
done < /tmp/hwlab-public-tags
|
||||
emit_timing publish succeeded "$publish_started_ms"
|
||||
for head_branch in __HWLAB_SOURCE_BRANCH_ARGS__; do
|
||||
if git -C "$repo_path" show-ref --verify --quiet "refs/heads/$head_branch"; then
|
||||
git -C "$repo_path" symbolic-ref HEAD "refs/heads/$head_branch"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fsck_started_ms=$(now_ms)
|
||||
git -C "$repo_path" fsck --connectivity-only --no-dangling >/tmp/hwlab-git-fsck.out
|
||||
emit_timing fsck succeeded "$fsck_started_ms"
|
||||
git -C "$repo_path" update-server-info
|
||||
published_at=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
for source_branch in __HWLAB_SOURCE_BRANCH_ARGS__; do
|
||||
git -C "$repo_path" rev-parse "refs/heads/$source_branch" 2>/dev/null | tee "/cache/HWLAB-$source_branch.head" >/dev/null || true
|
||||
done
|
||||
printf '%s
|
||||
' "$published_at" > /cache/HWLAB.last-sync
|
||||
export published_at
|
||||
export source_snapshot_ref_prefix
|
||||
export mirror_branches_json=__HWLAB_MIRROR_BRANCHES_JSON_SHELL__
|
||||
export source_branches_json=__HWLAB_SOURCE_BRANCHES_JSON_SHELL__
|
||||
export gitops_branches_json=__HWLAB_GITOPS_BRANCHES_JSON_SHELL__
|
||||
node - <<'NODE' | tee /cache/HWLAB.last-sync.json
|
||||
const { execFileSync } = require("node:child_process");
|
||||
const repo = "/cache/pikasTech/HWLAB.git";
|
||||
const mirrorBranches = JSON.parse(process.env.mirror_branches_json || "[]");
|
||||
const sourceBranches = JSON.parse(process.env.source_branches_json || "[]");
|
||||
const gitopsBranches = JSON.parse(process.env.gitops_branches_json || "[]");
|
||||
const sourceSnapshotRefPrefix = (process.env.source_snapshot_ref_prefix || "refs/unidesk/snapshots/hwlab-node-runtime").replace(//+$/u, "");
|
||||
function rev(ref) {
|
||||
try { return execFileSync("git", ["-C", repo, "rev-parse", ref], { encoding: "utf8" }).trim() || null; } catch { return null; }
|
||||
}
|
||||
const refs = {};
|
||||
for (const branch of mirrorBranches) {
|
||||
refs["refs/heads/" + branch] = rev("refs/heads/" + branch);
|
||||
refs["refs/mirror-stage/heads/" + branch] = rev("refs/mirror-stage/heads/" + branch);
|
||||
}
|
||||
const sourceSnapshots = {};
|
||||
for (const branch of sourceBranches) {
|
||||
const source = refs["refs/heads/" + branch] || null;
|
||||
const stageRef = source ? sourceSnapshotRefPrefix + "/" + branch + "/" + source : null;
|
||||
const sourceSnapshot = stageRef ? rev(stageRef) : null;
|
||||
if (stageRef) refs[stageRef] = sourceSnapshot;
|
||||
sourceSnapshots[branch] = { stageRef, sourceSnapshot };
|
||||
}
|
||||
const sourceInSync = sourceBranches.every((branch) => refs["refs/heads/" + branch] && refs["refs/heads/" + branch] === refs["refs/mirror-stage/heads/" + branch] && sourceSnapshots[branch]?.sourceSnapshot === refs["refs/mirror-stage/heads/" + branch]);
|
||||
const gitopsInSync = gitopsBranches.every((branch) => refs["refs/heads/" + branch] && refs["refs/heads/" + branch] === refs["refs/mirror-stage/heads/" + branch]);
|
||||
const pendingFlush = gitopsBranches.some((branch) => refs["refs/heads/" + branch] && refs["refs/mirror-stage/heads/" + branch] && refs["refs/heads/" + branch] !== refs["refs/mirror-stage/heads/" + branch]);
|
||||
const payload = {
|
||||
event: "git-mirror-sync",
|
||||
status: "published",
|
||||
repository: "pikasTech/HWLAB",
|
||||
publishedAt: process.env.published_at,
|
||||
pendingFlush,
|
||||
sourceInSync,
|
||||
gitopsInSync,
|
||||
sourceSnapshots,
|
||||
refs
|
||||
};
|
||||
console.log(JSON.stringify(payload));
|
||||
NODE
|
||||
emit_timing total succeeded "$sync_started_ms"
|
||||
@@ -8,9 +8,6 @@ export HWLAB_TEKTON_TASK="gitops-promote"
|
||||
export HWLAB_SOURCE_REVISION="$(params.revision)"
|
||||
echo '{"event":"ci-base-image","phase":"gitops-promote","image":"__HWLAB_CI_TOOLS_IMAGE__","policy":"no-runtime-apt"}'
|
||||
for tool in node git timeout; do command -v "$tool" >/dev/null 2>&1 || { echo '{"event":"ci-base-image","phase":"gitops-promote","ok":false,"reason":"missing-tool","tool":"'"$tool"'"}'; exit 31; }; done
|
||||
# __HWLAB_GIT_SSH_SHELL__
|
||||
|
||||
git_url_requires_ssh() { case "$1" in git@*|ssh://*) return 0 ;; *) return 1 ;; esac; }
|
||||
lane="$(params.lane)"
|
||||
case "$lane" in
|
||||
node) runtime_lane=false ;;
|
||||
@@ -21,29 +18,27 @@ if [ "$runtime_lane" = "true" ]; then
|
||||
else
|
||||
printf 'true' > /tekton/results/runtime-ready-required
|
||||
fi
|
||||
source_head_url_for_setup="$(params.git-url)"
|
||||
gitops_read_url_for_setup="$(params.git-url)"
|
||||
if [ "$runtime_lane" = "true" ]; then
|
||||
source_head_url_for_setup="$(params.git-read-url)"
|
||||
gitops_read_url_for_setup="$(params.git-read-url)"
|
||||
fi
|
||||
gitops_write_url_for_setup="$(params.git-write-url)"
|
||||
if git_url_requires_ssh "$source_head_url_for_setup" || git_url_requires_ssh "$gitops_read_url_for_setup" || git_url_requires_ssh "$gitops_write_url_for_setup"; then
|
||||
for tool in ssh ssh-keyscan; do command -v "$tool" >/dev/null 2>&1 || { echo '{"event":"ci-base-image","phase":"gitops-promote","ok":false,"reason":"missing-tool","tool":"'"$tool"'"}'; exit 31; }; done
|
||||
git_ssh_setup
|
||||
else
|
||||
echo '{"event":"git-ssh-setup","phase":"gitops-promote","status":"skipped","reason":"non-ssh-git-url"}'
|
||||
fi
|
||||
test -s /workspace/gitea-auth/token || { echo '{"event":"gitea-auth","phase":"gitops-promote","status":"failed","reason":"token-missing"}'; exit 31; }
|
||||
askpass_dir="$(mktemp -d)"
|
||||
cat > "$askpass_dir/askpass.sh" <<'SH'
|
||||
#!/bin/sh
|
||||
case "$1" in
|
||||
*sername*) printf '%s\n' "$GITEA_USERNAME" ;;
|
||||
*) cat /workspace/gitea-auth/token ;;
|
||||
esac
|
||||
SH
|
||||
chmod 0700 "$askpass_dir/askpass.sh"
|
||||
export GITEA_USERNAME="$(params.gitops-username)"
|
||||
export GIT_ASKPASS="$askpass_dir/askpass.sh"
|
||||
export GIT_ASKPASS_REQUIRE=force
|
||||
export GIT_TERMINAL_PROMPT=0
|
||||
cd /workspace/source/repo
|
||||
test "$(git rev-parse HEAD)" = "$(params.revision)"
|
||||
|
||||
check_source_head() {
|
||||
phase="$1"
|
||||
expected="${2:-$(params.revision)}"
|
||||
source_head_url="$(params.git-url)"
|
||||
if [ "$runtime_lane" = "true" ]; then
|
||||
source_head_url="$(params.git-read-url)"
|
||||
fi
|
||||
source_head_url="$(params.git-read-url)"
|
||||
latest_file="$(mktemp)"
|
||||
if ! git_timed "source-head-$phase" 45 git ls-remote "$source_head_url" "refs/heads/$(params.source-branch)" > "$latest_file"; then
|
||||
echo '{"status":"failed","reason":"source-head-check-failed","phase":"'"$phase"'","sourceBranch":"'"$(params.source-branch)"'","sourceRevision":"'"$(params.revision)"'"}'
|
||||
@@ -182,11 +177,8 @@ node scripts/run-bun.mjs scripts/gitops-render.mjs --lane "$lane" --catalog-path
|
||||
ci_timing_emit gitops-render succeeded "$gitops_render_started_ms"
|
||||
check_source_head before-push
|
||||
workdir="$(mktemp -d)"
|
||||
gitops_read_url="$(params.git-url)"
|
||||
gitops_read_url="$(params.gitops-read-url)"
|
||||
gitops_write_url="$(params.git-write-url)"
|
||||
if [ "$runtime_lane" = "true" ]; then
|
||||
gitops_read_url="$(params.git-read-url)"
|
||||
fi
|
||||
gitops_clone_started_ms="$(ci_now_ms)"
|
||||
git_timed gitops-clone 180 git clone --no-checkout "$gitops_read_url" "$workdir/gitops"
|
||||
cd "$workdir/gitops"
|
||||
|
||||
@@ -28,7 +28,7 @@ const catalog = JSON.parse(fs.readFileSync(process.env.HWLAB_ARTIFACT_CATALOG_PA
|
||||
const plan = fs.existsSync("/workspace/source/affected-services.json") ? JSON.parse(fs.readFileSync("/workspace/source/affected-services.json", "utf8")) : {};
|
||||
const service = (catalog.services || []).find((item) => item.serviceId === serviceId) || {};
|
||||
const planned = (plan.services || []).find((item) => item.serviceId === serviceId) || {};
|
||||
const envReuse = planned.runtimeMode === "env-reuse-git-mirror-checkout" || service.runtimeMode === "env-reuse-git-mirror-checkout" || planned.envReuse === true || service.envReuse === true;
|
||||
const envReuse = planned.runtimeMode === "env-reuse-gitea-checkout" || service.runtimeMode === "env-reuse-gitea-checkout" || planned.envReuse === true || service.envReuse === true;
|
||||
const image = envReuse ? (service.environmentImage || service.image || "") : (service.image || "");
|
||||
const digest = envReuse ? (service.environmentDigest || service.digest || "not_published") : (service.digest || "not_published");
|
||||
const imageTag = service.imageTag || (image.includes(":") ? image.slice(image.lastIndexOf(":") + 1) : "");
|
||||
@@ -48,7 +48,7 @@ const values = {
|
||||
"component-input-hash": componentInputHash,
|
||||
"environment-input-hash": environmentInputHash,
|
||||
"code-input-hash": codeInputHash,
|
||||
"runtime-mode": envReuse ? "env-reuse-git-mirror-checkout" : "service-image",
|
||||
"runtime-mode": envReuse ? "env-reuse-gitea-checkout" : "service-image",
|
||||
"boot-repo": planned.bootRepo || service.bootRepo || "",
|
||||
"boot-commit": envReuse ? revision : (service.bootCommit || ""),
|
||||
"boot-sh": planned.bootSh || service.bootSh || "",
|
||||
|
||||
@@ -9,7 +9,7 @@ if [ -d "$ci_node_deps/yaml" ] && [ ! -e node_modules/yaml ]; then
|
||||
ln -s "$ci_node_deps/yaml" node_modules/yaml
|
||||
fi
|
||||
test "$(git rev-parse HEAD)" = "$(params.revision)"
|
||||
HWLAB_CATALOG_PATH="$(params.catalog-path)" HWLAB_GIT_URL="$(params.git-url)" HWLAB_GIT_READ_URL="$(params.git-read-url)" HWLAB_GITOPS_BRANCH="$(params.gitops-branch)" HWLAB_SERVICES="$(params.services)" node scripts/ci/restore-artifact-catalog.mjs
|
||||
HWLAB_CATALOG_PATH="$(params.catalog-path)" HWLAB_GIT_URL="$(params.git-url)" HWLAB_GIT_READ_URL="$(params.gitops-read-url)" HWLAB_GITOPS_BRANCH="$(params.gitops-branch)" HWLAB_SERVICES="$(params.services)" node scripts/ci/restore-artifact-catalog.mjs
|
||||
node scripts/ci-plan.mjs --lane "$(params.lane)" --base-ref "$(params.release-base-commit)" --target-ref HEAD --deploy-config deploy/deploy.yaml --artifact-catalog "$(params.catalog-path)" --registry-prefix "$(params.registry-prefix)" --services "$(params.services)" --release-target "$(params.release-target)" --release-consumer "$(params.release-consumer)" --verify-reuse-registry > /workspace/source/ci-plan.json
|
||||
node scripts/ci/verify-reviewed-plan.mjs --actual-plan /workspace/source/ci-plan.json --reviewed-plan "$(params.reviewed-plan)"
|
||||
node - <<'NODE'
|
||||
@@ -25,7 +25,7 @@ const entries = allServices.map((serviceId) => {
|
||||
const service = byService.get(serviceId) || {};
|
||||
const serviceSelected = selectedSet.has(serviceId);
|
||||
const rolloutAffected = serviceSelected && affected.has(serviceId);
|
||||
const envReuse = service.runtimeMode === "env-reuse-git-mirror-checkout" || service.envReuse === true;
|
||||
const envReuse = service.runtimeMode === "env-reuse-gitea-checkout" || service.envReuse === true;
|
||||
const buildRequired = serviceSelected && (plannedBuildServices ? plannedBuildServices.has(serviceId) : (envReuse ? service.envChanged === true : rolloutAffected));
|
||||
return {
|
||||
serviceId,
|
||||
|
||||
@@ -9,16 +9,8 @@ export HWLAB_SOURCE_REVISION="$(params.revision)"
|
||||
echo '{"event":"ci-base-image","phase":"prepare-source","image":"__HWLAB_CI_TOOLS_IMAGE__","policy":"no-runtime-apk"}'
|
||||
for tool in node git timeout; do command -v "$tool" >/dev/null 2>&1 || { echo '{"event":"ci-base-image","ok":false,"reason":"missing-tool","tool":"'"$tool"'"}'; exit 31; }; done
|
||||
node -e 'console.log(JSON.stringify({event:"ci-base-image",phase:"prepare-source",ok:true,node:process.version}))'
|
||||
# __HWLAB_GIT_SSH_SHELL__
|
||||
|
||||
git_url_requires_ssh() { case "$1" in git@*|ssh://*) return 0 ;; *) return 1 ;; esac; }
|
||||
git_read_url="$(params.git-read-url)"
|
||||
if git_url_requires_ssh "$git_read_url"; then
|
||||
for tool in ssh ssh-keyscan; do command -v "$tool" >/dev/null 2>&1 || { echo '{"event":"ci-base-image","ok":false,"reason":"missing-tool","tool":"'"$tool"'"}'; exit 31; }; done
|
||||
git_ssh_setup
|
||||
else
|
||||
echo '{"event":"git-ssh-setup","phase":"prepare-source","status":"skipped","reason":"non-ssh-git-read-url"}'
|
||||
fi
|
||||
gitops_read_url="$(params.gitops-read-url)"
|
||||
rm -rf /workspace/source/repo
|
||||
source_clone_started_ms="$(ci_now_ms)"
|
||||
git_timed source-clone 180 git clone --branch "$(params.source-branch)" "$git_read_url" /workspace/source/repo
|
||||
@@ -35,8 +27,8 @@ ci_timing_emit prepare-source-dependencies succeeded "$prepare_source_dependenci
|
||||
catalog_path="$(params.catalog-path)"
|
||||
mkdir -p "$(dirname "$catalog_path")"
|
||||
catalog_fetch_started_ms="$(ci_now_ms)"
|
||||
if git_timed catalog-ls-remote 45 git ls-remote --exit-code --heads "$git_read_url" "$(params.gitops-branch)" >/dev/null; then
|
||||
git remote set-url gitops-catalog "$git_read_url" 2>/dev/null || git remote add gitops-catalog "$git_read_url"
|
||||
if git_timed catalog-ls-remote 45 git ls-remote --exit-code --heads "$gitops_read_url" "$(params.gitops-branch)" >/dev/null; then
|
||||
git remote set-url gitops-catalog "$gitops_read_url" 2>/dev/null || git remote add gitops-catalog "$gitops_read_url"
|
||||
git_timed catalog-fetch 90 git fetch --depth 1 gitops-catalog "$(params.gitops-branch)" >/dev/null || true
|
||||
if git cat-file -e FETCH_HEAD:"$catalog_path" 2>/dev/null; then
|
||||
git show FETCH_HEAD:"$catalog_path" > /tmp/hwlab-gitops-artifact-catalog.json
|
||||
|
||||
Reference in New Issue
Block a user