Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions .github/.env.base
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ ENABLE_GODOCS_PUBLISHING=true # Publish to pkg.go.dev on tag/releases
ARTIFACT_DOWNLOAD_RETRIES=3 # Number of retry attempts for failed downloads
ARTIFACT_DOWNLOAD_RETRY_DELAY=10 # Initial retry delay in seconds (uses exponential backoff)
ARTIFACT_DOWNLOAD_TIMEOUT=300 # Download timeout in seconds (5 minutes)
ARTIFACT_DOWNLOAD_CONTINUE_ON_ERROR=false # Continue workflow execution even if artifact download fails
ARTIFACT_DOWNLOAD_CONTINUE_ON_ERROR=true # Continue workflow execution even if artifact download fails (required for fork PRs)

# ================================================================================================
# ⚙️ BENCHMARK & TEST CONFIGURATION
Expand Down Expand Up @@ -299,12 +299,12 @@ NANCY_VERSION=v1.0.51 # https://github.com/sonatype-nexus-commu
# ================================================================================================

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

# System Settings
GO_PRE_COMMIT_FAIL_FAST=false
GO_PRE_COMMIT_TIMEOUT_SECONDS=300
GO_PRE_COMMIT_TIMEOUT_SECONDS=720
GO_PRE_COMMIT_TOOL_INSTALL_TIMEOUT=300
GO_PRE_COMMIT_AUTO_ADJUST_CI_TIMEOUTS=true
GO_PRE_COMMIT_PARALLEL_WORKERS=2
Expand Down Expand Up @@ -347,7 +347,7 @@ GO_PRE_COMMIT_AI_DETECTION_AUTO_FIX=false
GO_PRE_COMMIT_FMT_TIMEOUT=30
GO_PRE_COMMIT_FUMPT_TIMEOUT=30
GO_PRE_COMMIT_GOIMPORTS_TIMEOUT=30
GO_PRE_COMMIT_LINT_TIMEOUT=60
GO_PRE_COMMIT_LINT_TIMEOUT=600
GO_PRE_COMMIT_MOD_TIDY_TIMEOUT=60
GO_PRE_COMMIT_WHITESPACE_TIMEOUT=30
GO_PRE_COMMIT_EOF_TIMEOUT=30
Expand Down Expand Up @@ -409,6 +409,10 @@ AUTO_MERGE_COMMENT_ON_ENABLE=true
AUTO_MERGE_COMMENT_ON_DISABLE=true
AUTO_MERGE_LABELS_TO_ADD=automerge-enabled
AUTO_MERGE_SKIP_BOT_PRS=true
AUTO_MERGE_SKIP_FORK_PRS=true
# Note: Fork PRs receive welcome comments from pull-request-management-fork.yml instead
# This setting only affects same-repo PRs (fork PRs use read-only GITHUB_TOKEN)
AUTO_MERGE_COMMENT_ON_FORK_SKIP=true

