version: 1
kind: platform-infra-gitea

metadata:
  id: gitea-internal-mirror
  owner: unidesk
  spec: GH-1548/GH-1550/GH-1560
  relatedIssues:
    - 1548
    - 1549
    - 1550
    - 1557
    - 1560
    - 1760
    - 1768

defaults:
  targetId: NC01

migration:
  role: gitea-pac-cicd-source-authority
  replaces: branch-follower-self-maintained-branch-observer
  parentConfigRef: config/cicd-gitea-actions-poc.yaml#spec.sourceAuthority.giteaMirror
  archivedPocRef: config/cicd-gitea-actions-poc.yaml
  activePacConfigRef: config/platform-infra/pipelines-as-code.yaml
  envReusePolicy: preserve-existing-runtime-env-reuse
  buildPlane: controlled-docker-or-buildkit-outside-runtime
  runtimePlane: k3s-gitea-service-zero-docker
  activeTriggerPath: gitea-webhook-to-pipelines-as-code-to-tekton-to-argo

sourceAuthority:
  enabled: true
  stage: gitea-controlled-mirror-source-authority
  statusAuthority: gitea-repository-refs-plus-snapshot-ref
  firstCiConsumer: agentrun-jd01-v02
  credentials:
    sourceRoot: /root/.unidesk/.env
    admin:
      sourceRef: gitea.auth
      format: line-pair
      usernameLine: 1
      passwordLine: 2
      requiredFor:
        - repo-bootstrap
        - mirror-sync
        - snapshot-create
    github:
      transport: https-token
      sourceRef: gh_token.txt
      sourceKey: GH_TOKEN
      format: raw-token
      requiredFor:
        - upstream-mirror
        - mirror-sync
        - managed-repository-fetch
      gitFetchCredential:
        apiVersion: unidesk.ai/v1
        kind: GitFetchCredential
        authMode: github-https-token
        host: github.com
        secretRef:
          namespace: devops-infra
          name: gitea-github-sync-secrets
          key: github-token
  githubProxy:
    enabled: true
    url: http://10.42.0.1:10808
    noProxy:
      - 127.0.0.1
      - localhost
      - .svc
      - .svc.cluster.local
  webhookSync:
    enabled: true
    direction: github-to-gitea
    # GitHub Cloud 要求 10 秒内返回 2xx；保留公网与 FRP 传输余量。
    # https://docs.github.com/en/webhooks/using-webhooks/handling-failed-webhook-deliveries
    responseBudgetMs: 6500
    publicPath: /_unidesk/github-to-gitea
    events:
      - push
    ingressRetry:
      # PK01 host reconciliation 尚未纳入 PR-merge 自动控制面；关闭后不得声称已应用 Caddy retry。
      # https://github.com/pikasTech/unidesk/issues/1768
      enabled: false
      maxBodyBytes: 1048576
      maxRetries: 1
      tryIntervalMs: 250
      dialTimeoutMs: 500
      writeTimeoutMs: 500
      retryStatusCodes:
        - 502
        - 503
        - 504
    secret:
      sourceRef: gitea.github-webhook.env
      sourceKey: GITHUB_WEBHOOK_SECRET
      createIfMissing: true
    hookReconcile:
      enabled: true
      # 只有 owning target 写 GitHub hook topology；其他 target 仅接收与观察。
      ownerTargetId: NC01
      intervalMs: 60000
      requestTimeoutMs: 15000
      listMaxPages: 10
      failedDeliveryRecovery:
        enabled: true
        # 恢复只处理 owner target 的 exact hook；其他 target 必须由其本地 authority 收口。
        targetId: NC01
        statePath: /var/lib/gitea-github-sync/hook-recovery/ledger.json
        # GitHub REST redelivery 只支持最近 3 天。
        lookbackSeconds: 259200
        historyPerHook: 50
        maxRedeliveriesPerCycle: 4
        cooldownMs: 300000
        maxAttemptsPerDelivery: 3
        retryStatusCodes:
          - 502
          - 503
          - 504
        stateRetentionSeconds: 1209600
    bridge:
      deploymentName: gitea-github-sync
      serviceName: gitea-github-sync
      secretName: gitea-github-sync-secrets
      configMapName: gitea-github-sync-config
      image: 127.0.0.1:5000/hwlab/hwlab-ci-node-tools:node22-alpine-bun-v1
      replicas: 1
      httpPort: 8080
      serviceAccountName: gitea-github-sync
      shutdownGraceMs: 5000
      candidateGate:
        enabled: true
        configMapName: gitea-github-sync-candidate
        jobName: gitea-github-sync-candidate
        activeDeadlineSeconds: 45
        ttlSecondsAfterFinished: 300
        healthTimeoutMs: 15000
        pollIntervalMs: 250
      inbox:
        claimName: gitea-github-sync-inbox
        path: /var/lib/gitea-github-sync
        storageSize: 1Gi
        maxBytes: 805306368
        committedRetentionSeconds: 604800
        cleanupIntervalMs: 60000
      retry:
        maxAttempts: 3
        initialDelayMs: 1000
        maxDelayMs: 30000
        terminalRetryDelayMs: 300000
        attemptTimeoutMs: 120000
        scanIntervalMs: 1000
    gitOpsDelivery:
      enabled: true
      targetId: NC01
      readUrl: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/unidesk.git
      writeUrl: http://git-mirror-write.devops-infra.svc.cluster.local:8080/pikasTech/unidesk.git
      branch: unidesk-host-gitops
      sourceSnapshotPrefix: refs/unidesk/snapshots/gitea-actions/unidesk-master-nc01
      desiredManifestPath: deploy/gitops/platform-infra/gitea-nc01/resources.yaml
      bootstrapApplicationPath: deploy/gitops/unidesk-host/platform-infra-gitea-nc01-application.yaml
      releaseStatePath: deploy/gitops-state/platform-infra/gitea-nc01.json
      application:
        name: platform-infra-gitea-nc01
        namespace: argocd
        project: default
        repoUrl: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/unidesk.git
        targetRevision: unidesk-host-gitops
        path: deploy/gitops/platform-infra/gitea-nc01
        destinationNamespace: devops-infra
        automated: true
      author:
        name: UniDesk Platform Infra CI
        email: platform-infra-ci@unidesk.local
      cas:
        maxAttempts: 3
    frpc:
      proxyName: platform-infra-gitea-jd01-github-webhook
      remotePort: 22081
  responsibilities:
    - name: source-read
      current: legacy-git-mirror
      target: gitea
      disposition: replaced-by-gitea
    - name: branch-observation
      current: branch-follower
      target: gitea-mirror
      disposition: replaced-by-gitea
    - name: immutable-snapshot-ref
      current: legacy-git-mirror-cache
      target: gitea-ref
      disposition: replaced-by-gitea
    - name: gitops-flush
      current: legacy-git-mirror
      target: github-direct-or-gitea-writeback
      disposition: retained-for-gitops-flush
    - name: legacy-status
      current: branch-follower-status
      target: gitea-mirror-status
      disposition: migration-readonly
  repositories:
    - key: agentrun-jd01-v02
      targetId: JD01
      upstream:
        repository: pikasTech/agentrun
        cloneUrl: https://github.com/pikasTech/agentrun.git
        branch: v0.2
      gitea:
        owner: mirrors
        name: pikasTech-agentrun
        mirrorMode: controlled-push
        publicRead: true
        readUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git
      gitops:
        branch: jd01-v0.2-gitops
        flushDisposition: retained-for-gitops-flush
      snapshot:
        naming: historical-gitea-actions-prefix-retained-for-existing-refs
        prefix: refs/unidesk/snapshots/gitea-actions/agentrun-v0.2
      legacyGitMirror:
        readUrl: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/agentrun.git
        configRef: config/cicd-branch-followers.yaml#followers.agentrun-jd01-v02.nativeStatus.source.gitMirrorReadUrl
        disposition: replaced-by-gitea
    - key: agentrun-nc01-v02
      targetId: NC01
      upstream:
        repository: pikasTech/agentrun
        cloneUrl: https://github.com/pikasTech/agentrun.git
        branch: v0.2
      gitea:
        owner: mirrors
        name: pikasTech-agentrun
        mirrorMode: controlled-push
        publicRead: true
        readUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-agentrun.git
      gitops:
        branch: nc01-v0.2-gitops
        flushDisposition: retained-for-gitops-flush
      snapshot:
        naming: historical-gitea-actions-prefix-retained-for-existing-refs
        prefix: refs/unidesk/snapshots/gitea-actions/agentrun-v0.2
      legacyGitMirror:
        readUrl: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/agentrun.git
        configRef: config/cicd-branch-followers.yaml#followers.agentrun-nc01-v02.nativeStatus.source.gitMirrorReadUrl
        disposition: replaced-by-gitea
    - key: unidesk-master
      targetId: JD01
      upstream:
        repository: pikasTech/unidesk
        cloneUrl: https://github.com/pikasTech/unidesk.git
        branch: master
      gitea:
        owner: mirrors
        name: pikasTech-unidesk
        mirrorMode: controlled-push
        publicRead: true
        readUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-unidesk.git
      gitops:
        branch: master
        flushDisposition: not-a-gitops-branch
      snapshot:
        naming: historical-gitea-actions-prefix-retained-for-existing-refs
        prefix: refs/unidesk/snapshots/gitea-actions/unidesk-master
      legacyGitMirror:
        readUrl: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/unidesk.git
        configRef: config/cicd-branch-followers.yaml#controller.source.gitMirrorReadUrl
        disposition: replaced-by-gitea
    - key: unidesk-master-nc01
      targetId: NC01
      upstream:
        repository: pikasTech/unidesk
        cloneUrl: https://github.com/pikasTech/unidesk.git
        branch: master
      gitea:
        owner: mirrors
        name: pikasTech-unidesk
        mirrorMode: controlled-push
        publicRead: true
        readUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-unidesk.git
      gitops:
        branch: master
        flushDisposition: not-a-gitops-branch
      snapshot:
        naming: historical-gitea-actions-prefix-retained-for-existing-refs
        prefix: refs/unidesk/snapshots/gitea-actions/unidesk-master-nc01
      legacyGitMirror:
        readUrl: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/unidesk.git
        configRef: config/cicd-branch-followers.yaml#controller.source.gitMirrorReadUrl
        disposition: replaced-by-gitea
    - key: sub2rank-nc01
      targetId: NC01
      upstream:
        repository: pikasTech/sub2rank
        cloneUrl: https://github.com/pikasTech/sub2rank.git
        branch: master
      gitea:
        owner: mirrors
        name: pikasTech-sub2rank
        mirrorMode: controlled-push
        publicRead: true
        readUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-sub2rank.git
      gitops:
        branch: master
        flushDisposition: not-a-gitops-branch
      snapshot:
        naming: application-source-snapshot
        prefix: refs/unidesk/snapshots/gitea-actions/sub2rank-master-nc01
      legacyGitMirror:
        readUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-sub2rank.git
        configRef: config/platform-infra/sub2rank.yaml#application.remote
        disposition: replaced-by-gitea
    - key: hwlab-jd01-v03
      targetId: JD01
      upstream:
        repository: pikasTech/HWLAB
        cloneUrl: https://github.com/pikasTech/HWLAB.git
        branch: v0.3
      gitea:
        owner: mirrors
        name: pikasTech-HWLAB
        mirrorMode: controlled-push
        publicRead: true
        readUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git
      gitops:
        branch: v0.3-gitops
        flushDisposition: retained-for-gitops-flush
      snapshot:
        naming: historical-gitea-actions-prefix-retained-for-existing-refs
        prefix: refs/unidesk/snapshots/gitea-actions/hwlab-node-runtime/v0.3
      legacyGitMirror:
        readUrl: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/HWLAB.git
        configRef: config/hwlab-node-lanes.yaml#lanes.v03.targets.JD01.git.readUrl
        disposition: replaced-by-gitea
    - key: hwlab-nc01-v03
      targetId: NC01
      upstream:
        repository: pikasTech/HWLAB
        cloneUrl: https://github.com/pikasTech/HWLAB.git
        branch: v0.3
      gitea:
        owner: mirrors
        name: pikasTech-HWLAB
        mirrorMode: controlled-push
        publicRead: true
        readUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikasTech-HWLAB.git
      gitops:
        branch: v0.3-gitops
        flushDisposition: retained-for-gitops-flush
      snapshot:
        naming: historical-gitea-actions-prefix-retained-for-existing-refs
        prefix: refs/unidesk/snapshots/gitea-actions/hwlab-node-runtime/v0.3
      legacyGitMirror:
        readUrl: http://git-mirror-http.devops-infra.svc.cluster.local:8080/pikasTech/HWLAB.git
        configRef: config/hwlab-node-lanes.yaml#lanes.v03.targets.NC01.git.readUrl
        disposition: replaced-by-gitea
    - key: selfmedia-nc01
      targetId: NC01
      credentialOverride:
        github:
          transport: https-token
          sourceRef: pikainc-selfmedia-gh-token.txt
          sourceKey: GH_TOKEN
          format: raw-token
          requiredFor:
            - upstream-mirror
            - mirror-sync
            - managed-repository-fetch
            - github-head-observe
            - github-hooks-list
            - github-hooks-reconcile
          permissions:
            contents: read
            metadata: read
            webhooks: read-write
          gitFetchCredential:
            apiVersion: unidesk.ai/v1
            kind: GitFetchCredential
            authMode: github-https-token
            host: github.com
            secretRef:
              namespace: devops-infra
              name: gitea-github-sync-secrets
              key: github-token-pikainc-selfmedia
      upstream:
        repository: pikainc/selfmedia
        cloneUrl: https://github.com/pikainc/selfmedia.git
        branch: master
        visibility: private
      gitea:
        owner: mirrors
        name: pikainc-selfmedia
        mirrorMode: controlled-push
        publicRead: false
        readUrl: http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/pikainc-selfmedia.git
      gitops:
        branch: nc01-selfmedia-gitops
        flushDisposition: gitea-writeback
      snapshot:
        naming: gitea-actions-immutable-source
        prefix: refs/unidesk/snapshots/gitea-actions/selfmedia-master-nc01
      legacyGitMirror: null

