Skip to content

deps(deps): Bump the "dependencies" group with 2 updates across multiple ecosystems #1613

deps(deps): Bump the "dependencies" group with 2 updates across multiple ecosystems

deps(deps): Bump the "dependencies" group with 2 updates across multiple ecosystems #1613

Workflow file for this run

# file: .github/workflows/pr-automation.yml
# version: 4.5.7
# guid: a7b8c9d0-e1f2-3456-a789-0123456789bc
# NOTE: This file should be updated in ghcommon repository first, then copied to other repositories.
# To update: Edit in https://github.com/falkcorp/github-common/.github/workflows/pr-automation.yml then copy to other repos
# ⚠️ DO NOT EDIT DIRECTLY - This file is managed in ghcommon repository
# All changes should be made in falkcorp/github-common and will be synced to other repositories
# Edit this file at: https://github.com/falkcorp/github-common/edit/main/.github/workflows/pr-automation.yml
name: PR Automation
on:
pull_request:
types: [opened, edited, synchronize, reopened, labeled, unlabeled]
pull_request_target:
types: [opened, edited, synchronize, reopened]
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true
permissions:
contents: write
pull-requests: write
issues: write
checks: write
statuses: write
security-events: write
actions: write
packages: read
id-token: write
repository-projects: write
env:
VALIDATE_ALL_CODEBASE: false
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
FILTER_REGEX_EXCLUDE: ".*\\.git/.*|.*\\.github/copilot/.*|.*\\.vscode/.*|.*node_modules/.*|.*\\.cache/.*|.*vendor/.*|.*dist/.*"
jobs:
# Primary code quality check - runs on all PRs
code-quality:
name: Code Quality Check
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: '3.13'
- name: Detect project languages (for linter toolchain setup)
id: detect_langs
run: |
go_present=false
if [ -f "go.mod" ]; then
go_present=true
fi
rust_present=false
if [ -f "Cargo.toml" ]; then
rust_present=true
fi
node_present=false
if [ -f "package.json" ] || [ -f "webui/package.json" ]; then
node_present=true
fi
{
echo "go_present=${go_present}"
echo "rust_present=${rust_present}"
echo "node_present=${node_present}"
} >> "$GITHUB_OUTPUT"
- name: Setup Go (if go.mod present)
if: steps.detect_langs.outputs.go_present == 'true'
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '1.24'
cache: true
- name: Setup Rust (if Cargo.toml present)
if: steps.detect_langs.outputs.rust_present == 'true'
uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # stable
with:
toolchain: stable
components: rustfmt, clippy
- name: Setup Node.js (if package.json present)
if: steps.detect_langs.outputs.node_present == 'true'
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '22'
cache: npm
cache-dependency-path: |
**/package-lock.json
webui/package-lock.json
- name: Load PR Auto-Fix Configuration
run: |
echo "Loading Super Linter PR automation configuration..."
# Check if PR-specific config exists, fallback to default
if [ -f "super-linter-pr.env" ]; then
echo "Using PR automation configuration: super-linter-pr.env"
cat super-linter-pr.env >> "$GITHUB_ENV"
else
echo "PR config not found, using default configuration"
{
echo "VALIDATE_ALL_CODEBASE=false"
echo "DEFAULT_BRANCH=${{ github.event.repository.default_branch }}"
echo "FILTER_REGEX_EXCLUDE=${{ env.FILTER_REGEX_EXCLUDE }}"
} >> "$GITHUB_ENV"
fi
- name: Run Super Linter with Auto-Fix
id: run-super-linter
# Advisory auto-fix pass: it applies and commits fixable issues and
# reports the rest in the job summary (via steps.run-super-linter.outcome),
# but a lint finding must not hard-fail the PR. Real linting is enforced
# separately by reusable-ci.yml. Without this the job blocked every PR.
continue-on-error: true
uses: super-linter/super-linter@4ce20838b8ab83717e78138c5b3a1407148e0918 # v8.7.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check for auto-fixes
id: check-fixes
run: |
if ! git diff --quiet; then
echo "has_fixes=true" >> "$GITHUB_OUTPUT"
echo "Auto-fixes were applied by Super Linter"
else
echo "has_fixes=false" >> "$GITHUB_OUTPUT"
echo "No auto-fixes were applied"
fi
- name: Commit and push auto-fixes
if: steps.check-fixes.outputs.has_fixes == 'true'
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
echo "Staging auto-fixes..."
git add -A
# Create detailed commit message
FIXED_FILES=$(git diff --cached --name-only | head -10)
TOTAL_FILES=$(git diff --cached --name-only | wc -l)
{
printf '%s\n' "style: auto-fix linting issues [skip ci]"
printf '%s\n' ""
printf '%s\n' "Auto-formatting and fixes applied by Super Linter."
printf '%s\n' ""
printf '%s\n' "Files changed:"
} > commit_msg.txt
echo "$FIXED_FILES" | while IFS= read -r file; do
echo "- $file - Auto-formatting applied" >> commit_msg.txt
done
if [ "$TOTAL_FILES" -gt 10 ]; then
echo "- ... and $((TOTAL_FILES - 10)) more files" >> commit_msg.txt
fi
{
echo ""
echo "Total files changed: $TOTAL_FILES"
echo ""
echo "Generated-by: Super Linter"
} >> commit_msg.txt
git commit -F commit_msg.txt
rm commit_msg.txt
echo "Pushing auto-fixes..."
git push
echo "βœ… Auto-fixes committed and pushed successfully"
- name: Create Job Summary
if: always()
run: |
{
echo "# πŸ” Super Linter Summary"
} >> "$GITHUB_STEP_SUMMARY"
if [ "${{ steps.run-super-linter.outcome }}" = "success" ]; then
echo "βœ… **All code quality checks passed!**" >> "$GITHUB_STEP_SUMMARY"
elif [ "${{ steps.run-super-linter.outcome }}" = "failure" ]; then
echo "❌ **Issues found that need attention**" >> "$GITHUB_STEP_SUMMARY"
else
echo "⚠️ **Linter status unknown** - check workflow logs" >> "$GITHUB_STEP_SUMMARY"
fi
echo "" >> "$GITHUB_STEP_SUMMARY"
# Show auto-fixes if applied
if [ "${{ steps.check-fixes.outputs.has_fixes }}" = "true" ]; then
{
echo "## πŸ”§ Auto-fixes Applied"
echo "Auto-formatting fixes were applied and committed."
echo ""
} >> "$GITHUB_STEP_SUMMARY"
fi
{
echo "## Configuration"
echo "- **Mode**: Changed files only"
echo "- **Auto-fix**: true"
echo "- **Auto-commit**: true"
} >> "$GITHUB_STEP_SUMMARY"
- name: Upload Super Linter results
if: always() && hashFiles('super-linter-output/**/*') != ''
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: super-linter-output-${{ github.run_id }}-${{ github.run_attempt }}
path: super-linter-output/
retention-days: 7
- name: Mark PR Automation Complete
if: always()
run: |
echo "PR_AUTOMATION_COMPLETE=true" >> "$GITHUB_ENV"
{
echo "# 🎯 PR Automation Complete"
echo ""
echo "βœ… **PR automation workflow has completed**"
echo ""
echo "- Code quality checks: ${{ steps.run-super-linter.outcome }}"
echo "- Auto-fixes applied: ${{ steps.check-fixes.outputs.has_fixes }}"
echo "- CI workflow can now run safely"
} >> "$GITHUB_STEP_SUMMARY"
{
echo ""
echo "_This marker allows CI workflows to detect completion of PR automation_"
} >> "$GITHUB_STEP_SUMMARY"
# Create a completion marker file for CI workflows
mkdir -p .github/workflow-markers
date -u +%Y-%m-%dT%H:%M:%SZ > ".github/workflow-markers/pr-automation-complete"
echo "PR automation completed at $(date -u +%Y-%m-%dT%H:%M:%SZ)"
# File-pattern based auto-labeling
auto-labeling:
name: Auto Label PR
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
- name: Apply file-based labels
uses: actions/labeler@bf12e9b00b37c5c0ca2b87b79b2daf7891dbda13 # v7.0.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
configuration-path: .github/labeler.yml
sync-labels: true
# Intelligent AI-powered labeling
intelligent-labeling:
name: Intelligent AI Labeling
runs-on: ubuntu-latest
if: github.event.action == 'opened' || github.event.action == 'edited'
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: '3.13'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install requests pyyaml python-dateutil scikit-learn nltk
- name: Download NLTK data
run: |
python -c "
import nltk
nltk.download('punkt')
nltk.download('stopwords')
nltk.download('vader_lexicon')
"
- name: Run intelligent labeling
uses: falkcorp/gha-pr-auto-label@329b41e704ab05c0ffc2b3581dffa249be11dea4 # v1.1.3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
pr-number: ${{ github.event.number }}
# PR size and complexity analysis
pr-analysis:
name: PR Analysis
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
fetch-depth: 0
- name: Analyze PR size and complexity
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
BASE_REF="origin/${{ github.event.repository.default_branch }}"
CHANGED_FILES=$(git diff --name-only "${BASE_REF}...HEAD" | wc -l | tr -d '[:space:]')
ADDED_LINES=$(git diff --numstat "${BASE_REF}...HEAD" | awk '{sum += $1} END {print sum}')
ADDED_LINES=${ADDED_LINES:-0}
DELETED_LINES=$(git diff --numstat "${BASE_REF}...HEAD" | awk '{sum += $2} END {print sum}')
DELETED_LINES=${DELETED_LINES:-0}
TOTAL_CHANGES=$((ADDED_LINES + DELETED_LINES))
{
echo "# πŸ“Š PR Analysis"
echo ""
echo "| Metric | Value |"
echo "|--------|-------|"
echo "| Files Changed | ${CHANGED_FILES} |"
echo "| Lines Added | ${ADDED_LINES} |"
echo "| Lines Deleted | ${DELETED_LINES} |"
echo "| Total Changes | ${TOTAL_CHANGES} |"
echo ""
} >> "$GITHUB_STEP_SUMMARY"
# Determine size label
if [ "${TOTAL_CHANGES}" -lt 10 ]; then
SIZE_LABEL="size/XS"
elif [ "${TOTAL_CHANGES}" -lt 30 ]; then
SIZE_LABEL="size/S"
elif [ "${TOTAL_CHANGES}" -lt 100 ]; then
SIZE_LABEL="size/M"
elif [ "${TOTAL_CHANGES}" -lt 500 ]; then
SIZE_LABEL="size/L"
else
SIZE_LABEL="size/XL"
fi
echo "**Size Classification**: \`${SIZE_LABEL}\`" >> "$GITHUB_STEP_SUMMARY"
curl -sS -X POST \
-H "Authorization: token ${GITHUB_TOKEN}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.number }}/labels" \
-d "{\"labels\":[\"${SIZE_LABEL}\"]}"
# Check for breaking changes
breaking-changes:
name: Breaking Changes Check
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
fetch-depth: 0
- name: Check for breaking changes
run: |
set -euo pipefail
BASE_REF="origin/${{ github.event.repository.default_branch }}"
BREAKING_COMMITS=$(git log --oneline "${BASE_REF}...HEAD" | grep -Ei 'breaking' || true)
API_CHANGES=$(git diff "${BASE_REF}...HEAD" -- '*.go' | grep -E '^-.*func.*\(' || true)
{
echo "# 🚨 Breaking Changes Analysis"
echo ""
} >> "$GITHUB_STEP_SUMMARY"
if [ -n "${BREAKING_COMMITS}${API_CHANGES}" ]; then
{
echo "⚠️ **Potential breaking changes detected.**"
if [ -n "${BREAKING_COMMITS}" ]; then
echo ""
echo "Commits referencing breaking changes:"
echo '```'
echo "${BREAKING_COMMITS}"
echo '```'
fi
if [ -n "${API_CHANGES}" ]; then
echo ""
echo "Notable API modifications detected in Go sources:"
echo '```diff'
echo "${API_CHANGES}"
echo '```'
fi
} >> "$GITHUB_STEP_SUMMARY"
curl -sS -X POST \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.number }}/labels" \
-d '{"labels":["breaking-change"]}'
else
echo "βœ… **No breaking changes detected**" >> "$GITHUB_STEP_SUMMARY"
fi
# Conflict resolution helper
conflict-resolution:
name: Conflict Resolution
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' && github.event.action == 'synchronize'
steps:
- name: Check for merge conflicts
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
PR_STATUS=$(curl -sS \
-H "Authorization: token ${GITHUB_TOKEN}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.number }}" \
| jq -r '.mergeable')
PR_STATUS=${PR_STATUS:-"unknown"}
{
echo "# πŸ”€ Merge Status"
echo ""
} >> "$GITHUB_STEP_SUMMARY"
if [ "${PR_STATUS}" = "false" ]; then
{
echo "❌ **Merge conflicts detected**"
echo ""
echo "This PR has merge conflicts that need to be resolved."
echo ""
echo "**Steps to resolve:**"
echo "1. Pull the latest changes from the base branch"
echo "2. Merge or rebase your branch"
echo "3. Resolve any conflicts"
echo "4. Push the resolved changes"
} >> "$GITHUB_STEP_SUMMARY"
curl -sS -X POST \
-H "Authorization: token ${GITHUB_TOKEN}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.number }}/labels" \
-d '{"labels":["needs-rebase"]}'
elif [ "${PR_STATUS}" = "true" ]; then
{
echo "βœ… **No merge conflicts**"
echo ""
echo "This PR can be merged cleanly."
} >> "$GITHUB_STEP_SUMMARY"
curl -sS -X DELETE \
-H "Authorization: token ${GITHUB_TOKEN}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.number }}/labels/needs-rebase" || true
else
{
echo "⏳ **Merge status unknown**"
echo ""
echo "GitHub is still calculating the merge status."
} >> "$GITHUB_STEP_SUMMARY"
fi
# PR automation summary
pr-summary:
name: PR Automation Summary
runs-on: ubuntu-latest
needs:
[
code-quality,
auto-labeling,
intelligent-labeling,
pr-analysis,
attestations,
ai-rebase,
]
if: always()
steps:
- name: Generate summary
run: |
set -euo pipefail
SUMMARY_FILE="$GITHUB_STEP_SUMMARY"
{
echo "# πŸ€– PR Automation Summary"
echo ""
if [[ "${{ needs.code-quality.result }}" == "success" ]]; then
echo "βœ… **Code Quality**: Passed"
else
echo "❌ **Code Quality**: Failed"
fi
if [[ "${{ needs.auto-labeling.result }}" == "success" ]]; then
echo "βœ… **Auto Labeling**: Applied"
else
echo "⏭️ **Auto Labeling**: Skipped"
fi
if [[ "${{ needs.intelligent-labeling.result }}" == "success" ]]; then
echo "βœ… **AI Labeling**: Applied"
else
echo "⏭️ **AI Labeling**: Skipped"
fi
if [[ "${{ needs.pr-analysis.result }}" == "success" ]]; then
echo "βœ… **PR Analysis**: Completed"
else
echo "⏭️ **PR Analysis**: Skipped"
fi
if [[ "${{ needs.attestations.result }}" == "success" ]]; then
echo "βœ… **Attestations**: Generated"
elif [[ "${{ needs.attestations.result }}" == "skipped" ]]; then
echo "⏭️ **Attestations**: Skipped"
else
echo "❌ **Attestations**: Failed"
fi
if [[ "${{ needs.ai-rebase.result }}" == "success" ]]; then
echo "βœ… **AI Rebase**: Completed"
elif [[ "${{ needs.ai-rebase.result }}" == "skipped" ]]; then
echo "⏭️ **AI Rebase**: Skipped (no conflicts)"
else
echo "❌ **AI Rebase**: Failed"
fi
echo ""
echo "**Workflow completed at**: $(date -u)"
} >> "${SUMMARY_FILE}"
# AI-powered rebase and conflict resolution
ai-rebase:
name: AI Rebase & Conflict Resolution
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' && github.event.action != 'closed'
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
- name: Check for merge conflicts
id: conflict-check
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
result-encoding: string
script: |
const pr_number = context.issue.number;
try {
let pr = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr_number,
});
// GitHub may return 'unknown' mergeable_state on first request
if (pr.data.mergeable_state === 'unknown') {
await new Promise(r => setTimeout(r, 2000));
pr = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr_number,
});
}
const state = pr.data.mergeable_state;
core.info(`PR #${pr_number} mergeable state: ${state}`);
if (state === 'dirty' || state === 'behind') {
return 'true';
} else {
return 'false';
}
} catch (error) {
core.error(`Error checking PR: ${error.message}`);
return 'false';
}
- name: Run AI rebase assistant
if: steps.conflict-check.outputs.result == 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_BASE_REF: ${{ github.event.pull_request.base.ref }}
PR_HEAD_REF: ${{ github.event.pull_request.head.ref }}
run: |
set -euo pipefail
chmod +x .github/scripts/ai-rebase.sh
.github/scripts/ai-rebase.sh \
"${PR_NUMBER}" \
"${PR_BASE_REF}" \
"${PR_HEAD_REF}"
# SBOM generation and provenance attestations (runs on PR for visibility)
attestations:
name: SBOM & Provenance Attestations
runs-on: ubuntu-latest
needs: [code-quality]
if: always()
permissions:
contents: read
id-token: write
actions: read
attestations: write
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
submodules: recursive
fetch-depth: 0
- name: Generate SBOM (Syft)
id: generate-sbom
uses: anchore/sbom-action@3ad7283483fc7af8ff2b4ea19663c2d5ca935e26 # v0.24.2
with:
output-file: sbom.spdx.json
- name: Upload SBOM artifact
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: sbom-${{ github.run_id }}-${{ github.run_attempt }}
path: sbom.spdx.json
retention-days: 7
- name: Create attestation bundle
run: |
set -euo pipefail
tar -czf pr-automation-context.tar.gz \
.github/workflows/pr-automation.yml \
sbom.spdx.json
ls -l pr-automation-context.tar.gz
- name: Attest SBOM
uses: actions/attest-sbom@c604332985a26aa8cf1bdc465b92731239ec6b9e # v4.1.0
with:
subject-path: pr-automation-context.tar.gz
sbom-path: sbom.spdx.json
- name: Build Provenance Attestation
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
with:
subject-path: pr-automation-context.tar.gz
- name: Attestation summary
if: always()
run: |
{
echo "# πŸ›‘οΈ Attestations"
echo ""
echo "Generated SBOM (sbom.spdx.json) and created provenance & SBOM attestations."
echo "Subject: pr-automation-context.tar.gz"
} >> "$GITHUB_STEP_SUMMARY"