Skip to content

Commit 00cc464

Browse files
authored
sync: update 16 files from source repository (#54)
1 parent e682ad4 commit 00cc464

16 files changed

+1086
-76
lines changed

.github/.env.base

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ ENABLE_GODOCS_PUBLISHING=true # Publish to pkg.go.dev on tag/releases
106106
ARTIFACT_DOWNLOAD_RETRIES=3 # Number of retry attempts for failed downloads
107107
ARTIFACT_DOWNLOAD_RETRY_DELAY=10 # Initial retry delay in seconds (uses exponential backoff)
108108
ARTIFACT_DOWNLOAD_TIMEOUT=300 # Download timeout in seconds (5 minutes)
109-
ARTIFACT_DOWNLOAD_CONTINUE_ON_ERROR=false # Continue workflow execution even if artifact download fails
109+
ARTIFACT_DOWNLOAD_CONTINUE_ON_ERROR=true # Continue workflow execution even if artifact download fails (required for fork PRs)
110110

111111
# ================================================================================================
112112
# ⚙️ BENCHMARK & TEST CONFIGURATION
@@ -299,12 +299,12 @@ NANCY_VERSION=v1.0.51 # https://github.com/sonatype-nexus-commu
299299
# ================================================================================================
300300

301301
# Pre-Commit System
302-
GO_PRE_COMMIT_VERSION=v1.3.4 # https://github.com/mrz1836/go-pre-commit
302+
GO_PRE_COMMIT_VERSION=v1.3.5 # https://github.com/mrz1836/go-pre-commit
303303
GO_PRE_COMMIT_USE_LOCAL=false # Use local version for development
304304

305305
# System Settings
306306
GO_PRE_COMMIT_FAIL_FAST=false
307-
GO_PRE_COMMIT_TIMEOUT_SECONDS=300
307+
GO_PRE_COMMIT_TIMEOUT_SECONDS=720
308308
GO_PRE_COMMIT_TOOL_INSTALL_TIMEOUT=300
309309
GO_PRE_COMMIT_AUTO_ADJUST_CI_TIMEOUTS=true
310310
GO_PRE_COMMIT_PARALLEL_WORKERS=2
@@ -347,7 +347,7 @@ GO_PRE_COMMIT_AI_DETECTION_AUTO_FIX=false
347347
GO_PRE_COMMIT_FMT_TIMEOUT=30
348348
GO_PRE_COMMIT_FUMPT_TIMEOUT=30
349349
GO_PRE_COMMIT_GOIMPORTS_TIMEOUT=30
350-
GO_PRE_COMMIT_LINT_TIMEOUT=60
350+
GO_PRE_COMMIT_LINT_TIMEOUT=600
351351
GO_PRE_COMMIT_MOD_TIDY_TIMEOUT=60
352352
GO_PRE_COMMIT_WHITESPACE_TIMEOUT=30
353353
GO_PRE_COMMIT_EOF_TIMEOUT=30
@@ -409,6 +409,10 @@ AUTO_MERGE_COMMENT_ON_ENABLE=true
409409
AUTO_MERGE_COMMENT_ON_DISABLE=true
410410
AUTO_MERGE_LABELS_TO_ADD=automerge-enabled
411411
AUTO_MERGE_SKIP_BOT_PRS=true
412+
AUTO_MERGE_SKIP_FORK_PRS=true
413+
# Note: Fork PRs receive welcome comments from pull-request-management-fork.yml instead
414+
# This setting only affects same-repo PRs (fork PRs use read-only GITHUB_TOKEN)
415+
AUTO_MERGE_COMMENT_ON_FORK_SKIP=true
412416

413417
# ================================================================================================
414418
# 📝 PULL REQUEST MANAGEMENT CONFIGURATION

.github/actions/load-env/action.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,50 @@ runs:
7373
fi
7474
}
7575
76+
# Function to validate environment variable names and values
77+
validate_env_vars() {
78+
local json="$1"
79+
local source="$2"
80+
81+
echo "🔒 Validating environment variables from $source..."
82+
83+
# Extract all keys and values
84+
local keys=$(echo "$json" | jq -r 'keys[]')
85+
86+
while IFS= read -r key; do
87+
# Skip empty keys
88+
[[ -z "$key" ]] && continue
89+
90+
# Validate key name: must match ^[A-Z_][A-Z0-9_]*$
91+
if ! echo "$key" | grep -qE '^[A-Z_][A-Z0-9_]*$'; then
92+
echo "❌ ERROR: Invalid environment variable name in $source: '$key'" >&2
93+
echo " Variable names must start with uppercase letter or underscore" >&2
94+
echo " and contain only uppercase letters, numbers, and underscores" >&2
95+
exit 1
96+
fi
97+
98+
# Get the value for this key
99+
local value=$(echo "$json" | jq -r --arg k "$key" '.[$k]')
100+
101+
# Validate value length (max 10000 chars to prevent DoS)
102+
if [[ ${#value} -gt 10000 ]]; then
103+
echo "❌ ERROR: Environment variable value too long in $source: '$key'" >&2
104+
echo " Maximum length is 10000 characters, got ${#value}" >&2
105+
exit 1
106+
fi
107+
108+
# Check for suspicious command injection patterns
109+
if echo "$value" | grep -qE '`|\$\(|\$\{|;|&|\||<\(|>|<|\\|'"'"'|"|\x00|[[:cntrl:]]'; then
110+
echo "⚠️ WARNING: Potentially unsafe characters in $source variable '$key'" >&2
111+
echo " Value contains backticks, command substitution, or shell metacharacters" >&2
112+
echo " Value will be treated as a literal string during extraction" >&2
113+
fi
114+
115+
done <<< "$keys"
116+
117+
echo "✅ All variables in $source passed validation"
118+
}
119+
76120
# Load configuration files in order of precedence
77121
BASE_JSON="{}"
78122
CUSTOM_JSON="{}"
@@ -83,6 +127,9 @@ runs:
83127
BASE_JSON=$(parse_env_file ".github/.env.base")
84128
BASE_COUNT=$(echo "$BASE_JSON" | jq 'keys | length')
85129
echo "✅ Loaded $BASE_COUNT base configuration variables"
130+
131+
# Validate base configuration
132+
validate_env_vars "$BASE_JSON" ".env.base"
86133
else
87134
echo "❌ ERROR: Required .env.base file not found!" >&2
88135
exit 1
@@ -94,6 +141,9 @@ runs:
94141
CUSTOM_JSON=$(parse_env_file ".github/.env.custom")
95142
CUSTOM_COUNT=$(echo "$CUSTOM_JSON" | jq 'keys | length')
96143
echo "✅ Loaded $CUSTOM_COUNT custom override variables"
144+
145+
# Validate custom configuration
146+
validate_env_vars "$CUSTOM_JSON" ".env.custom"
97147
else
98148
echo "ℹ️ No custom configuration file found (this is optional)"
99149
fi

.github/labels.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
4343
- name: "feature"
4444
description: "Any new significant addition"
4545
color: 0e8a16
46+
- name: "fork-pr"
47+
description: "PR originated from a forked repository"
48+
color: 5319e7
4649
- name: "github-actions"
4750
description: "Used for referencing GitHub Actions"
4851
color: 006b75

.github/workflows/auto-merge-on-approval.yml

Lines changed: 89 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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
;;

.github/workflows/codeql-analysis.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ jobs:
4747

4848
# Initializes the CodeQL tools for scanning.
4949
- name: Initialize CodeQL
50-
uses: github/codeql-action/init@5fe9434cd24fe243e33e7f3305f8a5b519b70280 # v4.31.1
50+
uses: github/codeql-action/init@0499de31b99561a6d14a36a5f662c2a54f91beee # v4.31.2
5151
with:
5252
languages: ${{ matrix.language }}
5353
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -58,7 +58,7 @@ jobs:
5858
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
5959
# If this step fails, then you should remove it and run the build manually (see below)
6060
- name: Autobuild
61-
uses: github/codeql-action/autobuild@5fe9434cd24fe243e33e7f3305f8a5b519b70280 # v4.31.1
61+
uses: github/codeql-action/autobuild@0499de31b99561a6d14a36a5f662c2a54f91beee # v4.31.2
6262

6363
# ℹ️ Command-line programs to run using the OS shell.
6464
# 📚 https://git.io/JvXDl
@@ -68,4 +68,4 @@ jobs:
6868
# uses a compiled language
6969

7070
- name: Perform CodeQL Analysis
71-
uses: github/codeql-action/analyze@5fe9434cd24fe243e33e7f3305f8a5b519b70280 # v4.31.1
71+
uses: github/codeql-action/analyze@0499de31b99561a6d14a36a5f662c2a54f91beee # v4.31.2

.github/workflows/fortress-completion-finalize.yml

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ jobs:
134134
echo "| **Workflow** | ${{ github.workflow }} |"
135135
echo "| **Run Number** | ${{ github.run_number }} |"
136136
echo "| **Trigger** | ${{ github.event_name }} |"
137-
echo "| **Source** | ${{ github.event.pull_request.head.repo.full_name == github.repository && 'Internal' || 'Fork' }} |"
137+
echo "| **Source** | ${{ github.event.pull_request.head.repo && github.event.pull_request.head.repo.full_name == github.repository && 'Internal' || 'Fork' }} |"
138138
echo ""
139139
echo "<br><br>"
140140
} > final-report.md
@@ -204,6 +204,41 @@ jobs:
204204
205205
echo "" >> final-report.md
206206
207+
# Add fork PR specific information if this is a fork PR
208+
if [[ "${{ env.INPUT_is-fork-pr }}" == "true" ]]; then
209+
{
210+
echo ""
211+
echo "## 🔐 Fork PR Security Status"
212+
echo ""
213+
echo "⚠️ **This workflow ran on a FORK Pull Request**"
214+
echo ""
215+
echo "**Security Mode:** \`${{ env.INPUT_fork-security-mode }}\`"
216+
echo ""
217+
echo "### Jobs Status for Fork PR"
218+
echo "**✅ Jobs That Ran Successfully:**"
219+
echo "- Setup & Configuration"
220+
echo "- MAGE-X Testing"
221+
echo "- Code Quality Checks"
222+
echo "- Pre-Commit System"
223+
echo "- $([ "${{ env.INPUT_benchmarks-result }}" != "skipped" ] && echo "Benchmarks" || echo "_(Benchmarks were skipped)_")"
224+
echo ""
225+
echo "**⛔ Jobs Skipped for Security:**"
226+
echo "- **Security Scans** - Requires secrets (\`OSSI_TOKEN\`, \`OSSI_USERNAME\`, \`GITLEAKS_LICENSE\`)"
227+
echo "- **Test Suite** - Requires \`CODECOV_TOKEN\` for coverage uploads"
228+
echo "- **Release** - PRs cannot trigger releases (tags only)"
229+
echo ""
230+
echo "### Why Were Jobs Skipped?"
231+
echo "Fork PRs have restricted access to repository secrets for security:"
232+
echo "- ✅ Prevents credential theft from malicious fork PRs"
233+
echo "- ✅ Protects external service tokens (OSSI, Codecov)"
234+
echo "- ✅ Prevents unauthorized access through workflow modifications"
235+
echo ""
236+
echo "**Note for Fork Contributors:**"
237+
echo "Repository maintainers will review your PR and can manually run security scans if needed."
238+
echo "All code quality checks and tests that don't require secrets have already run successfully!"
239+
} >> final-report.md
240+
fi
241+
207242
# Add release-specific information if this was a tag push
208243
if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
209244
{

0 commit comments

Comments
 (0)