diff --git a/.github/workflows/on-child-update.yml b/.github/workflows/on-child-update.yml new file mode 100644 index 0000000..679d2c6 --- /dev/null +++ b/.github/workflows/on-child-update.yml @@ -0,0 +1,83 @@ +name: On Child Repo Update + +on: + repository_dispatch: + types: [child-repo-updated] + +concurrency: + group: child-repo-sync + cancel-in-progress: false + +permissions: + contents: write + pull-requests: write + +jobs: + create-sync-pr: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.PARENT_REPO_PAT }} + + - name: Create sync PR + env: + REPO_NAME: ${{ github.event.client_payload.repo_name }} + FULL_SHA: ${{ github.event.client_payload.sha }} + GH_TOKEN: ${{ secrets.PARENT_REPO_PAT }} + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + + REPO_NAME="${REPO_NAME:-unknown}" + SHORT_SHA="${FULL_SHA:0:7}" + SHORT_SHA="${SHORT_SHA:-$(date +%s | tail -c 8)}" + + BRANCH="sync/${REPO_NAME}/${SHORT_SHA}" + PR_TITLE="chore(${REPO_NAME}): sync ${SHORT_SHA}" + + # Check for existing branch + if git ls-remote --exit-code origin "refs/heads/$BRANCH" >/dev/null 2>&1; then + EXISTING_PR=$(gh pr list --head "$BRANCH" --base main --json url --jq '.[0].url // empty') + if [[ -n "$EXISTING_PR" ]]; then + echo "PR already exists: $EXISTING_PR" + gh pr merge "$EXISTING_PR" --auto --squash --delete-branch || true + exit 0 + fi + # Branch exists but no PR — previous run pushed but failed to create PR. + # Delete the orphaned branch and recreate cleanly. + echo "Found orphaned branch $BRANCH (no PR) — deleting and recreating" + delete_output=$(git push origin --delete "$BRANCH" 2>&1) || { + if git ls-remote --exit-code origin "refs/heads/$BRANCH" >/dev/null 2>&1; then + echo "Failed to delete orphaned branch: $delete_output" + exit 1 + fi + } + fi + + git checkout -b "$BRANCH" + git commit --allow-empty -m "$PR_TITLE" + + push_output=$(git push -u origin "$BRANCH" 2>&1) || { + if echo "$push_output" | grep -qE "(non-fast-forward|already exists|fetch first)"; then + echo "Push failed due to race condition — another run likely handled this" + exit 0 + fi + echo "Push failed unexpectedly: $push_output" + exit 1 + } + + PR_URL=$(gh pr create \ + --title "$PR_TITLE" \ + --body "Synced from \`${REPO_NAME}@${SHORT_SHA}\`" \ + --head "$BRANCH" \ + --base main) || { + echo "PR creation failed — deleting orphaned branch" + git push origin --delete "$BRANCH" || true + exit 1 + } + + gh pr merge "$PR_URL" --auto --squash --delete-branch || true + echo "PR ready: $PR_URL" +