# ================================================================================================
# 📝 PULL REQUEST MANAGEMENT CONFIGURATION
Expand Down
50 changes: 50 additions & 0 deletions .github/actions/load-env/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,50 @@ runs:
fi
}
# Function to validate environment variable names and values
validate_env_vars() {
local json="$1"
local source="$2"
echo "🔒 Validating environment variables from $source..."
# Extract all keys and values
local keys=$(echo "$json" | jq -r 'keys[]')
while IFS= read -r key; do
# Skip empty keys
[[ -z "$key" ]] && continue
# Validate key name: must match ^[A-Z_][A-Z0-9_]*$
if ! echo "$key" | grep -qE '^[A-Z_][A-Z0-9_]*$'; then
echo "❌ ERROR: Invalid environment variable name in $source: '$key'" >&2
echo " Variable names must start with uppercase letter or underscore" >&2
echo " and contain only uppercase letters, numbers, and underscores" >&2
exit 1
fi
# Get the value for this key
local value=$(echo "$json" | jq -r --arg k "$key" '.[$k]')
# Validate value length (max 10000 chars to prevent DoS)
if [[ ${#value} -gt 10000 ]]; then
echo "❌ ERROR: Environment variable value too long in $source: '$key'" >&2
echo " Maximum length is 10000 characters, got ${#value}" >&2
exit 1
fi
# Check for suspicious command injection patterns
if echo "$value" | grep -qE '`|\$\(|\$\{|;|&|\||<\(|>|<|\\|'"'"'|"|\x00|[[:cntrl:]]'; then
echo "⚠️ WARNING: Potentially unsafe characters in $source variable '$key'" >&2
echo " Value contains backticks, command substitution, or shell metacharacters" >&2
echo " Value will be treated as a literal string during extraction" >&2
fi
done <<< "$keys"
echo "✅ All variables in $source passed validation"
}
# Load configuration files in order of precedence
BASE_JSON="{}"
CUSTOM_JSON="{}"
Expand All @@ -83,6 +127,9 @@ runs:
BASE_JSON=$(parse_env_file ".github/.env.base")
BASE_COUNT=$(echo "$BASE_JSON" | jq 'keys | length')
echo "✅ Loaded $BASE_COUNT base configuration variables"
# Validate base configuration
validate_env_vars "$BASE_JSON" ".env.base"
else
echo "❌ ERROR: Required .env.base file not found!" >&2
exit 1
Expand All @@ -94,6 +141,9 @@ runs:
CUSTOM_JSON=$(parse_env_file ".github/.env.custom")
CUSTOM_COUNT=$(echo "$CUSTOM_JSON" | jq 'keys | length')
echo "✅ Loaded $CUSTOM_COUNT custom override variables"
# Validate custom configuration
validate_env_vars "$CUSTOM_JSON" ".env.custom"
else
echo "ℹ️ No custom configuration file found (this is optional)"
fi
Expand Down
3 changes: 3 additions & 0 deletions .github/labels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
- name: "feature"
description: "Any new significant addition"
color: 0e8a16
- name: "fork-pr"
description: "PR originated from a forked repository"
color: 5319e7
- name: "github-actions"
description: "Used for referencing GitHub Actions"
color: 006b75
Expand Down
107 changes: 89 additions & 18 deletions .github/workflows/auto-merge-on-approval.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ jobs:
id: config
env:
ENV_JSON: ${{ needs.load-env.outputs.env-json }}
GH_PAT_TOKEN: ${{ secrets.GH_PAT_TOKEN }}
run: |
echo "📋 Extracting auto-merge configuration from environment..."
Expand All @@ -116,6 +115,8 @@ jobs:
COMMENT_ON_DISABLE=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_COMMENT_ON_DISABLE')
LABELS_TO_ADD=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_LABELS_TO_ADD')
SKIP_BOT_PRS=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_SKIP_BOT_PRS')
SKIP_FORK_PRS=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_SKIP_FORK_PRS')
COMMENT_ON_FORK_SKIP=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_COMMENT_ON_FORK_SKIP')
PREFERRED_TOKEN=$(echo "$ENV_JSON" | jq -r '.PREFERRED_GITHUB_TOKEN')
# Validate required configuration
Expand All @@ -135,6 +136,8 @@ jobs:
echo "COMMENT_ON_DISABLE=$COMMENT_ON_DISABLE" >> $GITHUB_ENV
echo "LABELS_TO_ADD=$LABELS_TO_ADD" >> $GITHUB_ENV
echo "SKIP_BOT_PRS=$SKIP_BOT_PRS" >> $GITHUB_ENV
echo "SKIP_FORK_PRS=$SKIP_FORK_PRS" >> $GITHUB_ENV
echo "COMMENT_ON_FORK_SKIP=$COMMENT_ON_FORK_SKIP" >> $GITHUB_ENV
# Determine default merge type
DEFAULT_MERGE_TYPE=$(echo "$MERGE_TYPES" | cut -d',' -f1)
Expand All @@ -156,12 +159,9 @@ jobs:
echo " 💬 Comment on disable: $COMMENT_ON_DISABLE"
echo " 🏷️ Labels to add: $LABELS_TO_ADD"
echo " 🤖 Skip bot PRs: $SKIP_BOT_PRS"
if [[ "$PREFERRED_TOKEN" == "GH_PAT_TOKEN" && -n "$GH_PAT_TOKEN" ]]; then
echo " 🔑 Token: Personal Access Token (PAT)"
else
echo " 🔑 Token: Default GITHUB_TOKEN"
fi
echo " 🍴 Skip fork PRs: $SKIP_FORK_PRS"
echo " 💬 Comment on fork skip: $COMMENT_ON_FORK_SKIP"
echo " 🔑 Token: Selected via github-script action"
# --------------------------------------------------------------------
# Process the PR for auto-merge
Expand Down Expand Up @@ -198,6 +198,43 @@ jobs:
return;
}
// ————————————————————————————————————————————————————————————————
// Check if we should skip fork PRs
// ————————————————————————————————————————————————————————————————
// Handle edge case: fork repository deleted/inaccessible (pr.head.repo is null)
if (!pr.head.repo) {
console.log('⚠️ PR head repository is null (fork may have been deleted)');
if (process.env.SKIP_FORK_PRS === 'true') {
console.log('🍴 Skipping PR with deleted fork source (security policy)');
core.setOutput('action', 'skip-deleted-fork');
return;
}
// If not skipping forks, log and continue (will be treated as same-repo PR)
console.log('⚠️ Continuing with auto-merge processing (null repo treated as same-repo)');
} else {
// Safe to access pr.head.repo.full_name now
const headRepoFullName = pr.head.repo.full_name;
const baseRepoFullName = `${owner}/${repo}`;
const isForkPR = headRepoFullName !== baseRepoFullName;
if (isForkPR && process.env.SKIP_FORK_PRS === 'true') {
console.log('🍴 Skipping fork PR (security policy: fork PRs are not auto-merged)');
console.log(` Fork source: ${headRepoFullName}`);
console.log(` Base repository: ${baseRepoFullName}`);
console.log(' Security reason: Fork PRs require manual maintainer review before merge');
// Note: Comments are not posted to fork PRs due to read-only GITHUB_TOKEN permissions
// Fork PR handling is already managed by pull-request-management-fork.yml workflow
if (process.env.COMMENT_ON_FORK_SKIP === 'true') {
console.log(' ℹ️ Comment posting skipped for fork PR (handled by fork PR workflow)');
}
core.setOutput('action', 'skip-fork');
return;
}
}
// ————————————————————————————————————————————————————————————————
// Check basic PR conditions
// ————————————————————————————————————————————————————————————————
Expand Down Expand Up @@ -287,7 +324,7 @@ jobs:
execSync(`gh pr merge --disable-auto "${pr.html_url}"`, {
env: {
...process.env,
GH_TOKEN: '${{ secrets.GH_PAT_TOKEN || secrets.GITHUB_TOKEN }}'
GH_TOKEN: process.env.GITHUB_TOKEN
},
stdio: 'inherit'
});
Expand All @@ -304,8 +341,17 @@ jobs:
}
core.setOutput('action', 'disabled-changes-requested');
} catch (error) {
console.log('ℹ️ Could not disable auto-merge (may not have been enabled)');
} catch (disableError) {
// Differentiate between "not enabled" and actual failures
if (disableError.message && (
disableError.message.includes('not enabled') ||
disableError.message.includes('auto-merge is not enabled')
)) {
console.log('ℹ️ Auto-merge was not enabled, no action needed');
} else {
console.error(`❌ Failed to disable auto-merge: ${disableError.message}`);
// Don't fail workflow, but log the error properly
}
}
return;
}
Expand Down Expand Up @@ -342,15 +388,29 @@ jobs:
console.log(`🚀 Enabling auto-merge with command: ${mergeCommand}`);
execSync(mergeCommand, {
env: {
...process.env,
GH_TOKEN: '${{ secrets.GH_PAT_TOKEN || secrets.GITHUB_TOKEN }}'
},
stdio: 'inherit'
});
try {
execSync(mergeCommand, {
env: {
...process.env,
GH_TOKEN: process.env.GITHUB_TOKEN
},
Comment on lines +391 to +396

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Auto-merge command ignores configured PAT token

The auto‑merge job now runs gh pr merge with GH_TOKEN set to process.env.GITHUB_TOKEN and no longer injects secrets.GH_PAT_TOKEN. Repositories that relied on the PAT (e.g., to provide contents: write or use a maintainer identity) will now attempt to enable/disable auto‑merge with the default Actions token, which lacks those privileges and will return Resource not accessible by integration. The secret is still configured and the github-script step uses it, but the actual merge command cannot access it, so auto‑merge will silently stop working wherever the PAT was required.

Useful? React with 👍 / 👎.

stdio: 'inherit'
});
console.log('✅ Auto-merge enabled! PR will merge when all status checks pass.');
console.log('✅ Auto-merge enabled! PR will merge when all status checks pass.');
} catch (enableError) {
// Handle race condition: another workflow run may have enabled auto-merge
if (enableError.message && (
enableError.message.includes('already enabled') ||
enableError.message.includes('auto-merge is already enabled')
)) {
console.log('ℹ️ Auto-merge already enabled by another workflow run');
core.setOutput('action', 'already-enabled');
return;
}
// Re-throw other errors to be caught by outer catch block
throw enableError;
}
// Add comment if configured
if (process.env.COMMENT_ON_ENABLE === 'true') {
Expand Down Expand Up @@ -445,6 +505,12 @@ jobs:
"skip-bot")
ACTION_DESC="🤖 Skipped (bot PR)"
;;
"skip-fork")
ACTION_DESC="🍴 Skipped (fork PR - security policy)"
;;
"skip-deleted-fork")
ACTION_DESC="🍴 Skipped (deleted fork PR)"
;;
"skip-draft")
ACTION_DESC="📝 Skipped (draft PR)"
;;
Expand Down Expand Up @@ -477,6 +543,7 @@ jobs:
SKIP_DRAFT=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_SKIP_DRAFT')
SKIP_WIP=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_SKIP_WIP')
SKIP_BOT_PRS=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_SKIP_BOT_PRS')
SKIP_FORK_PRS=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_SKIP_FORK_PRS')
echo "| Setting | Value |" >> $GITHUB_STEP_SUMMARY
echo "|---------|-------|" >> $GITHUB_STEP_SUMMARY
Expand All @@ -486,6 +553,7 @@ jobs:
echo "| Skip draft PRs | $SKIP_DRAFT |" >> $GITHUB_STEP_SUMMARY
echo "| Skip WIP PRs | $SKIP_WIP |" >> $GITHUB_STEP_SUMMARY
echo "| Skip bot PRs | $SKIP_BOT_PRS |" >> $GITHUB_STEP_SUMMARY
echo "| Skip fork PRs | $SKIP_FORK_PRS |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "---" >> $GITHUB_STEP_SUMMARY
echo "🤖 _Automated by GitHub Actions_" >> $GITHUB_STEP_SUMMARY
Expand All @@ -509,6 +577,9 @@ jobs:
disabled-changes-requested)
echo "🛑 Action: Auto-merge disabled due to changes requested"
;;
skip-fork)
echo "🍴 Action: Skipped - Fork PR (security policy)"
;;
skip-*)
echo "⏭️ Action: Skipped - $ACTION"
;;
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:

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

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

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@5fe9434cd24fe243e33e7f3305f8a5b519b70280 # v4.31.1
uses: github/codeql-action/analyze@0499de31b99561a6d14a36a5f662c2a54f91beee # v4.31.2
37 changes: 36 additions & 1 deletion .github/workflows/fortress-completion-finalize.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ jobs:
echo "| **Workflow** | ${{ github.workflow }} |"
echo "| **Run Number** | ${{ github.run_number }} |"
echo "| **Trigger** | ${{ github.event_name }} |"
echo "| **Source** | ${{ github.event.pull_request.head.repo.full_name == github.repository && 'Internal' || 'Fork' }} |"
echo "| **Source** | ${{ github.event.pull_request.head.repo && github.event.pull_request.head.repo.full_name == github.repository && 'Internal' || 'Fork' }} |"
echo ""
echo "<br><br>"
} > final-report.md
Expand Down Expand Up @@ -204,6 +204,41 @@ jobs:

