Files
pikasTech-unidesk/.agents/skills/unidesk-cicd/references/gitea-pac.md
T
2026-07-13 09:27:42 +02:00

20 KiB
Raw Blame History

Gitea + Pipelines-as-Code

Gitea/Pipelines-as-Code 迁移后的 CI/CD 只有一条正式路径:

GitHub PR merge -> GitHub webhook bridge -> Gitea controlled mirror and immutable snapshot refs -> Gitea Repository webhook -> Pipelines-as-Code -> Tekton PipelineRun -> GitOps/Argo -> k8s runtime

GitHub 是唯一上游写入权威。目标 source branch 的 GitHub PR merge 是唯一正式交付触发事件;合并后必须由 webhook、mirror、PaC、Tekton、GitOps/Argo 自动推进到运行面,无需主代理、子代理或操作者执行任何 apply、closeout、trigger、sync、flush 或补跑。状态与历史命令只能观察和诊断,不能推进交付。

自动链任一环节不通时,任务目标是修复该环节的 YAML、controller 或源码,并以修复 PR 合并后产生的新自动链事件作为验收证据。禁止用 Gitea Actions、act_runner、branch-follower、host worktree、Pipeline 内直连 GitHub、直接 Gitea push、人工 mirror sync、人工 PipelineRun、trigger-current、伪 push、hook test 或自定义脚本补齐当前交付。config/cicd-gitea-actions-poc.yaml 只保留只读历史材料。会 POST Gitea hook /testswebhook-test 已从 Gitea source-authority 与 PaC 公共 CLI、远端执行器移除,因为它会制造交付事件,不是只读连通性诊断。

Webhook bridge 自举保护

  • Argo selfHeal 的边界:
    • 只能把 GitOps branch 已存在的 desired 恢复到运行面;
    • 不能从 GitHub 获取尚未进入 Gitea branch/snapshot 的 bridge 修复 commit
    • 不得把 selfHeal 描述为 bridge 故障后的独立 source authority。
  • Bridge desired 更新必须经过同一 Argo Application 的 PreSync candidate gate
    • owning 配置是 config/platform-infra/gitea.yaml#sourceAuthority.webhookSync.bridge.candidateGate
    • candidate 使用与正式 Deployment 相同的镜像、server.mjs 和 ConfigMap 符号链接挂载形状;
    • candidate 使用隔离的临时 inbox,只验证进程启动、durable storage readiness 与 /healthz
    • candidate 通过后才允许 Argo 更新正式 ConfigMap 和 Recreate Deployment
    • candidate 失败时必须保留现有 ready bridge,不能继续替换单写者。
  • Candidate gate 不是第二触发或恢复路径:
    • 不读取 GitHub branch
    • 不写 Gitea branch/snapshot
    • 不创建业务 PipelineRun
    • 不接收或重投 webhook delivery。
  • 若 bridge 在 candidate gate 引入前已经不可用:
    • 新 PR 不能通过同一故障 bridge 自动部署自身修复;
    • 状态必须明确报告自举死锁;
    • 禁止用 branch-follower、轮询、人工 mirror sync、直接 Gitea push、人工 PipelineRun、trigger-current、sync/flush 或 delivery 重投伪造自动恢复。

