@@ -100,7 +100,6 @@ jobs:
100100 id : config
101101 env :
102102 ENV_JSON : ${{ needs.load-env.outputs.env-json }}
103- GH_PAT_TOKEN : ${{ secrets.GH_PAT_TOKEN }}
104103 run : |
105104 echo "📋 Extracting auto-merge configuration from environment..."
106105
@@ -116,6 +115,8 @@ jobs:
116115 COMMENT_ON_DISABLE=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_COMMENT_ON_DISABLE')
117116 LABELS_TO_ADD=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_LABELS_TO_ADD')
118117 SKIP_BOT_PRS=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_SKIP_BOT_PRS')
118+ SKIP_FORK_PRS=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_SKIP_FORK_PRS')
119+ COMMENT_ON_FORK_SKIP=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_COMMENT_ON_FORK_SKIP')
119120 PREFERRED_TOKEN=$(echo "$ENV_JSON" | jq -r '.PREFERRED_GITHUB_TOKEN')
120121
121122 # Validate required configuration
@@ -135,6 +136,8 @@ jobs:
135136 echo "COMMENT_ON_DISABLE=$COMMENT_ON_DISABLE" >> $GITHUB_ENV
136137 echo "LABELS_TO_ADD=$LABELS_TO_ADD" >> $GITHUB_ENV
137138 echo "SKIP_BOT_PRS=$SKIP_BOT_PRS" >> $GITHUB_ENV
139+ echo "SKIP_FORK_PRS=$SKIP_FORK_PRS" >> $GITHUB_ENV
140+ echo "COMMENT_ON_FORK_SKIP=$COMMENT_ON_FORK_SKIP" >> $GITHUB_ENV
138141
139142 # Determine default merge type
140143 DEFAULT_MERGE_TYPE=$(echo "$MERGE_TYPES" | cut -d',' -f1)
@@ -156,12 +159,9 @@ jobs:
156159 echo " 💬 Comment on disable: $COMMENT_ON_DISABLE"
157160 echo " 🏷️ Labels to add: $LABELS_TO_ADD"
158161 echo " 🤖 Skip bot PRs: $SKIP_BOT_PRS"
159-
160- if [[ "$PREFERRED_TOKEN" == "GH_PAT_TOKEN" && -n "$GH_PAT_TOKEN" ]]; then
161- echo " 🔑 Token: Personal Access Token (PAT)"
162- else
163- echo " 🔑 Token: Default GITHUB_TOKEN"
164- fi
162+ echo " 🍴 Skip fork PRs: $SKIP_FORK_PRS"
163+ echo " 💬 Comment on fork skip: $COMMENT_ON_FORK_SKIP"
164+ echo " 🔑 Token: Selected via github-script action"
165165
166166 # --------------------------------------------------------------------
167167 # Process the PR for auto-merge
@@ -198,6 +198,43 @@ jobs:
198198 return;
199199 }
200200
201+ // ————————————————————————————————————————————————————————————————
202+ // Check if we should skip fork PRs
203+ // ————————————————————————————————————————————————————————————————
204+
205+ // Handle edge case: fork repository deleted/inaccessible (pr.head.repo is null)
206+ if (!pr.head.repo) {
207+ console.log('⚠️ PR head repository is null (fork may have been deleted)');
208+ if (process.env.SKIP_FORK_PRS === 'true') {
209+ console.log('🍴 Skipping PR with deleted fork source (security policy)');
210+ core.setOutput('action', 'skip-deleted-fork');
211+ return;
212+ }
213+ // If not skipping forks, log and continue (will be treated as same-repo PR)
214+ console.log('⚠️ Continuing with auto-merge processing (null repo treated as same-repo)');
215+ } else {
216+ // Safe to access pr.head.repo.full_name now
217+ const headRepoFullName = pr.head.repo.full_name;
218+ const baseRepoFullName = `${owner}/${repo}`;
219+ const isForkPR = headRepoFullName !== baseRepoFullName;
220+
221+ if (isForkPR && process.env.SKIP_FORK_PRS === 'true') {
222+ console.log('🍴 Skipping fork PR (security policy: fork PRs are not auto-merged)');
223+ console.log(` Fork source: ${headRepoFullName}`);
224+ console.log(` Base repository: ${baseRepoFullName}`);
225+ console.log(' Security reason: Fork PRs require manual maintainer review before merge');
226+
227+ // Note: Comments are not posted to fork PRs due to read-only GITHUB_TOKEN permissions
228+ // Fork PR handling is already managed by pull-request-management-fork.yml workflow
229+ if (process.env.COMMENT_ON_FORK_SKIP === 'true') {
230+ console.log(' ℹ️ Comment posting skipped for fork PR (handled by fork PR workflow)');
231+ }
232+
233+ core.setOutput('action', 'skip-fork');
234+ return;
235+ }
236+ }
237+
201238 // ————————————————————————————————————————————————————————————————
202239 // Check basic PR conditions
203240 // ————————————————————————————————————————————————————————————————
@@ -287,7 +324,7 @@ jobs:
287324 execSync(`gh pr merge --disable-auto "${pr.html_url}"`, {
288325 env: {
289326 ...process.env,
290- GH_TOKEN: '${{ secrets.GH_PAT_TOKEN || secrets .GITHUB_TOKEN }}'
327+ GH_TOKEN: process.env .GITHUB_TOKEN
291328 },
292329 stdio: 'inherit'
293330 });
@@ -304,8 +341,17 @@ jobs:
304341 }
305342
306343 core.setOutput('action', 'disabled-changes-requested');
307- } catch (error) {
308- console.log('ℹ️ Could not disable auto-merge (may not have been enabled)');
344+ } catch (disableError) {
345+ // Differentiate between "not enabled" and actual failures
346+ if (disableError.message && (
347+ disableError.message.includes('not enabled') ||
348+ disableError.message.includes('auto-merge is not enabled')
349+ )) {
350+ console.log('ℹ️ Auto-merge was not enabled, no action needed');
351+ } else {
352+ console.error(`❌ Failed to disable auto-merge: ${disableError.message}`);
353+ // Don't fail workflow, but log the error properly
354+ }
309355 }
310356 return;
311357 }
@@ -342,15 +388,29 @@ jobs:
342388
343389 console.log(`🚀 Enabling auto-merge with command: ${mergeCommand}`);
344390
345- execSync(mergeCommand, {
346- env: {
347- ...process.env,
348- GH_TOKEN: '${{ secrets.GH_PAT_TOKEN || secrets.GITHUB_TOKEN }}'
349- },
350- stdio: 'inherit'
351- });
391+ try {
392+ execSync(mergeCommand, {
393+ env: {
394+ ...process.env,
395+ GH_TOKEN: process.env.GITHUB_TOKEN
396+ },
397+ stdio: 'inherit'
398+ });
352399
353- console.log('✅ Auto-merge enabled! PR will merge when all status checks pass.');
400+ console.log('✅ Auto-merge enabled! PR will merge when all status checks pass.');
401+ } catch (enableError) {
402+ // Handle race condition: another workflow run may have enabled auto-merge
403+ if (enableError.message && (
404+ enableError.message.includes('already enabled') ||
405+ enableError.message.includes('auto-merge is already enabled')
406+ )) {
407+ console.log('ℹ️ Auto-merge already enabled by another workflow run');
408+ core.setOutput('action', 'already-enabled');
409+ return;
410+ }
411+ // Re-throw other errors to be caught by outer catch block
412+ throw enableError;
413+ }
354414
355415 // Add comment if configured
356416 if (process.env.COMMENT_ON_ENABLE === 'true') {
@@ -445,6 +505,12 @@ jobs:
445505 "skip-bot")
446506 ACTION_DESC="🤖 Skipped (bot PR)"
447507 ;;
508+ "skip-fork")
509+ ACTION_DESC="🍴 Skipped (fork PR - security policy)"
510+ ;;
511+ "skip-deleted-fork")
512+ ACTION_DESC="🍴 Skipped (deleted fork PR)"
513+ ;;
448514 "skip-draft")
449515 ACTION_DESC="📝 Skipped (draft PR)"
450516 ;;
@@ -477,6 +543,7 @@ jobs:
477543 SKIP_DRAFT=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_SKIP_DRAFT')
478544 SKIP_WIP=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_SKIP_WIP')
479545 SKIP_BOT_PRS=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_SKIP_BOT_PRS')
546+ SKIP_FORK_PRS=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_SKIP_FORK_PRS')
480547
481548 echo "| Setting | Value |" >> $GITHUB_STEP_SUMMARY
482549 echo "|---------|-------|" >> $GITHUB_STEP_SUMMARY
@@ -486,6 +553,7 @@ jobs:
486553 echo "| Skip draft PRs | $SKIP_DRAFT |" >> $GITHUB_STEP_SUMMARY
487554 echo "| Skip WIP PRs | $SKIP_WIP |" >> $GITHUB_STEP_SUMMARY
488555 echo "| Skip bot PRs | $SKIP_BOT_PRS |" >> $GITHUB_STEP_SUMMARY
556+ echo "| Skip fork PRs | $SKIP_FORK_PRS |" >> $GITHUB_STEP_SUMMARY
489557 echo "" >> $GITHUB_STEP_SUMMARY
490558 echo "---" >> $GITHUB_STEP_SUMMARY
491559 echo "🤖 _Automated by GitHub Actions_" >> $GITHUB_STEP_SUMMARY
@@ -509,6 +577,9 @@ jobs:
509577 disabled-changes-requested)
510578 echo "🛑 Action: Auto-merge disabled due to changes requested"
511579 ;;
580+ skip-fork)
581+ echo "🍴 Action: Skipped - Fork PR (security policy)"
582+ ;;
512583 skip-*)
513584 echo "⏭️ Action: Skipped - $ACTION"
514585 ;;
0 commit comments