echo "" >> final-report.md

# Add fork PR specific information if this is a fork PR
if [[ "${{ env.INPUT_is-fork-pr }}" == "true" ]]; then
{
echo ""
echo "## 🔐 Fork PR Security Status"
echo ""
echo "⚠️ **This workflow ran on a FORK Pull Request**"
echo ""
echo "**Security Mode:** \`${{ env.INPUT_fork-security-mode }}\`"
echo ""
echo "### Jobs Status for Fork PR"
echo "**✅ Jobs That Ran Successfully:**"
echo "- Setup & Configuration"
echo "- MAGE-X Testing"
echo "- Code Quality Checks"
echo "- Pre-Commit System"
echo "- $([ "${{ env.INPUT_benchmarks-result }}" != "skipped" ] && echo "Benchmarks" || echo "_(Benchmarks were skipped)_")"
echo ""
echo "**⛔ Jobs Skipped for Security:**"
echo "- **Security Scans** - Requires secrets (\`OSSI_TOKEN\`, \`OSSI_USERNAME\`, \`GITLEAKS_LICENSE\`)"
echo "- **Test Suite** - Requires \`CODECOV_TOKEN\` for coverage uploads"
echo "- **Release** - PRs cannot trigger releases (tags only)"
echo ""
echo "### Why Were Jobs Skipped?"
echo "Fork PRs have restricted access to repository secrets for security:"
echo "- ✅ Prevents credential theft from malicious fork PRs"
echo "- ✅ Protects external service tokens (OSSI, Codecov)"
echo "- ✅ Prevents unauthorized access through workflow modifications"
echo ""
echo "**Note for Fork Contributors:**"
echo "Repository maintainers will review your PR and can manually run security scans if needed."
echo "All code quality checks and tests that don't require secrets have already run successfully!"
} >> final-report.md
fi

# Add release-specific information if this was a tag push
if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
{
Expand Down
Loading