唯一事实来源

  • Gitea source authority、GitHub webhook bridge、公网暴露与 source snapshot 归属 config/platform-infra/gitea.yaml
  • PaC controller、Repository CR、consumer 参数、Tekton pipeline 名称与 Argo Application 归属 config/platform-infra/pipelines-as-code.yaml
  • CLI 必须组合两份 YAML,并按 consumer、node、lane、upstream repository、branch 与 Gitea repository 精确解析 authority。不得用 URL heuristic 或 repo 专属特例;unknown、歧义和配置错误都必须 mutation=false 并 fail-closed。
  • 旧人工 mutation 入口只允许在 owning YAML 精确解析为 legacy-manual 后从 scoped help 使用;Gitea/PaC migrated consumer 和 unknown authority 都不得回退到 legacy 实现。
  • 包含 gitea-actions 的历史 snapshot prefix 只为既有 ref 保留,不代表 Gitea Actions 仍是有效触发架构。
  • node 级状态入口是 bun scripts/cli.ts cicd status --node <NODE>consumer 级默认下钻入口是 platform-infra pipelines-as-code status|history --target <NODE> --consumer <id>
  • 共用 GitHub 上游的多 node PaC consumer 不得共用 webhook bridge URL。每个 target node 在 config/platform-infra/gitea.yaml#targets[].webhookSync 声明自己的 GitHub webhook 公网路径与 FRP remote port,并由平台自动交付渲染 node-local bridge、FRPC proxy 和 PK01 Caddy 路径;禁止在 source PR 合并后人工 apply 补齐。
  • PaC Repository CR spec.url 必须与 Gitea webhook payload 中的 URL 一致。config/platform-infra/pipelines-as-code.yaml#repositories[].url 保持公网 Gitea repository URLk8s 内网 service URL 只能写入 cloneUrlparams.git_read_url;否则 PaC 会记录 cannot find a repository match 且不会创建 PipelineRun。
  • JD01 与 NC01 共用的 repository 必须传入 target-specific node Repository param,每个 .tekton PipelineRun 必须用 pipelinesascode.tekton.dev/on-cel-expression 过滤该参数。一个 target 的 push 不得在同一 target cluster 创建另一 target 的 PipelineRun。

PaC consumer 首发最短路径

  • 在 source PR 合并前完成源码侧准备:
    • owning YAML 中声明 Gitea repository、PaC repository 与 consumer
    • consumer 声明 sourceArtifact 时,先在 source worktree 执行 source-artifact check
    • 不创建人工 PipelineRun,也不推送 Gitea branch 或 snapshot。
  • 只使用同一个组合入口完成控制面首次引导:
bun scripts/cli.ts platform-infra pipelines-as-code bootstrap --target <NODE> --consumer <consumer> --dry-run
bun scripts/cli.ts platform-infra pipelines-as-code bootstrap --target <NODE> --consumer <consumer> --confirm
  • 组合入口负责以下职责:
    • 组合 config/platform-infra/gitea.yamlconfig/platform-infra/pipelines-as-code.yaml
    • 按 target、Gitea owner/name 与 read URL 精确选择唯一 repository
    • 初始化选中的空 Gitea repository
    • 安装或更新 PaC controller、consumer RBAC、Repository CR、Argo bootstrap 与 Gitea webhook
    • 不同步 source branch,不创建 snapshot,不触发业务 PipelineRun。
  • 预检与失败边界:
    • PaC apply 在任何 Kubernetes 写入前读取 Gitea repository
    • repository 缺失时返回 gitea-repository-missing,不留下半套 Tekton/RBAC/Argo 状态;
    • YAML 零匹配或多匹配时在本地拒绝,不猜测 repository;
    • gitea mirror bootstrap 未带 --confirm 时输出可读 dry-run 与精确 confirm 命令,不再返回空白拒绝。
  • 完成 bootstrap --confirm 后合并 source PR
    • GitHub PR merge 是唯一 delivery 触发;
    • 不再调用 bootstrap、apply、mirror sync、PipelineRun、Argo refresh 或 closeout
    • 正常链路不串联 mirror status、webhook status、PaC status 与 history。
  • 只有出现自动链故障或用户明确要求验收时才读取状态:
    • 首选一次 cicd status --node <NODE> 获取 node 摘要;
    • 只对失败 consumer 使用一次 pipelines-as-code status --consumer <id>
    • 只有归属或 TaskRun 断点不清楚时再用 history --iddebug-step --id
    • 默认不使用 --full--raw,避免把大对象带回本机;
    • consumer 声明 sourceArtifact 且需要精确提交验收时,最后执行一次 source-artifact verify-runtime

PaC 源码侧制品同步

当 owning Pipeline 与消费仓 .tekton 内联 pipelineSpec 或远程 Pipeline 文件存在漂移时,统一使用以下入口:

