Dependency Updates #2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Dependency Updates | |
| on: | |
| schedule: | |
| # Check for dependency updates weekly on Tuesday at 3 AM UTC (different from security scan) | |
| - cron: '0 3 * * 2' | |
| workflow_dispatch: # Allow manual trigger | |
| inputs: | |
| update_type: | |
| description: 'Type of dependency update' | |
| required: false | |
| default: 'all' | |
| type: choice | |
| options: | |
| - all | |
| - patch | |
| - minor | |
| - major | |
| - security | |
| include_indirect: | |
| description: 'Include indirect dependencies' | |
| required: false | |
| type: boolean | |
| default: true | |
| create_pr: | |
| description: 'Create pull request for updates' | |
| required: false | |
| type: boolean | |
| default: true | |
| env: | |
| GO_VERSION: '1.24' | |
| jobs: | |
| check-dependencies: | |
| name: Check for Dependency Updates | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| outputs: | |
| updates_available: ${{ steps.check-updates.outputs.updates_available }} | |
| security_updates: ${{ steps.check-security.outputs.security_updates }} | |
| outdated_count: ${{ steps.check-updates.outputs.outdated_count }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| cache: true | |
| - name: Cache go modules | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-go-deps-${{ hashFiles('**/go.sum') }} | |
| restore-keys: | | |
| ${{ runner.os }}-go-deps- | |
| - name: Download dependencies | |
| run: go mod download | |
| - name: Install dependency update tools | |
| run: | | |
| # Install go-mod-upgrade with proper error handling | |
| if ! go install github.com/chainguard-dev/go-mod-upgrade@latest 2>/dev/null; then | |
| echo "Failed to install chainguard-dev/go-mod-upgrade, trying alternative..." | |
| # Try the oligot version as fallback (already installed below) | |
| go install github.com/oligot/go-mod-upgrade@latest | |
| fi | |
| go install github.com/oligot/go-mod-upgrade@latest | |
| go install golang.org/x/vuln/cmd/govulncheck@latest | |
| - name: Check for outdated dependencies | |
| id: check-updates | |
| run: | | |
| echo "Checking for outdated dependencies..." | |
| # Get list of outdated modules | |
| go list -u -m -json all | jq -r '. | select(.Update != null) | "\(.Path) \(.Version) \(.Update.Version)"' > outdated.txt | |
| echo "Found outdated dependencies:" | |
| cat outdated.txt | |
| COUNT=$(wc -l < outdated.txt) | |
| echo "outdated_count=$COUNT" >> $GITHUB_OUTPUT | |
| if [ "$COUNT" -gt 0 ]; then | |
| echo "updates_available=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "updates_available=false" >> $GITHUB_OUTPUT | |
| fi | |
| # Create detailed dependency report | |
| cat > dependency-report.txt << 'EOF' | |
| # Dependency Update Report | |
| Generated on: $(date) | |
| Repository: ${{ github.repository }} | |
| Commit: ${{ github.sha }} | |
| EOF | |
| echo -e "\n## Outdated Dependencies\n" >> dependency-report.txt | |
| echo "| Module | Current | Latest | Type |" >> dependency-report.txt | |
| echo "|--------|---------|--------|------|" >> dependency-report.txt | |
| while read -r module current latest; do | |
| # Determine update type | |
| update_type="patch" | |
| if [[ "$current" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] && [[ "$latest" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| current_major=$(echo "$current" | cut -d. -f1) | |
| current_minor=$(echo "$current" | cut -d. -f2) | |
| latest_major=$(echo "$latest" | cut -d. -f1) | |
| latest_minor=$(echo "$latest" | cut -d. -f2) | |
| if [ "$current_major" != "$latest_major" ]; then | |
| update_type="major" | |
| elif [ "$current_minor" != "$latest_minor" ]; then | |
| update_type="minor" | |
| fi | |
| fi | |
| echo "| $module | $current | $latest | $update_type |" >> dependency-report.txt | |
| done < outdated.txt | |
| - name: Check for security vulnerabilities | |
| id: check-security | |
| run: | | |
| echo "Checking for security vulnerabilities..." | |
| # Run vulnerability scanner | |
| govulncheck -json ./... > vuln-report.json 2>/dev/null || echo "No vulnerabilities found or vulncheck failed" | |
| # Extract security vulnerabilities | |
| if [ -f "vuln-report.json" ] && [ -s "vuln-report.json" ]; then | |
| VULNS=$(jq -r '.ID // empty' vuln-report.json | wc -l) | |
| echo "Found $VULNS potential security vulnerabilities" | |
| if [ "$VULNS" -gt 0 ]; then | |
| echo "security_updates=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "security_updates=false" >> $GITHUB_OUTPUT | |
| fi | |
| echo -e "\n## Security Vulnerabilities\n" >> dependency-report.txt | |
| jq -r '"| \(.ID) | \(.details.Pkg // .pkg) | \(.details.CurrentVersion // "unknown") | \(.details.FixedVersion // "unknown") |"' vuln-report.json >> dependency-report.txt || echo "No vulnerabilities details available" | |
| else | |
| echo "No security vulnerabilities found" | |
| echo "security_updates=false" >> $GITHUB_OUTPUT | |
| echo -e "\n## Security Vulnerabilities\nNo security vulnerabilities found." >> dependency-report.txt | |
| fi | |
| - name: Upload dependency report | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: dependency-report-${{ github.run_number }} | |
| path: | | |
| dependency-report.txt | |
| outdated.txt | |
| vuln-report.json | |
| retention-days: 30 | |
| update-dependencies: | |
| name: Update Dependencies | |
| runs-on: ubuntu-latest | |
| needs: check-dependencies | |
| if: needs.check-dependencies.outputs.updates_available == 'true' | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| cache: true | |
| - name: Cache go modules | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-go-deps-${{ hashFiles('**/go.sum') }} | |
| - name: Download dependencies | |
| run: go mod download | |
| - name: Configure Git | |
| run: | | |
| git config --local user.email "[email protected]" | |
| git config --local user.name "GitHub Actions" | |
| - name: Create update branch | |
| run: | | |
| BRANCH_NAME="deps/$(date +'%Y-%m-%d')-update-${{ github.run_number }}" | |
| echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV | |
| git checkout -b "$BRANCH_NAME" | |
| - name: Apply dependency updates | |
| id: updates | |
| run: | | |
| echo "Applying dependency updates..." | |
| # Update based on input type | |
| case "${{ github.event.inputs.update_type || 'all' }}" in | |
| "patch") | |
| go get -u=patch ./... | |
| ;; | |
| "minor") | |
| go get -u=patch ./... | |
| go get -u=minor ./... | |
| ;; | |
| "major") | |
| go get -u ./... | |
| ;; | |
| "security") | |
| # Focus on security updates only | |
| go install github.com/oligot/go-mod-upgrade@latest | |
| go-mod-upgrade -v | |
| ;; | |
| *) | |
| go get -u ./... | |
| ;; | |
| esac | |
| # Include indirect dependencies if requested | |
| if [ "${{ github.event.inputs.include_indirect || 'true' }}" = "true" ]; then | |
| go get -u=patch ./... | |
| fi | |
| # Tidy up | |
| go mod tidy | |
| # Check if anything changed | |
| if git diff --quiet go.mod go.sum; then | |
| echo "No dependency changes after update" | |
| echo "changes=false" >> $GITHUB_OUTPUT | |
| else | |
| echo "Dependencies updated" | |
| echo "changes=true" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Run tests after update | |
| if: steps.updates.outputs.changes == 'true' | |
| run: | | |
| echo "Running tests with updated dependencies..." | |
| # Quick test to ensure updates don't break anything | |
| go test -v ./... || { | |
| echo "Tests failed after dependency update" | |
| echo::warning::Dependency updates broke tests, creating PR anyway for manual review" | |
| } | |
| - name: Commit and push changes | |
| if: steps.updates.outputs.changes == 'true' && (github.event.inputs.create_pr != 'false') | |
| run: | | |
| git add go.mod go.sum | |
| # Create commit based on what was updated | |
| if [ "${{ needs.check-dependencies.outputs.security_updates }}" = "true" ]; then | |
| COMMIT_MSG="chore: update dependencies (including security fixes)" | |
| else | |
| COMMIT_MSG="chore: update Go dependencies ($(date +'%Y-%m-%d'))" | |
| fi | |
| git commit -m "$COMMIT_MSG | |
| This PR updates Go modules to their latest versions. | |
| **Updated Dependencies:** | |
| $(cat outdated.txt | awk '{printf "- %s: %s → %s\n", $1, $2, $3}') | |
| **Security Updates:** | |
| $(if [ -f "vuln-report.json" ] && [ -s "vuln-report.json" ]; then jq -r '.ID' vuln-report.json | sed 's/^/- /'; else echo "None"; fi) | |
| ⚠️ **Manual Review Required**: Please review the changes and ensure all tests pass before merging. | |
| 🤖 Generated with [Claude Code](https://claude.com/claude-code) | |
| Co-Authored-By: GitHub Actions <[email protected]>" | |
| git push origin "$BRANCH_NAME" | |
| - name: Create pull request | |
| if: steps.updates.outputs.changes == 'true' && (github.event.inputs.create_pr != 'false') | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| PR_TITLE="chore: update Go dependencies ($(date +'%Y-%m-%d'))" | |
| PR_BODY="## 📦 Dependency Update | |
| This PR updates Go modules to their latest versions. | |
| **Summary:** | |
| - 📋 Outdated dependencies found: ${{ needs.check-dependencies.outputs.outdated_count }} | |
| - 🔒 Security updates available: ${{ needs.check-dependencies.outputs.security_updates }} | |
| - 📅 Generated: $(date +'%Y-%m-%d %H:%M:%S UTC') | |
| **Updated Modules:** | |
| \`\`\` | |
| $(cat outdated.txt | awk '{printf "%-40s %s → %s\n", $1, $2, $3}') | |
| \`\`\` | |
| **Security Vulnerabilities:** | |
| $(if [ -f "vuln-report.json" ] && [ -s "vuln-report.json" ]; then echo "Found security vulnerabilities requiring attention:"; cat vuln-report.json | jq -r '"- \(.ID): \(.details.summary // "")"'; else echo "No security vulnerabilities found."; fi) | |
| **Next Steps:** | |
| 1. 🧪 Review the test results | |
| 2. 🔍 Check for breaking changes in the dependency updates | |
| 3. ✅ Ensure all tests pass | |
| 4. 🚀 Merge if everything looks good | |
| **Automated Checks:** | |
| - [x] Dependency compatibility check | |
| - [x] Basic test suite execution | |
| - [x] Security vulnerability scan | |
| --- | |
| 🤖 Generated with [Claude Code](https://claude.com/claude-code) | |
| " | |
| gh pr create \ | |
| --title "$PR_TITLE" \ | |
| --body "$PR_BODY" \ | |
| --head "$BRANCH_NAME" \ | |
| --base main \ | |
| --label "dependencies" \ | |
| --label "automated" || { | |
| echo "PR creation failed or already exists" | |
| gh pr list --head "$BRANCH_NAME" || echo "No PR found for this branch" | |
| } | |
| compatibility-tests: | |
| name: Compatibility Testing | |
| runs-on: ubuntu-latest | |
| needs: check-dependencies | |
| if: needs.check-dependencies.outputs.updates_available == 'true' | |
| strategy: | |
| matrix: | |
| go_version: ['1.21', '1.22', '1.23'] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Go ${{ matrix.go_version }} | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ matrix.go_version }} | |
| cache: true | |
| - name: Cache go modules | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cache/go-build | |
| ~/go/pkg/mod | |
| key: ${{ runner.os }}-go-${{ matrix.go_version }}-${{ hashFiles('**/go.sum') }} | |
| - name: Update to latest dependencies | |
| run: | | |
| go get -u ./... | |
| go mod tidy | |
| - name: Run compatibility tests | |
| run: | | |
| go test -v ./... || { | |
| echo "Compatibility tests failed for Go ${{ matrix.go_version }}" | |
| exit 1 | |
| } | |
| - name: Build with updated dependencies | |
| run: | | |
| go build -o cortex-compat-${{ matrix.go_version }} ./cmd/router | |
| license-compliance: | |
| name: License Compliance Check | |
| runs-on: ubuntu-latest | |
| needs: check-dependencies | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| cache: true | |
| - name: Install go-licenses | |
| run: go install github.com/google/go-licenses@latest | |
| - name: Update to latest dependencies | |
| run: | | |
| go get -u ./... | |
| go mod tidy | |
| - name: Check licenses for updated dependencies | |
| run: | | |
| echo "Checking licenses for updated dependencies..." | |
| # Check licenses | |
| go-licenses check ./... || { | |
| echo "::warning::License check failed - review new dependencies" | |
| } | |
| # Generate license report | |
| go-licenses csv ./... > updated-licenses.csv | |
| # Check for problematic licenses | |
| if grep -i "gpl\|agpl\|lgpl" updated-licenses.csv; then | |
| echo "::warning::Found GPL/AGPL/LGPL licensed dependencies" | |
| echo "Review licensing compliance for new dependencies" | |
| else | |
| echo "✅ All dependencies have compatible licenses" | |
| fi | |
| - name: Upload license report | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: updated-licenses-${{ github.run_number }} | |
| path: updated-licenses.csv | |
| retention-days: 30 | |
| notify-dependencies: | |
| name: Dependency Update Notifications | |
| runs-on: ubuntu-latest | |
| needs: [check-dependencies, update-dependencies, compatibility-tests] | |
| if: always() | |
| steps: | |
| - name: Notify on successful updates | |
| if: needs.update-dependencies.result == 'success' | |
| run: | | |
| echo "✅ Dependency update process completed successfully!" | |
| echo "📊 Outdated dependencies found: ${{ needs.check-dependencies.outputs.outdated_count }}" | |
| echo "🔒 Security updates needed: ${{ needs.check-dependencies.outputs.security_updates }}" | |
| - name: Notify when no updates needed | |
| if: needs.check-dependencies.outputs.updates_available == 'false' | |
| run: | | |
| echo "✅ All dependencies are up to date!" | |
| echo "No action needed at this time." | |
| - name: Notify on failures | |
| if: needs.update-dependencies.result == 'failure' || needs.compatibility-tests.result == 'failure' | |
| run: | | |
| echo "⚠️ Dependency update process encountered issues" | |
| if [ "${{ needs.update-dependencies.result }}" = "failure" ]; then | |
| echo "- Dependency update failed" | |
| fi | |
| if [ "${{ needs.compatibility-tests.result }}" = "failure" ]; then | |
| echo "- Compatibility tests failed" | |
| fi | |
| echo "Please review the run logs and manually address any issues." | |
| - name: Create summary comment for dashboard | |
| if: github.event_name == 'schedule' | |
| run: | | |
| cat << EOF | |
| ## 📊 Dependency Update Summary - $(date +'%Y-%m-%d') | |
| - 📋 **Outdated Dependencies**: ${{ needs.check-dependencies.outputs.outdated_count }} | |
| - 🔒 **Security Updates**: ${{ needs.check-dependencies.outputs.security_updates }} | |
| - ✅ **Update Status**: ${{ needs.update-dependencies.result || 'completed' }} | |
| - 🧪 **Compatibility**: ${{ needs.compatibility-tests.result || 'passed' }} | |
| **Repository**: ${{ github.repository }} | |
| **Commit**: ${{ github.sha }} | |
| EOF |