targets:
  - id: JD01
    route: JD01:k3s
    namespace: devops-infra
    role: active-source-authority
    enabled: true
    createNamespace: true
    storageClassName: local-path
    publicExposure:
      enabled: false
  - id: NC01
    route: NC01:k3s
    namespace: devops-infra
    role: active-source-authority
    enabled: true
    createNamespace: true
    storageClassName: local-path
    publicExposure:
      enabled: true
    webhookSync:
      publicPath: /_unidesk/github-to-gitea/nc01
      frpc:
        proxyName: platform-infra-gitea-nc01-github-webhook
        remotePort: 22086

app:
  name: gitea
  statefulSetName: gitea
  serviceName: gitea-http
  replicas: 1
  image:
    repository: docker.gitea.com/gitea
    tag: 1.26.4-rootless
    pullPolicy: IfNotPresent
  service:
    type: ClusterIP
    httpPort: 3000
    sshPort: 2222
  server:
    domain: gitea.pikapython.com
    rootUrl: https://gitea.pikapython.com/
    sshDomain: gitea-http.devops-infra.svc.cluster.local
    protocol: http
    startSshServer: true
  publicExposure:
    enabled: true
    publicBaseUrl: https://gitea.pikapython.com
    secretRoot: /root/.unidesk/.state/secrets
    dns:
      hostname: gitea.pikapython.com
      expectedA: 82.156.23.220
      resolvers: [1.1.1.1, 8.8.8.8, 223.5.5.5, 114.114.114.114]
    frpc:
      deploymentName: gitea-frpc
      secretName: gitea-frpc-secrets
      secretKey: frpc.toml
      image: fatedier/frpc:v0.68.1
      serverAddr: 82.156.23.220
      serverPort: 22000
      proxyName: platform-infra-gitea-nc01-web
      remotePort: 22080
      localIP: gitea-http.devops-infra.svc.cluster.local
      localPort: 3000
      tokenSourceRef: platform-infra/pk01-frp.env
      tokenSourceKey: FRP_TOKEN
    pk01:
      route: PK01
      caddyConfigPath: /etc/caddy/Caddyfile
      caddyServiceName: caddy
      responseHeaderTimeoutSeconds: 600
  database:
    type: sqlite3
    path: /var/lib/gitea/gitea.db
  actions:
    enabled: true
  webhook:
    allowedHostList: private,loopback
  registration:
    disabled: true
  storage:
    data:
      size: 8Gi
      mountPath: /var/lib/gitea
    config:
      size: 1Gi
      mountPath: /etc/gitea
  securityContext:
    runAsUser: 1000
    runAsGroup: 1000
    fsGroup: 1000
  resources:
    requests:
      cpu: 100m
      memory: 256Mi
    limits:
      cpu: "1"
      memory: 1Gi
  probes:
    healthPath: /api/healthz
    initialDelaySeconds: 30
    periodSeconds: 10
    timeoutSeconds: 5
    failureThreshold: 12

validation:
  waitTimeoutSeconds: 55
  healthPath: /api/healthz
