fix(cicd): match PaC repositories by public Gitea URL

This commit is contained in:
Codex
2026-07-08 20:56:44 +02:00
parent 6b3ea35846
commit 199f8e9909
5 changed files with 36 additions and 9 deletions
@@ -139,7 +139,6 @@ NODE
}
repository_manifest() {
repository_url=$(resolve_service_url_to_cluster_ip "$UNIDESK_PAC_REPOSITORY_URL")
cat <<EOF
apiVersion: pipelinesascode.tekton.dev/v1alpha1
kind: Repository
@@ -151,7 +150,7 @@ metadata:
app.kubernetes.io/part-of: $UNIDESK_PAC_PART_OF
unidesk.ai/spec: $UNIDESK_PAC_SPEC
spec:
url: $repository_url
url: $UNIDESK_PAC_REPOSITORY_URL
git_provider:
type: gitea
url: $UNIDESK_PAC_GITEA_BASE_URL
@@ -913,10 +912,15 @@ status_action() {
argo=$(json_normalize "$argo")
runtime=$(json_normalize "$(runtime_summary)")
diagnostics=$(cicd_diagnostics "$pipelines" "$artifact" "$argo" "$runtime")
printf '{"ok":%s,"crdPresent":%s,"controllerReady":"%s","repositoryCondition":"%s","webhooks":%s,"pipelineRuns":%s,"taskRuns":%s,"artifact":%s,"argo":%s,"runtime":%s,"diagnostics":%s,"valuesPrinted":false}\n' \
printf '{"ok":%s,"crdPresent":%s,"controllerReady":"%s","repository":{"name":"%s","repo":"%s/%s","url":"%s","condition":"%s"},"repositoryCondition":"%s","webhooks":%s,"pipelineRuns":%s,"taskRuns":%s,"artifact":%s,"argo":%s,"runtime":%s,"diagnostics":%s,"valuesPrinted":false}\n' \
"$( [ -n "$crd" ] && [ "$controller_ready" != "0/0" ] && echo true || echo false )" \
"$( [ -n "$crd" ] && echo true || echo false )" \
"$(json_string "$controller_ready")" \
"$(json_string "$UNIDESK_PAC_REPOSITORY_NAME")" \
"$(json_string "$UNIDESK_PAC_GITEA_OWNER")" \
"$(json_string "$UNIDESK_PAC_GITEA_REPO")" \
"$(json_string "$UNIDESK_PAC_REPOSITORY_URL")" \
"$(json_string "$repository_condition")" \
"$(json_string "$repository_condition")" \
"$hooks" "$pipelines" "$tasks" "$artifact" "$argo" "$runtime" "$diagnostics"
}
@@ -350,6 +350,7 @@ function validateConfig(config: PacConfig): void {
if (ids.has(repository.id)) throw new Error(`${configLabel}.repositories id must be unique: ${repository.id}`);
ids.add(repository.id);
if (repository.providerType !== "gitea") throw new Error(`${configLabel}.repositories.${repository.id}.providerType must be gitea`);
if (isInternalRepositoryMatchUrl(repository.url)) throw new Error(`${configLabel}.repositories.${repository.id}.url must be the public Gitea URL used in webhook payloads; keep internal service URLs in cloneUrl/params.git_read_url`);
if (new URL(repository.cloneUrl).origin !== new URL(config.gitea.internalBaseUrl).origin) throw new Error(`${configLabel}.repositories.${repository.id}.cloneUrl must use the configured internal Gitea base URL`);
}
const consumerIds = new Set<string>();
@@ -775,6 +776,7 @@ function statusSummary(payload: Record<string, unknown>): Record<string, unknown
const argo = record(payload.argo);
const runtime = record(payload.runtime);
const diagnostics = record(payload.diagnostics);
const webhooks = arrayRecords(payload.webhooks);
const artifact = {
...record(payload.artifact),
imageStatus: record(payload.artifact).imageStatus ?? (runtime.image === undefined ? undefined : "runtime"),
@@ -787,7 +789,9 @@ function statusSummary(payload: Record<string, unknown>): Record<string, unknown
crdPresent: payload.crdPresent === true,
controllerReady: payload.controllerReady,
repositoryCondition: payload.repositoryCondition,
webhookCount: arrayRecords(payload.webhooks).length,
repository: record(payload.repository),
webhooks,
webhookCount: webhooks.length,
latestPipelineRun: latest,
taskRuns,
pipelineRunGate: pipelineGate,
@@ -872,11 +876,22 @@ function policyChecks(repository: PacRepository): Array<Record<string, unknown>>
return [
{ name: "single-path", ok: true, detail: "Gitea webhook -> Pipelines-as-Code -> Tekton -> Argo/k8s runtime; no Gitea Actions/act_runner/branch-follower fallback." },
{ name: "yaml-source-of-truth", ok: true, detail: `${configLabel} owns PaC release, Repository CR, Gitea webhook and consumer params.` },
{ name: "public-repository-url", ok: !isInternalRepositoryMatchUrl(repository.url), detail: "Repository CR url matches the public Gitea webhook payload URL; internal service URLs remain clone/read URLs only." },
{ name: "gitea-internal-source", ok: repository.cloneUrl.includes(".svc.cluster.local"), detail: "Tekton source clone uses the internal k3s Gitea service URL." },
{ name: "runtime-zero-docker", ok: true, detail: "Runtime starts at k8s pulling already-built images; CI build may use Tekton/BuildKit." },
];
}
function isInternalRepositoryMatchUrl(value: string): boolean {
const parsed = new URL(value);
return parsed.hostname.endsWith(".svc.cluster.local")
|| parsed.hostname === "localhost"
|| parsed.hostname === "127.0.0.1"
|| /^10\./u.test(parsed.hostname)
|| /^192\.168\./u.test(parsed.hostname)
|| /^172\.(1[6-9]|2\d|3[0-1])\./u.test(parsed.hostname);
}
function targetSummary(target: PacTarget): Record<string, unknown> {
return { id: target.id, route: target.route, namespace: target.namespace, role: target.role };
}
@@ -1015,6 +1030,8 @@ function renderStatus(result: Record<string, unknown>): RenderedCliResult {
const artifact = record(summary.artifact);
const argo = record(summary.argo);
const diagnostics = record(summary.diagnostics);
const repository = record(summary.repository);
const webhooks = arrayRecords(summary.webhooks);
const lines = [
"PLATFORM-INFRA PIPELINES-AS-CODE STATUS",
...(coverage.length === 0 ? [] : [
@@ -1022,7 +1039,11 @@ function renderStatus(result: Record<string, unknown>): RenderedCliResult {
...table(["CONSUMER", "SOURCE", "NAMESPACE", "PIPELINE", "ARGO_APP"], coverage.map((item) => [stringValue(item.consumer), stringValue(item.source), stringValue(item.namespace), stringValue(item.pipeline), stringValue(item.argoApplication)])),
"",
]),
...table(["CONSUMER", "READY", "CRD", "CONTROLLER", "WEBHOOKS", "REPOSITORY"], [[stringValue(consumer.id), boolText(summary.ready), boolText(summary.crdPresent), stringValue(summary.controllerReady), stringValue(summary.webhookCount), compactLine(stringValue(summary.repositoryCondition))]]),
...table(["CONSUMER", "READY", "CRD", "CONTROLLER", "WEBHOOKS", "REPO_URL"], [[stringValue(consumer.id), boolText(summary.ready), boolText(summary.crdPresent), stringValue(summary.controllerReady), stringValue(summary.webhookCount), short(stringValue(repository.url), 56)]]),
` repository-condition: ${compactLine(stringValue(summary.repositoryCondition))}`,
"",
"GITEA HOOKS",
...(webhooks.length === 0 ? ["-"] : table(["HOOK", "ACTIVE", "EVENTS", "URL"], webhooks.map((item) => [stringValue(item.id), boolText(item.active), Array.isArray(item.events) ? item.events.join(",") : stringValue(item.events), short(stringValue(item.url), 56)]))),
"",
"LATEST PIPELINERUN",
...table(["NAME", "STATUS", "REASON", "DURATION_S", "SOURCE"], [[stringValue(latest.name), stringValue(latest.status), stringValue(latest.reason), stringValue(latest.durationSeconds), short(stringValue(latest.sourceCommit))]]),