返回 CodeWhale
sync-cnb.yml
根目录 / .github / workflows / sync-cnb.yml
1 name: Sync to CNB
2
3 # Mirror commits and release tags to cnb.cool/codewhale.net/codewhale
4 # so users behind GitHub-blocking networks can fetch the source and tagged
5 # releases from the Tencent-hosted mirror.
6 #
7 # Triggers:
8 # * push to main → mirrors that commit to CNB main
9 # * tag matching v* → mirrors that tag to CNB
10 # * release work branches → mirrors release-candidate refs for CNB preflight
11 # * fix/rebrand branches → mirrors first-party heavy Linux CI refs
12 # * Tencent release branches → mirrors Feishu/Lighthouse setup branches
13 # * workflow_dispatch → manual fallback if any of the above fails
14 #
15 # Why the rewrite (v0.8.31):
16 # The previous implementation used the opaque tencentcom/git-sync Docker
17 # action, which discovered every local ref via fetch-depth: 0 and tried
18 # to push them all — including dependabot/* branches that GitHub had
19 # locally. Those follow-on pushes ran without the configured credential
20 # helper in scope and failed with
21 # `fatal: could not read Username for 'https://cnb.cool'`
22 # No concurrency block meant the main-push and tag-push workflow runs
23 # that auto-tag.yml fires within seconds of each other raced. About
24 # half of recent runs failed for those two reasons combined.
25
26 on:
27 push:
28 branches:
29 - main
30 - 'work/v*'
31 - 'fix/*'
32 - 'rebrand/*'
33 - 'work/v*-feishu-*'
34 - 'work/v*-lighthouse*'
35 tags: ['v*']
36 workflow_dispatch: {}
37
38 # Serialize runs so the back-to-back main-push + tag-push from auto-tag.yml
39 # don't race each other rebasing onto CNB. cancel-in-progress: false so
40 # every commit actually arrives — we'd rather queue than drop.
41 concurrency:
42 group: cnb-sync
43 cancel-in-progress: false
44
45 permissions:
46 contents: read
47
48 jobs:
49 sync:
50 runs-on: ubuntu-latest
51 steps:
52 - uses: actions/checkout@v7
53 with:
54 fetch-depth: 0
55
56 - name: Push triggering ref to CNB
57 env:
58 CNB_TOKEN: ${{ secrets.CNB_GIT_TOKEN }}
59 shell: bash
60 run: |
61 set -euo pipefail
62
63 if [ -z "${CNB_TOKEN:-}" ]; then
64 echo "::error::CNB_GIT_TOKEN secret is not set; cannot push to CNB." >&2
65 exit 1
66 fi
67
68 # URL-encode any '%' in the token so basic-auth doesn't break on
69 # special characters. CNB tokens are typically alphanumeric so
70 # this is belt-and-suspenders.
71 ENCODED_TOKEN="$(printf '%s' "${CNB_TOKEN}" | python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.stdin.read(), safe=""))')"
72 REMOTE_URL="https://cnb:${ENCODED_TOKEN}@cnb.cool/codewhale.net/codewhale.git"
73 # Use a masked alias so the token never appears in log lines.
74 git remote add cnb "${REMOTE_URL}"
75
76 # Push with retry on transient failures (CNB rate-limits, DNS
77 # blips, etc.). Args after `kind` are forwarded to `git push`
78 # so callers can pass `--force-with-lease`, multiple refspecs,
79 # etc. without quoting them into one string.
80 push_with_retry() {
81 local kind="$1"
82 shift
83 local attempt
84 for attempt in 1 2 3; do
85 echo "Attempt ${attempt}: pushing ${kind} to CNB"
86 if git push cnb "$@" 2>&1; then
87 echo "Successfully pushed ${kind} to CNB"
88 return 0
89 fi
90 if [ "${attempt}" -lt 3 ]; then
91 sleep $((attempt * 5))
92 fi
93 done
94 echo "::error::Failed to push ${kind} to CNB after 3 attempts" >&2
95 return 1
96 }
97
98 if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
99 TAG="${GITHUB_REF#refs/tags/}"
100 # Release tags may be repointed while rebuilding a failed
101 # publish attempt. CNB is a one-way mirror, so force the tag
102 # there to match GitHub instead of failing on "already exists".
103 push_with_retry "tag ${TAG}" "+refs/tags/${TAG}:refs/tags/${TAG}"
104 elif [[ "${GITHUB_REF}" == refs/heads/main ]]; then
105 # Plain --force. The CNB mirror is one-way by design —
106 # nothing else pushes to it, so there's no contributor work
107 # to protect against. `--force-with-lease` would be safer
108 # in a multi-writer scenario, but in our setup the lease
109 # check requires `refs/remotes/cnb/main` to exist in the
110 # runner's local clone, which it never does (we add `cnb`
111 # as a fresh remote in this step and don't fetch first).
112 # That made the lease check spuriously fail with
113 # `! [rejected] HEAD -> main (stale info)` even when CNB
114 # was actually behind GitHub.
115 push_with_retry "main" HEAD:refs/heads/main --force
116 else
117 # First-party fix/rebrand/release branches are first-class CNB
118 # sources for heavy Linux CI, release preflight, and
119 # Lighthouse/Feishu bootstrap.
120 # Mirror the triggering branch exactly so the CNB clone path stays
121 # useful before the branch has merged to main or become a release
122 # tag.
123 BRANCH="${GITHUB_REF#refs/heads/}"
124 push_with_retry "branch ${BRANCH}" "HEAD:refs/heads/${BRANCH}" --force
125 fi
126
126 lines YAML