Repository navigation
218 lines (194 loc) · 9.47 KB
/
Copy pathcomponent-updates.yml
File metadata and controls
218 lines (194 loc) · 9.47 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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
name: Update released components
on:
workflow_dispatch:
permissions:
contents: write
pull-requests: write
issues: write
concurrency:
group: component-release-sync
cancel-in-progress: false
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Check out pi-agent-desktop
uses: actions/checkout@v7
with:
fetch-depth: 0
ref: main
- name: Set up Node.js
uses: actions/setup-node@v7
with:
node-version: 22
cache: npm
- name: Install current dependencies
run: npm ci
- name: Resolve latest component releases
id: releases
env:
GITHUB_TOKEN: ${{ github.token }}
run: node scripts/resolve-component-releases.mjs
# A sync held for review keeps `needs_update` true until it is merged, so
# without this the job would redo the same work — and fail on the existing
# branch — every night while the PR sits open.
- name: Skip if this sync is already awaiting review
id: pending
if: steps.releases.outputs.pi_web_update == 'true'
env:
GH_TOKEN: ${{ github.token }}
PI_WEB_TAG: ${{ steps.releases.outputs.pi_web_tag }}
run: |
set -euo pipefail
open="$(gh pr list --repo "$GITHUB_REPOSITORY" --state open \
--head "sync/pi-web-$PI_WEB_TAG" --limit 1 --json number --jq '.[0].number // empty')"
if [ -n "$open" ]; then
echo "Sync for $PI_WEB_TAG is already open as PR #$open; nothing to do."
echo "awaiting_review=true" >> "$GITHUB_OUTPUT"
else
echo "awaiting_review=false" >> "$GITHUB_OUTPUT"
fi
# Classify BEFORE merging: once the merge commit exists the incoming
# changeset is no longer recoverable with a plain diff.
- name: Classify the upstream changeset against the fork boundary
id: boundary
if: steps.releases.outputs.pi_web_update == 'true' && steps.pending.outputs.awaiting_review != 'true'
env:
PI_WEB_TAG: ${{ steps.releases.outputs.pi_web_tag }}
run: |
set -euo pipefail
git remote add pi-web-upstream https://github.com/agegr/pi-web.git
git fetch --no-tags pi-web-upstream "refs/tags/$PI_WEB_TAG:refs/tags/pi-web-release"
base="$(git merge-base HEAD refs/tags/pi-web-release)"
git diff --name-only "$base" refs/tags/pi-web-release \
| node scripts/fork-ownership.mjs classify -
- name: Synchronize released components
if: steps.releases.outputs.needs_update == 'true' && steps.pending.outputs.awaiting_review != 'true'
env:
PI_VERSION: ${{ steps.releases.outputs.pi_version }}
PI_UPDATE: ${{ steps.releases.outputs.pi_update }}
PI_WEB_UPDATE: ${{ steps.releases.outputs.pi_web_update }}
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
# When a pi-web merge is also pending, defer the pi install until after
# the merge: installing first dirties the tree and git refuses to merge.
if [ "$PI_UPDATE" = "true" ] && [ "$PI_WEB_UPDATE" != "true" ]; then
npm install --save-exact $(node scripts/pi-packages.mjs --install-spec "$PI_VERSION")
fi
if [ "$PI_WEB_UPDATE" = "true" ]; then
# The tag was already fetched by the boundary classification step.
git merge --no-edit --no-ff refs/tags/pi-web-release
# globals.css / settings.css must still equal upstream after the
# merge; this fails if fork rules crept back in, and otherwise moves
# the hashes checked by scripts/upstream-css-baseline.test.mjs.
node scripts/upstream-css-baseline.mjs update refs/tags/pi-web-release
npm install
if [ "$PI_UPDATE" = "true" ]; then
npm install --save-exact $(node scripts/pi-packages.mjs --install-spec "$PI_VERSION")
fi
fi
node scripts/bump-pi-agent-desktop-version.mjs
npm run release:manifest
# A clean `git merge` is not evidence the two sides agree, so the gate has
# to be as wide as it can cheaply be. Component tests are included here
# deliberately: upstream ships them and they cover fork-modified files.
- name: Verify the merged tree
if: steps.releases.outputs.needs_update == 'true' && steps.pending.outputs.awaiting_review != 'true'
run: |
set -euo pipefail
npm test
node_modules/.bin/tsc --noEmit
npm run lint
# Build the standalone output the desktop app actually ships, so a
# broken bundle fails here rather than midway through a signed release.
PI_WEB_DESKTOP_BUILD=1 node_modules/.bin/next build --webpack
- name: Commit the sync
if: steps.releases.outputs.needs_update == 'true' && steps.pending.outputs.awaiting_review != 'true'
run: |
set -euo pipefail
git add --all
git commit -m "chore: sync released pi components"
# Upstream did not touch anything this fork has modified, so a manually
# requested sync may update main without a review PR. Publishing a signed
# release remains a separate, manually dispatched action.
- name: Publish manually requested sync
if: steps.releases.outputs.needs_update == 'true' && steps.pending.outputs.awaiting_review != 'true' && steps.boundary.outputs.review_required != 'true'
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
git push origin HEAD:main
# Upstream changed files the fork has also rewritten. Git may have merged
# them cleanly and still be wrong, so a human reviews before anything is
# signed and published.
- name: Open a review PR
if: steps.releases.outputs.needs_update == 'true' && steps.pending.outputs.awaiting_review != 'true' && steps.boundary.outputs.review_required == 'true'
env:
GH_TOKEN: ${{ github.token }}
PI_WEB_TAG: ${{ steps.releases.outputs.pi_web_tag }}
HIGHEST_RISK: ${{ steps.boundary.outputs.highest_risk }}
BOUNDARY_REPORT: ${{ steps.boundary.outputs.report }}
run: |
set -euo pipefail
branch="sync/pi-web-$PI_WEB_TAG"
git push --force-with-lease origin "HEAD:refs/heads/$branch"
{
echo "Automated sync of \`$PI_WEB_TAG\`, held for review."
echo
echo "$BOUNDARY_REPORT"
echo
echo "Tests, \`tsc --noEmit\`, lint and the desktop build all passed —"
echo "that is exactly why this needs eyes. Check the listed files for"
echo "behaviour the merge kept from both sides."
echo
echo "After merging, dispatch \`release.yml\` manually when ready to publish."
} > /tmp/pr-body.md
gh pr create \
--repo "$GITHUB_REPOSITORY" \
--base main \
--head "$branch" \
--title "chore: sync pi-web $PI_WEB_TAG (review required: $HIGHEST_RISK risk)" \
--body-file /tmp/pr-body.md
# Without this a failed sync is silent, and the fork quietly falls behind
# upstream until someone happens to look at the Actions tab.
- name: Report a failed sync
if: failure()
env:
GH_TOKEN: ${{ github.token }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
set -euo pipefail
{
echo "## Component sync failed"
echo
echo "[Run log]($RUN_URL)"
echo
echo "Most likely a merge conflict against a file listed in"
echo "\`scripts/fork-ownership.json\`. See docs/ownership-boundaries.md."
} >> "$GITHUB_STEP_SUMMARY"
# Issues are disabled on this repository today, and an issue-only
# alert fails silently when they are. The summary above always works.
issues_enabled="$(gh api "repos/$GITHUB_REPOSITORY" --jq .has_issues 2>/dev/null || echo false)"
if [ "$issues_enabled" != "true" ]; then
echo "Issues are disabled for $GITHUB_REPOSITORY; reported in the job summary only."
echo "Enable Issues to also get a persistent, notifying alert." >> "$GITHUB_STEP_SUMMARY"
exit 0
fi
existing="$(gh issue list --repo "$GITHUB_REPOSITORY" \
--state open --label component-sync-failure --limit 1 --json number --jq '.[0].number // empty')"
if [ -n "$existing" ]; then
gh issue comment "$existing" --repo "$GITHUB_REPOSITORY" \
--body "Sync failed again: $RUN_URL"
else
gh label create component-sync-failure --repo "$GITHUB_REPOSITORY" \
--color B60205 --description "Automated pi/pi-web sync needs attention" 2>/dev/null || true
gh issue create --repo "$GITHUB_REPOSITORY" \
--title "Component sync failed" \
--label component-sync-failure \
--body "The nightly pi/pi-web sync failed: $RUN_URL
Most likely a merge conflict against a file listed in \`scripts/fork-ownership.json\`.
See docs/ownership-boundaries.md for how to resolve it. This issue is reused for
subsequent failures — close it once the sync is green again."
fi