bun scripts/cli.ts platform-infra pipelines-as-code source-artifact plan --target <NODE> --consumer <id> --source-worktree <absolute-path>
bun scripts/cli.ts platform-infra pipelines-as-code source-artifact check --target <NODE> --consumer <id> --source-worktree <absolute-path>
bun scripts/cli.ts platform-infra pipelines-as-code source-artifact write --target <NODE> --consumer <id> --source-worktree <absolute-path> --confirm
bun scripts/cli.ts platform-infra pipelines-as-code source-artifact status --target <NODE> --consumer <id> --source-worktree <absolute-path> [--source-commit <full-sha>]
bun scripts/cli.ts platform-infra pipelines-as-code source-artifact verify-runtime --target <NODE> --consumer <id> --source-worktree <absolute-path> --source-commit <full-sha>
  • config/platform-infra/pipelines-as-code.yaml#consumers[].sourceArtifact 是生成职责的声明入口;未声明的 consumer 必须稳定拒绝,模板不得替它发明 owner。
  • source-artifact plan|check|write 只能在 source PR 合并前生成或校验该 PR 的受管源码制品,不是合并后的 CI/CD 触发、同步、恢复或补跑入口。
  • desired 只来自 owning YAML 与共享 domain rendererlive Pipeline 和 PipelineRun 只能作为只读诊断证据,禁止从运行面反向导出 desired 或源码制品。
  • plancheckwrite 只比较或更新显式消费仓 worktree,不访问运行面;worktree 必须是绝对路径、Git 根目录,并与声明仓库的精确 remote identity 一致。
  • write 先完成全部路径、内容和 renderer 合同校验,再通过同目录临时文件与 rename 更新;连续执行必须无差异。
  • status 是非门禁诊断,允许不传 commit。
  • verify-runtime 必须满足以下条件:
    • 传入完整四十位 --source-commit
    • --source-worktree 干净;
    • worktree HEAD 与该 commit 完全相同;
    • 合并提交的验收新建精确提交 worktree,不使用带未提交修改或停在父提交的开发 worktree;
    • PipelineRun 按 PaC/source-commit label 或 annotation 精确筛选,不按 prefix 直接取全局 latest。
  • 同一 source commit 因 webhook 重投或 PaC retry 产生多个 PipelineRun 时,只在完整内联 spec 与 provenance 全部一致时确定性选择最新一条并披露候选数;存在冲突必须 fail-closed。
  • runtime observer 必须满足以下约束:
    • 区分对象 NotFound、transport/RBAC/命令不可用和 spec drift
    • 完整大 spec 通过受控临时文件传入目标侧原生 observer,不放入 shell argv 或环境变量;
    • 默认、--json--full 的错误与 drift 只输出结构路径、类型、长度、SHA-256 或 URL fingerprint
    • 不回显脚本、URL 凭据、查询参数、Authorization、Secret、stdout 或 stderr 原文。
  • 完整 spec 比较只移除六类已验证的 Tekton admission default,并限定在裸 Pipeline spec、完整 Pipeline 或 PipelineRun pipelineSpec 三个明确根;其他同名字段不得过滤。
  • sourceArtifact.taskRunTemplatehostNetworkdnsPolicyfsGroup 的唯一所有者;生成器不得另设硬编码默认值。
  • HWLAB source artifact 必须经过完整 domain renderer、正式 postprocess/verify 和完整 spec 比较。
    • Kafka refresh 等业务合同由 owning renderer 与消费者结构化负例测试保障;
    • 不得在通用生成器中用字符串 marker 扫描建立第二真相。
  • AgentRun source artifact 通过完整 owning Pipeline 与完整 spec 比较保留 RBAC、参数和 manager 环境合同。

覆盖矩阵

Consumer Source PaC namespace Pipeline Argo Application 状态命令
agentrun-jd01-v02 pikasTech/agentrun@v0.2 agentrun-ci agentrun-jd01-v02-ci-image-publish agentrun-jd01-v02 platform-infra pipelines-as-code status --target JD01 --consumer agentrun-jd01-v02
sentinel-jd01-v03 pikasTech/unidesk@master devops-infra hwlab-web-probe-sentinel-jd01-pac hwlab-web-probe-sentinel-jd01 platform-infra pipelines-as-code status --target JD01 --consumer sentinel-jd01-v03
hwlab-jd01-v03 pikasTech/HWLAB@v0.3 hwlab-ci hwlab-jd01-v03-ci-image-publish hwlab-node-v03 platform-infra pipelines-as-code status --target JD01 --consumer hwlab-jd01-v03
agentrun-nc01-v02 pikasTech/agentrun@v0.2 agentrun-ci agentrun-nc01-v02-ci-image-publish agentrun-nc01-v02 platform-infra pipelines-as-code status --target NC01 --consumer agentrun-nc01-v02
sentinel-nc01-v03 pikasTech/unidesk@master devops-infra hwlab-web-probe-sentinel-nc01-pac hwlab-web-probe-sentinel-nc01 platform-infra pipelines-as-code status --target NC01 --consumer sentinel-nc01-v03
hwlab-nc01-v03 pikasTech/HWLAB@v0.3 hwlab-ci hwlab-nc01-v03-ci-image-publish hwlab-node-v03 platform-infra pipelines-as-code status --target NC01 --consumer hwlab-nc01-v03

