From 25d1187ad65de99d9274188443fcec7f553eea5d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 18 May 2026 11:09:25 +0000 Subject: [PATCH 1/2] Initial plan From d9470293bb3d0f7e48fff06eacc885a2c005fcc5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 18 May 2026 11:14:48 +0000 Subject: [PATCH 2/2] fix: target manifest commit instead of blindly amending HEAD - Add X-Manifest-PR: true trailer to the initial manifest commit so it can be located reliably on later workflow runs. - Synchronize step: find the manifest commit, collect any user commits stacked above it, reset to its parent, re-apply it (amend committer date for a new SHA to retrigger CI), then cherry-pick user commits. - Merged step: same discovery, then update west.yml only in the manifest commit (preserving its message), cherry-pick user commits back on top, rebase onto upstream if conflicts exist, and push. - Backwards-compatible fallback searches by 'auto-manifest PR' subject for branches created before the marker was introduced. - Add per-cherry-pick error handling with clear failure messages. Agent-Logs-Url: https://github.com/nrfconnect/action-manifest-pr/sessions/2011b57a-adad-461d-87a3-46e574e14293 Co-authored-by: thst-nordic <14976801+thst-nordic@users.noreply.github.com> --- action.yml | 92 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 82 insertions(+), 10 deletions(-) diff --git a/action.yml b/action.yml index 9b26b96..c8da283 100644 --- a/action.yml +++ b/action.yml @@ -148,7 +148,7 @@ runs: run: | git checkout -b manifest_pr git add west.yml - git commit -m "manifest: Update ${{ github.event.repository.name }} revision (auto-manifest PR)" -m "$BODY" --signoff + git commit -m "manifest: Update ${{ github.event.repository.name }} revision (auto-manifest PR)" -m "$BODY" -m "X-Manifest-PR: true" --signoff git remote add fork "https://nordicbuilder:${{ inputs.token }}@github.com/${{ inputs.forked-repo }}" git push -u fork manifest_pr:auto-manifest-${{ github.event.repository.name }}-${{ github.event.pull_request.number }} USERNAME=$(echo "${{ inputs.forked-repo }}" | cut -d'/' -f1) @@ -170,33 +170,105 @@ runs: if: ${{ github.event.action == 'synchronize' && steps.check.outputs.SKIP_STRING != 'true' }} shell: bash run: | - git checkout auto-manifest-${{ github.event.repository.name }}-${{ github.event.pull_request.number }} + BRANCH="auto-manifest-${{ github.event.repository.name }}-${{ github.event.pull_request.number }}" + git checkout "$BRANCH" git remote add upstream https://github.com/${{ inputs.target-repo }} git fetch upstream git rebase upstream/${{ inputs.base-branch }} -X theirs + + # Find the original manifest commit by its durable marker + MANIFEST_COMMIT=$(git log "upstream/${{ inputs.base-branch }}..HEAD" \ + --grep='X-Manifest-PR: true' --format='%H' | tail -1) + # Fallback for branches created before the marker was introduced + if [ -z "$MANIFEST_COMMIT" ]; then + MANIFEST_COMMIT=$(git log "upstream/${{ inputs.base-branch }}..HEAD" \ + --grep='auto-manifest PR' --format='%H' | tail -1) + fi + if [ -z "$MANIFEST_COMMIT" ]; then + echo "Error: could not locate the manifest commit in the branch." >&2 + exit 1 + fi + + # Collect any commits stacked on top of the manifest commit + AFTER_COMMITS=$(git rev-list --reverse "${MANIFEST_COMMIT}..HEAD") + + # Rewind to the parent of the manifest commit + git reset --hard "${MANIFEST_COMMIT}^" + + # Re-apply the manifest commit then amend its committer date to get a new SHA, + # which is necessary to retrigger CI when there are no upstream changes. + git cherry-pick "$MANIFEST_COMMIT" git commit --amend --no-edit - git push origin auto-manifest-${{ github.event.repository.name }}-${{ github.event.pull_request.number }}:auto-manifest-${{ github.event.repository.name }}-${{ github.event.pull_request.number }} -f + + # Re-apply any commits that were stacked above the manifest commit + for c in $AFTER_COMMITS; do + if ! git cherry-pick "$c"; then + echo "Error: cherry-pick of commit $c failed. Aborting." >&2 + git cherry-pick --abort + exit 1 + fi + done + + git push origin "$BRANCH:$BRANCH" -f # This is used for changing PR pointer to sha in west.yml (assumes manifest PR exists) - name: Change commit sha and push it if: ${{ github.event.pull_request.merged == true && steps.check.outputs.SKIP_STRING != 'true' }} shell: bash run: | - git checkout auto-manifest-${{ github.event.repository.name }}-${{ github.event.pull_request.number }} + BRANCH="auto-manifest-${{ github.event.repository.name }}-${{ github.event.pull_request.number }}" + git checkout "$BRANCH" + git remote add upstream https://github.com/${{ inputs.target-repo }} + git fetch upstream + + # Find the original manifest commit by its durable marker + MANIFEST_COMMIT=$(git log "upstream/${{ inputs.base-branch }}..HEAD" \ + --grep='X-Manifest-PR: true' --format='%H' | tail -1) + # Fallback for branches created before the marker was introduced + if [ -z "$MANIFEST_COMMIT" ]; then + MANIFEST_COMMIT=$(git log "upstream/${{ inputs.base-branch }}..HEAD" \ + --grep='auto-manifest PR' --format='%H' | tail -1) + fi + if [ -z "$MANIFEST_COMMIT" ]; then + echo "Error: could not locate the manifest commit in the branch." >&2 + exit 1 + fi + + # Collect any commits stacked on top of the manifest commit + AFTER_COMMITS=$(git rev-list --reverse "${MANIFEST_COMMIT}..HEAD") + + # Save the manifest commit message to reuse it on the rewritten commit + git log -1 --format='%B' "$MANIFEST_COMMIT" > /tmp/manifest_commit_msg.txt + + # Rewind to the parent of the manifest commit and restore west.yml at that revision + git reset --hard "${MANIFEST_COMMIT}^" + git checkout "$MANIFEST_COMMIT" -- west.yml + + # Update west.yml revision from the PR pointer to the merge commit SHA PROJECT_KEY=$(yq --exit-status '.manifest.projects[] | select(.repo-path == "${{ github.event.repository.name }}") | key' west.yml) yq ".manifest.projects[$PROJECT_KEY].revision = \"${{ github.event.pull_request.merge_commit_sha }}\"" west.yml > tmp.yml diff -B west.yml tmp.yml | patch west.yml - || true + + # Commit the updated west.yml, preserving the original manifest commit message git add west.yml - git commit --amend --no-edit - git remote add upstream https://github.com/${{ inputs.target-repo }} - git fetch upstream + git commit -F /tmp/manifest_commit_msg.txt + + # Re-apply any commits that were stacked above the manifest commit + for c in $AFTER_COMMITS; do + if ! git cherry-pick "$c"; then + echo "Error: cherry-pick of commit $c failed. Aborting." >&2 + git cherry-pick --abort + exit 1 + fi + done + set +e - git merge-tree --write-tree --name-only upstream/${{ inputs.base-branch }} auto-manifest-${{ github.event.repository.name }}-${{ github.event.pull_request.number }} + git merge-tree --write-tree --name-only upstream/${{ inputs.base-branch }} HEAD has_conflict="$?" echo "has_conflict is" $has_conflict set -e - if (( $has_conflict == 1)) ; then git rebase upstream/${{ inputs.base-branch }} -X theirs ; fi - git push origin auto-manifest-${{ github.event.repository.name }}-${{ github.event.pull_request.number }}:auto-manifest-${{ github.event.repository.name }}-${{ github.event.pull_request.number }} -f + if (( $has_conflict == 1 )); then git rebase upstream/${{ inputs.base-branch }} -X theirs ; fi + git push origin "$BRANCH:$BRANCH" -f - name: Close manifest-PR upon closing PR if: ${{ github.event.action == 'closed' && github.event.pull_request.merged == false && steps.check.outputs.SKIP_STRING != 'true'}}