Repository navigation
143 lines (124 loc) 路 5.9 KB
/
Copy pathsync-internal-docs.yml
File metadata and controls
143 lines (124 loc) 路 5.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
name: Sync internal-docs submodule
on:
schedule:
- cron: '0 */4 * * *'
workflow_dispatch:
concurrency:
group: sync-internal-docs
cancel-in-progress: false
jobs:
sync:
name: Bump internal-docs submodule pointer on dev
runs-on: ubuntu-latest
permissions:
contents: read
steps:
# The .internal-docs submodule lives in the upstream private repo
# browseros-ai/internal-docs and is only reachable from the upstream
# BrowserOS. This workflow is inherited by forks (e.g. gHashTag/BrowserOS),
# where that submodule 404s. Gate the whole sync on the upstream identity so
# forks exit cleanly WITHOUT touching INTERNAL_DOCS_SYNC_TOKEN, while
# upstream keeps the full token-preflight + sync behavior below.
- name: Repository identity guard (upstream-only sync)
id: identity
env:
REPO: ${{ github.repository }}
run: |
if [ "${REPO}" = "browseros-ai/BrowserOS" ]; then
echo "Running in upstream ${REPO}; proceeding with internal-docs sync."
echo "is_upstream=true" >> "$GITHUB_OUTPUT"
else
echo "Repository ${REPO} is a fork of browseros-ai/BrowserOS. The internal-docs sync is upstream-only; skipping without accessing any secret."
echo "is_upstream=false" >> "$GITHUB_OUTPUT"
fi
# The .internal-docs submodule lives in a separate private repository, so
# syncing it requires a cross-repo credential that the default GITHUB_TOKEN
# does not carry. When that secret is absent (e.g. the handoff window before
# an admin provisions it), skip cleanly instead of hard-failing checkout on
# an empty `token:` input. Once the secret exists, the full sync runs below.
- name: Check sync token availability
id: preflight
if: steps.identity.outputs.is_upstream == 'true'
env:
TOKEN: ${{ secrets.INTERNAL_DOCS_SYNC_TOKEN }}
run: |
if [ -z "${TOKEN}" ]; then
echo "INTERNAL_DOCS_SYNC_TOKEN is not configured; skipping internal-docs sync."
echo "token_present=false" >> "$GITHUB_OUTPUT"
else
echo "token_present=true" >> "$GITHUB_OUTPUT"
fi
- name: Rewrite SSH submodule URL to HTTPS-with-token
if: steps.identity.outputs.is_upstream == 'true' && steps.preflight.outputs.token_present == 'true'
env:
TOKEN: ${{ secrets.INTERNAL_DOCS_SYNC_TOKEN }}
run: |
git config --global "url.https://x-access-token:${TOKEN}@github.com/.insteadOf" "git@github.com:"
- uses: actions/checkout@v4
if: steps.identity.outputs.is_upstream == 'true' && steps.preflight.outputs.token_present == 'true'
with:
token: ${{ secrets.INTERNAL_DOCS_SYNC_TOKEN }}
submodules: true
ref: dev
fetch-depth: 50
- name: Open auto-merge PR if internal-docs has new commits
if: steps.identity.outputs.is_upstream == 'true' && steps.preflight.outputs.token_present == 'true'
env:
GH_TOKEN: ${{ secrets.INTERNAL_DOCS_SYNC_TOKEN }}
run: |
set -euo pipefail
# Skip if submodule not yet configured (handoff window before someone adds it)
if ! git config --file .gitmodules --get-regexp '^submodule\..internal-docs\.path$' >/dev/null 2>&1; then
echo "internal-docs submodule not yet configured in .gitmodules. Skipping."
exit 0
fi
EXISTING_PR_URL=$(gh pr list \
--base dev \
--state open \
--json headRefName,url \
--jq '[.[] | select(.headRefName | startswith("bot/sync-internal-docs-")) | .url][0] // ""')
if [ -n "$EXISTING_PR_URL" ]; then
echo "An internal-docs sync PR is already open: $EXISTING_PR_URL"
exit 0
fi
git submodule update --remote --merge .internal-docs
if git diff --quiet .internal-docs; then
echo "No internal-docs changes to sync."
exit 0
fi
BRANCH="bot/sync-internal-docs-$(date -u +%Y%m%d-%H%M%S)"
git config user.name "browseros-bot"
git config user.email "bot@browseros.ai"
git checkout -b "$BRANCH"
git add .internal-docs
git commit -m "chore: sync internal-docs submodule"
CLEANUP_BRANCH=0
cleanup_branch() {
if [ "$CLEANUP_BRANCH" = "1" ]; then
git push origin --delete "$BRANCH" >/dev/null 2>&1 || true
fi
}
trap cleanup_branch ERR
git push -u origin "$BRANCH"
CLEANUP_BRANCH=1
PR_URL=$(gh pr create \
--base dev \
--head "$BRANCH" \
--title "chore: sync internal-docs submodule" \
--body "Automated bump of the \`.internal-docs\` submodule pointer. Auto-merging.")
CLEANUP_BRANCH=0
trap - ERR
if ! gh pr merge "$PR_URL" --squash --delete-branch; then
PR_STATE=$(gh pr view "$PR_URL" --json mergeStateStatus,statusCheckRollup)
MERGE_STATE=$(jq -r '.mergeStateStatus' <<<"$PR_STATE")
FAILED_CHECKS=$(jq '[.statusCheckRollup[] | select(
(.__typename == "CheckRun" and ((.conclusion // "") | test("^(FAILURE|CANCELLED|TIMED_OUT|ACTION_REQUIRED)$"))) or
(.__typename == "StatusContext" and ((.state // "") | test("^(FAILURE|ERROR)$")))
)] | length' <<<"$PR_STATE")
if [ "$MERGE_STATE" = "DIRTY" ] || [ "$FAILED_CHECKS" -gt 0 ]; then
echo "Immediate merge failed and PR is not auto-mergeable (mergeStateStatus=$MERGE_STATE, failedChecks=$FAILED_CHECKS). Leaving PR open."
exit 1
fi
echo "Immediate merge failed with mergeStateStatus=$MERGE_STATE and no failed checks; enabling auto-merge."
gh pr merge "$PR_URL" --auto --squash --delete-branch
fi