使用 bun scripts/cli.ts platform-infra pipelines-as-code history --target <NODE> --limit 10 审计全部 consumer 的触发、耗时与 reuse。命令必须读取 target node 上的实时 Gitea Repository CR 与 Tekton PipelineRun/TaskRun,在 target 侧聚合并显式输出 READ_ERRORS

history --id <pipelinerun> 必须按 target 内唯一 PipelineRun prefix 或 Tekton pipeline 归属解析实际 consumer,并用该 consumer 生成 status/history Next。零匹配、多匹配或显式 --consumer 与实际归属冲突时必须在远端读取前 fail-closed;禁止回退默认 consumer。

按需只读调查

自动链必须在没有任何操作者命令的情况下完成交付并记录 terminal 状态。以下入口只在显式调查自动链故障时按需使用,不是 PR 合并后的默认顺序、交付前置或“下一步”:

  • bun scripts/cli.ts platform-infra gitea mirror status --target <NODE>
  • bun scripts/cli.ts platform-infra gitea mirror webhook status --target <NODE>
  • bun scripts/cli.ts platform-infra pipelines-as-code status --target <NODE> --consumer <id>
  • bun scripts/cli.ts platform-infra pipelines-as-code history --target <NODE> --consumer <id> --limit 10
  • 对归属或状态不明的行,使用 bun scripts/cli.ts platform-infra pipelines-as-code history --target <NODE> --id <pipelinerun> 下钻 PipelineRun。

closeout 只保留为可选的只读历史/诊断兼容入口,不得出现在 migrated consumer 的默认观察顺序、覆盖矩阵、正常下一步或 PR 合并后的主/子代理任务中。它不得创建、同步、刷新、重试或补跑任何交付对象。consumer 专属 debug 命令只允许复现单步故障,不得成为正式交付或恢复入口。

GitHub webhook delivery 的持久接收与 refs 提交必须分层:

  • receiver 验签并校验 payload 后,只有在 delivery 通过 fsync 与 atomic rename 写入 YAML 声明的 PVC durable inbox 后才能返回 HTTP 202 Accepted
  • 202 Accepted 只证明 delivery 已持久接收,不证明 Gitea authority branch 或 immutable snapshot 已 committed
  • journal 状态必须显式区分 acceptedprocessingcommittedfailed,并保留 deliveryId、payload correlation、尝试次数与有界失败摘要;
  • 同 deliveryId 与同 payload 必须幂等,异 payload 必须返回 409PVC 不可用或容量满必须返回 503 并使 readiness=false
  • inbox worker 使用 YAML 声明的有界 backoff 自动重试,进程重启后恢复 accepted / processing,不要求人工 sync、repair、test 或 PipelineRun
  • 只有同一 delivery 的 exact-after immutable snapshot 与 authority branch 经 atomic push 后重新读取 refs 证明一致,才能进入 committed
  • Caddy 只可对尚未成功落盘的请求做小于 10 秒、body-safe 的有界重试,不能把代理成功当作 refs committed。

当前 bridge 的权威状态链是 GitHub delivery GUID -> durable inbox record -> post-push refs proof -> live refs。HTTP 202 后记录仍是 acceptedrefsCommitted=false;只有 worker 完成 exact refs 复核后才成为 committed。旧 durable journal 上线前的记录可以标记 pre-durable-bootstrap,但不得标记 committed。ingressRetry 在自动 PK01 host reconciler 完成前保持关闭,不能由操作者手工补配置。

