Skip to content

Commit 0153694

Browse files
authored
fix: sync-preview pushes directly on clean merge, PRs only on conflict (#1078)
* fix: sync-preview workflow restores version instead of ignoring files Instead of keeping preview's entire package.json/package-lock.json (which discards new deps, scripts, etc. from main), accept main's content and surgically restore only the version field to preview's value after merge. * fix: push directly to preview on clean merge via GitHub App bypass Use agentcore-devx-automation app token to bypass branch protection and push directly when the merge is clean (or only version conflicts). Only creates a PR when there are real conflicts in other files. * chore: use app-slug instead of app-id for token generation * fix: address review feedback on sync-preview workflow - Pass PREVIEW_VERSION via env var instead of string interpolation in node -e scripts (safer against special chars) - Make git add of package-lock.json conditional on file existence to match the earlier -f guard - Replace loose title search for dedup with headRefName prefix filter to avoid false positives from unrelated PRs - Clarify why package.json/package-lock.json are special-cased (preview carries a different version string that needs preserving) * fix: restore preview-owned files after sync merge Adds a step to restore schemas/agentcore.schema.v1.json and CHANGELOG.md to preview's versions after merging main. These files are auto-generated during preview releases — schema-check CI rejects direct modifications to schemas/, and CHANGELOG.md tracks preview releases separately. * fix: use app-id instead of app-slug for GitHub App token Aligns with the pattern in PR #1210 and ci-failure-issue.yml.
1 parent f69e252 commit 0153694

1 file changed

Lines changed: 104 additions & 46 deletions

File tree

.github/workflows/sync-preview.yml

Lines changed: 104 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -17,101 +17,161 @@ jobs:
1717
name: Merge main into preview
1818
runs-on: ubuntu-latest
1919
steps:
20+
- name: Generate GitHub App Token
21+
id: app-token
22+
uses: actions/create-github-app-token@v1
23+
with:
24+
app-id: ${{ vars.APP_ID }}
25+
private-key: ${{ secrets.APP_PRIVATE_KEY }}
26+
2027
- name: Checkout preview
2128
uses: actions/checkout@v6
2229
with:
2330
ref: preview
2431
fetch-depth: 0
32+
token: ${{ steps.app-token.outputs.token }}
2533

2634
- name: Configure git
2735
run: |
2836
git config --global user.name "github-actions[bot]"
2937
git config --global user.email "github-actions[bot]@users.noreply.github.com"
3038
31-
- name: Merge main into preview
32-
id: merge
39+
- name: Check if sync needed
40+
id: check
3341
run: |
3442
git fetch origin main
3543
MAIN_SHA=$(git rev-parse origin/main)
3644
MERGE_BASE=$(git merge-base HEAD origin/main)
3745
3846
if [[ "$MAIN_SHA" == "$MERGE_BASE" ]]; then
3947
echo "✅ preview already contains all of main"
40-
echo "status=up-to-date" >> $GITHUB_OUTPUT
41-
exit 0
48+
echo "needed=false" >> $GITHUB_OUTPUT
49+
else
50+
echo "needed=true" >> $GITHUB_OUTPUT
4251
fi
4352
44-
echo "ℹ️ Merging main into preview..."
53+
- name: Skip if already synced
54+
if: steps.check.outputs.needed == 'false'
55+
run: echo "Nothing to sync."
56+
57+
- name: Merge main into preview
58+
if: steps.check.outputs.needed == 'true'
59+
id: merge
60+
run: |
61+
# Save preview's version before merge so we can restore it after
62+
PREVIEW_VERSION=$(node -p "require('./package.json').version")
63+
echo "preview_version=$PREVIEW_VERSION" >> $GITHUB_OUTPUT
4564
4665
if git merge origin/main --no-edit -m "chore: merge main into preview"; then
47-
git push origin preview
48-
echo "✅ main merged into preview and pushed"
49-
echo "status=merged" >> $GITHUB_OUTPUT
66+
echo "status=clean" >> $GITHUB_OUTPUT
5067
else
51-
git merge --abort
52-
echo "status=conflict" >> $GITHUB_OUTPUT
68+
# preview carries a higher version string than main (e.g. 1.0.0-preview.X vs 0.13.X).
69+
# This means package.json/package-lock.json almost always conflict on the version field.
70+
# Accept main's content here; the version is restored in the next step.
71+
for f in package.json package-lock.json; do
72+
if git diff --name-only --diff-filter=U | grep -qx "$f"; then
73+
git checkout --theirs "$f"
74+
git add "$f"
75+
echo " ↳ resolved $f conflict (accepted main, will restore version)"
76+
fi
77+
done
78+
79+
# Check if all conflicts are now resolved
80+
if [[ -z "$(git diff --name-only --diff-filter=U)" ]]; then
81+
git commit --no-edit -m "chore: merge main into preview"
82+
echo "status=clean" >> $GITHUB_OUTPUT
83+
else
84+
echo "status=conflict" >> $GITHUB_OUTPUT
85+
fi
5386
fi
5487
55-
- name: Generate GitHub App Token
56-
if: steps.merge.outputs.status == 'conflict'
57-
id: app-token
58-
uses: actions/create-github-app-token@v1
59-
with:
60-
app-id: ${{ vars.APP_ID }}
61-
private-key: ${{ secrets.APP_PRIVATE_KEY }}
88+
- name: Restore preview-owned files
89+
if: steps.merge.outputs.status == 'clean'
90+
run: |
91+
# These files are auto-generated during preview releases and must not
92+
# be overwritten by main's versions (schema-check CI will reject changes
93+
# to schemas/, and CHANGELOG.md tracks preview releases separately).
94+
PREVIEW_HEAD=$(git rev-parse HEAD^1)
95+
for f in schemas/agentcore.schema.v1.json CHANGELOG.md; do
96+
if git show "$PREVIEW_HEAD:$f" > /dev/null 2>&1; then
97+
git show "$PREVIEW_HEAD:$f" > "$f"
98+
git add "$f"
99+
echo " ↳ restored preview's $f"
100+
fi
101+
done
102+
if ! git diff --cached --quiet; then
103+
git commit -m "chore: restore preview-owned files (schema, changelog)"
104+
fi
62105
63-
- name: Get original commit author
64-
if: steps.merge.outputs.status == 'conflict'
65-
id: author
106+
- name: Restore preview version and push
107+
if: steps.merge.outputs.status == 'clean'
66108
run: |
67-
AUTHOR=$(git log origin/main -1 --format='%an')
68-
GH_USER=$(git log origin/main -1 --format='%ae' | grep -oP '.*(?=@users\.noreply\.github\.com)' || echo "")
69-
if [[ -z "$GH_USER" ]]; then
70-
# Try to get GitHub username from the commit
71-
GH_USER=$(gh api "/repos/${{ github.repository }}/commits/$(git rev-parse origin/main)" --jq '.author.login // empty' 2>/dev/null || echo "")
109+
PREVIEW_VERSION="${{ steps.merge.outputs.preview_version }}"
110+
CURRENT_VERSION=$(node -p "require('./package.json').version")
111+
112+
if [[ "$CURRENT_VERSION" != "$PREVIEW_VERSION" ]]; then
113+
PREVIEW_VERSION="$PREVIEW_VERSION" node -e "
114+
const fs = require('fs');
115+
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
116+
pkg.version = process.env.PREVIEW_VERSION;
117+
fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');
118+
"
119+
if [[ -f package-lock.json ]]; then
120+
PREVIEW_VERSION="$PREVIEW_VERSION" node -e "
121+
const fs = require('fs');
122+
const lock = JSON.parse(fs.readFileSync('package-lock.json', 'utf8'));
123+
lock.version = process.env.PREVIEW_VERSION;
124+
if (lock.packages && lock.packages['']) {
125+
lock.packages[''].version = process.env.PREVIEW_VERSION;
126+
}
127+
fs.writeFileSync('package-lock.json', JSON.stringify(lock, null, 2) + '\n');
128+
"
129+
fi
130+
git add package.json
131+
[[ -f package-lock.json ]] && git add package-lock.json
132+
git commit -m "chore: restore preview version ($PREVIEW_VERSION)"
72133
fi
73-
echo "name=$AUTHOR" >> $GITHUB_OUTPUT
74-
echo "gh_user=$GH_USER" >> $GITHUB_OUTPUT
75-
env:
76-
GH_TOKEN: ${{ steps.app-token.outputs.token }}
134+
135+
git push origin HEAD:preview
136+
echo "✅ main merged into preview and pushed"
77137
78138
- name: Create PR for conflict resolution
79139
if: steps.merge.outputs.status == 'conflict'
80140
env:
81141
GH_TOKEN: ${{ steps.app-token.outputs.token }}
82-
AUTHOR_NAME: ${{ steps.author.outputs.name }}
83-
AUTHOR_GH: ${{ steps.author.outputs.gh_user }}
84142
run: |
85-
BRANCH="sync-preview/merge-main-$(date +%Y%m%d-%H%M%S)"
86-
87-
# Check if there's already an open sync PR
88-
EXISTING=$(gh pr list --base preview --search "sync-preview: merge main into preview" --state open --json number --jq 'length')
89-
if [[ "$EXISTING" != "0" ]]; then
143+
# Check if there's already an open sync PR (match by branch prefix, not title search)
144+
COUNT=$(gh pr list --base preview --state open --json headRefName \
145+
--jq '[.[] | select(.headRefName | startswith("sync-preview/"))] | length')
146+
if [[ "$COUNT" != "0" ]]; then
90147
echo "ℹ️ Sync PR already open — skipping duplicate."
91148
exit 0
92149
fi
93150
94-
# Create a branch from preview with the conflict markers
151+
# Abort the failed merge and redo on a branch for the PR
152+
git merge --abort
153+
154+
BRANCH="sync-preview/merge-main-$(date +%Y%m%d-%H%M%S)"
95155
git checkout -b "$BRANCH"
96-
git merge origin/main --no-edit -m "chore: merge main into preview" || true
156+
git merge origin/main --no-edit -m "chore: merge main into preview (conflicts need resolution)" || true
97157
git add -A
98158
git commit --no-edit -m "chore: merge main into preview (conflicts need resolution)" || true
99159
git push origin "$BRANCH"
100160
101-
# Build mention string
161+
GH_USER=$(gh api "/repos/${{ github.repository }}/commits/$(git rev-parse origin/main)" --jq '.author.login // empty' 2>/dev/null || echo "")
102162
MENTION=""
103-
if [[ -n "$AUTHOR_GH" ]]; then
104-
MENTION="cc @${AUTHOR_GH}"
163+
if [[ -n "$GH_USER" ]]; then
164+
MENTION="cc @${GH_USER}"
105165
fi
106166
107167
gh pr create \
108168
--base preview \
109169
--head "$BRANCH" \
110-
--title "sync-preview: merge main into preview" \
170+
--title "sync-preview: merge main into preview (conflicts)" \
111171
--body "$(cat <<BODY
112-
The automated sync-preview workflow could not cleanly merge \`main\` into \`preview\`.
172+
The automated sync could not cleanly merge \`main\` into \`preview\`.
113173
114-
**This PR contains the merge with conflict markers.** To resolve:
174+
**This PR contains conflict markers.** To resolve:
115175
116176
1. Check out this branch locally:
117177
\`\`\`bash
@@ -124,8 +184,6 @@ jobs:
124184
3. Keep preview-specific values (package version, preview tests, etc.) — accept main's changes for everything else.
125185
4. Commit and push, then merge this PR.
126186
127-
This must be resolved before the next coordinated release.
128-
129187
${MENTION}
130188
131189
_Opened automatically by the sync-preview workflow._

0 commit comments

Comments
 (0)