name: 'CI: Check merge source and destination' on: pull_request: branches: - master permissions: pull-requests: write contents: read jobs: check_branch: if: ${{ github.repository == 'n8n-io/n8n-private' }} name: enforce-bundle-branches-only-in-private runs-on: ubuntu-latest steps: - name: Validate head branch id: validate shell: bash run: | set -euo pipefail head="${{ github.head_ref }}" if [[ "$head" == bundle/* ]]; then echo "allowed=true" >> "$GITHUB_OUTPUT" else echo "allowed=false" >> "$GITHUB_OUTPUT" fi - name: Comment on PR (blocked) if: ${{ steps.validate.outputs.allowed == 'false' }} uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 with: script: | const owner = context.repo.owner; const repo = context.repo.repo; const issue_number = context.payload.pull_request.number; const head = context.payload.pull_request.head.ref; const base = context.payload.pull_request.base.ref; const marker = ""; const body = `${marker}\n` + `🚫 **Merge blocked**: PRs into \`${base}\` are only allowed from branches named \`bundle/*\`.\n\n` + `Current source branch: \`${head}\`\n\n` + `Merge your developments into a bundle branch instead of directly merging to master.`; // Find an existing marker comment (to update instead of spamming) const { data: comments } = await github.rest.issues.listComments({ owner, repo, issue_number, per_page: 100, }); const existing = comments.find(c => c.body && c.body.includes(marker)); if (existing) { await github.rest.issues.updateComment({ owner, repo, comment_id: existing.id, body, }); } else { await github.rest.issues.createComment({ owner, repo, issue_number, body, }); } - name: Fail (blocked) if: ${{ steps.validate.outputs.allowed == 'false' }} run: | echo "::error::You can only merge to master from a bundle/* branch. Got '${{ github.head_ref }}'." exit 1 - name: Allowed if: ${{ steps.validate.outputs.allowed == 'true' }} run: | echo "OK: '${{ github.head_ref }}' can merge into '${{ github.base_ref }}'"