Durable inbox 只是 webhook delivery 的持久接收与重试 journal,不是业务 source/ref 的第二份真相,也不得被 PaC、Tekton、GitOps、Argo 或 runtime 当作源码/read model。最终 source authority 仍只有 Gitea authority branch 与 immutable snapshot。webhook status 默认摘要必须显示 accepted -> processing -> committed/failed 分层,并将同一 delivery 的 accepted correlation 与 committed refs proof 关联。非 202、缺 accepted correlation、accepted 后未 committed 或进入 failed 都是失败/stale;只能修 webhook bridge、inbox worker、受控 mirror、snapshot controller 或 owning YAML,禁止输出或执行人工 REPAIR、mirror sync、直接 Gitea push 等补齐命令。

不得使用 cicd branch-follower status 判定三个已迁移 JD01 consumer 是否最新。该入口只保留历史/迁移用途,可能包含 PaC cutover 前的过期状态。

对已迁移 sentinel CI/CD 的 half-state 诊断,PaC status 命令负责 source/registry/GitOps/Argo/runtime 归因。它必须通过 target 侧短探针区分 registry-missing、GitOps-missing、Argo-pending 和 runtime-mismatch,并使用 registry_probe_base 等 YAML 声明的 probe endpoint;禁止重新把旧 control-plane status 当作主架构,也禁止把 registry manifest HEAD 当作 readiness 校验。

Sentinel 的内部 pac-publish-current capability 由 config/platform-infra/pipelines-as-code.yaml#capabilities.sentinelInternalPublish 单一拥有,当前必须保持 enabled=falseadmissionProvenance=unavailable.tekton 继续使用既有 publish-current 自动入口;不得因为 capability 关闭而改成人工 publish。Pod env、ownerReferences、ServiceAccount、label、annotation 与 controller metadata 都是普通 workload 可声明或可修改的运行对象,不能作为 creator proof。只有 #1769 定义的独立 admission-owned provenance、专用最小权限 SA/RBAC 与拒绝 workload 自声明标记全部落地后,才能通过 YAML 评审启用 capability。

PaC history/status 必须把候选 PipelineRun 分成 outer-pac-eventinner-deterministic-publishunknown。只有唯一外层 PaC push event 可以驱动 latest、status、debug-step 或 closeout;内层 deterministic publish 只能作为未绑定的执行观察展示,父子关系缺证据时必须标记 unproven,不得按名称前缀推断。运行对象 metadata 只能支持“已观察到 PaC 形态”的分类,不能宣称 admission provenance 已验证。

Reuse 证据解释

  • AgentRun IMAGE_STATUS=reused 表示本次跳过 image build,或复用了同一 env identity 的 registry artifact。
  • Sentinel ENV_REUSE=hit 表示依赖可复用;cache=hit 是独立的 BuildKit 证据。
  • HWLAB skipped,skip=<n> 表示 service-level artifact plan 跳过了可复用 build;判定具体变更 service 时应查看 PipelineRun 详情。

UniDesk Host 运行面变更过滤

unidesk-host consumer 将 source observation 与 runtime delivery 分离。config/unidesk-host-k8s.yaml#delivery.changeDetection.runtimePaths 是唯一可编辑的 runtime 变更 source path 列表,delivery.gitops.releaseStatePath 指向用作比较基线的 GitOps release state 生成物。

  • build:至少一个声明的 runtime path 发生变更,或没有可信的历史 release state。流水线构建 image、更新 manifest 与 release state,然后由 Argo 收敛。
  • skipsource commit 已推进,但没有声明的 runtime path 发生变更。流水线不得构建 image、修改 GitOps branch 或触发 Argo rollout,应保留既有 runtime source commit 与 digest 作为 provenance。
  • disableddelivery.enabled=false。删除生成的 manifest 与 release state;这代表 service retirement,不是 skip 的同义词。

CLI、文档、issue metadata 与 runtimePaths 之外的其他文件必须得到 IMAGE_STATUS=skipped。成功 skip 仍应产生一条短 PaC PipelineRun 作为 source-observation 证据,但应跳过 image build 与 GitOps publication。默认 status 必须校验保留的 digest、GitOps revision、Argo state、runtime readiness 与 health,不得强制 runtime source commit 等于更新的非 runtime source commit;兼容 closeout 只能复用同一只读证据。

缺少 reuse 文本不能证明 reuse path 失败,应先核对 consumer type 与 PipelineRun 详情。