Dependency Updates #5
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: | |
| # Run every Monday at 9:00 AM UTC | |
| - cron: '0 9 * * 1' | |
| workflow_dispatch: | |
| inputs: | |
| update_type: | |
| description: 'Type of update to perform' | |
| required: true | |
| default: 'security' | |
| type: choice | |
| options: | |
| - security | |
| - patch | |
| - minor | |
| - all | |
| env: | |
| RUBY_VERSION: '3.1' | |
| jobs: | |
| check-dependencies: | |
| name: Check Dependencies | |
| runs-on: ubuntu-latest | |
| outputs: | |
| has-updates: ${{ steps.check.outputs.has-updates }} | |
| security-updates: ${{ steps.check.outputs.security-updates }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Ruby | |
| uses: ruby/setup-ruby@v1 | |
| with: | |
| ruby-version: ${{ env.RUBY_VERSION }} | |
| bundler-cache: true | |
| - name: Install dependency tools | |
| run: | | |
| gem install bundler-audit | |
| bundle install | |
| - name: Check for security vulnerabilities | |
| id: check | |
| run: | | |
| echo "Checking for security vulnerabilities..." | |
| # Update vulnerability database | |
| bundle audit update | |
| # Check for vulnerabilities | |
| if bundle audit check --format json --output security-check.json; then | |
| echo "has-updates=false" >> $GITHUB_OUTPUT | |
| echo "security-updates=false" >> $GITHUB_OUTPUT | |
| echo "✅ No security vulnerabilities found" | |
| else | |
| echo "has-updates=true" >> $GITHUB_OUTPUT | |
| echo "security-updates=true" >> $GITHUB_OUTPUT | |
| echo "⚠️ Security vulnerabilities found" | |
| fi | |
| # Check for outdated gems | |
| if bundle outdated --parseable > outdated.txt; then | |
| if [ -s outdated.txt ]; then | |
| echo "has-updates=true" >> $GITHUB_OUTPUT | |
| echo "📦 Outdated dependencies found" | |
| fi | |
| fi | |
| - name: Upload dependency check results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: dependency-check-results | |
| path: | | |
| security-check.json | |
| outdated.txt | |
| update-dependencies: | |
| name: Update Dependencies | |
| runs-on: ubuntu-latest | |
| needs: check-dependencies | |
| if: needs.check-dependencies.outputs.has-updates == 'true' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Set up Ruby | |
| uses: ruby/setup-ruby@v1 | |
| with: | |
| ruby-version: ${{ env.RUBY_VERSION }} | |
| bundler-cache: true | |
| - name: Configure Git | |
| run: | | |
| git config --local user.email "action@github.com" | |
| git config --local user.name "GitHub Action" | |
| - name: Update security vulnerabilities | |
| if: needs.check-dependencies.outputs.security-updates == 'true' | |
| run: | | |
| echo "🔒 Updating security vulnerabilities..." | |
| # Install bundler-audit | |
| gem install bundler-audit | |
| bundle audit update | |
| # Get list of vulnerable gems | |
| bundle audit check --format json --output vulnerabilities.json || true | |
| # Update vulnerable gems (this is a simplified approach) | |
| bundle update --conservative | |
| # Verify fixes | |
| if bundle audit check; then | |
| echo "✅ Security vulnerabilities resolved" | |
| # Commit changes if any | |
| if ! git diff --quiet Gemfile.lock; then | |
| git add Gemfile.lock | |
| git commit -m "security: update vulnerable dependencies | |
| - Updated gems to resolve security vulnerabilities | |
| - Automated update via GitHub Actions | |
| Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>" | |
| # Create pull request | |
| git push origin HEAD:security-updates-$(date +%Y%m%d) | |
| fi | |
| else | |
| echo "❌ Some security vulnerabilities remain" | |
| fi | |
| - name: Update patch versions | |
| if: github.event.inputs.update_type == 'patch' || github.event.inputs.update_type == 'all' | |
| run: | | |
| echo "🔧 Updating patch versions..." | |
| bundle update --patch | |
| if ! git diff --quiet Gemfile.lock; then | |
| git add Gemfile.lock | |
| git commit -m "deps: update patch versions | |
| - Updated gems to latest patch versions | |
| - Automated update via GitHub Actions" | |
| fi | |
| - name: Update minor versions | |
| if: github.event.inputs.update_type == 'minor' || github.event.inputs.update_type == 'all' | |
| run: | | |
| echo "📦 Updating minor versions..." | |
| bundle update --minor | |
| if ! git diff --quiet Gemfile.lock; then | |
| git add Gemfile.lock | |
| git commit -m "deps: update minor versions | |
| - Updated gems to latest minor versions | |
| - Automated update via GitHub Actions" | |
| fi | |
| - name: Run tests after updates | |
| run: | | |
| echo "🧪 Running tests after dependency updates..." | |
| bundle install | |
| bundle exec rspec --format progress | |
| bundle exec rubocop | |
| - name: Create pull request | |
| if: success() | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const { execSync } = require('child_process'); | |
| // Check if there are any changes | |
| try { | |
| execSync('git diff --quiet HEAD~1'); | |
| console.log('No changes to create PR for'); | |
| return; | |
| } catch (error) { | |
| // There are changes, continue with PR creation | |
| } | |
| const branchName = `dependency-updates-${new Date().toISOString().split('T')[0]}`; | |
| // Create and push branch | |
| execSync(`git checkout -b ${branchName}`); | |
| execSync(`git push origin ${branchName}`); | |
| // Create pull request | |
| const { data: pr } = await github.rest.pulls.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title: '🔒 Automated Dependency Updates', | |
| head: branchName, | |
| base: 'main', | |
| body: `## Automated Dependency Updates | |
| This PR contains automated dependency updates performed by GitHub Actions. | |
| ### Changes Made | |
| - 🔒 Security vulnerability fixes | |
| - 📦 Dependency updates (${context.payload.inputs?.update_type || 'security'}) | |
| - ✅ All tests passing | |
| ### Verification | |
| - [x] Security vulnerabilities resolved | |
| - [x] Tests passing | |
| - [x] Code style checks passing | |
| ### Review Notes | |
| Please review the changes and ensure compatibility with the existing codebase. | |
| **Auto-merge**: This PR can be auto-merged if all checks pass and no breaking changes are detected. | |
| --- | |
| *This PR was created automatically by GitHub Actions*`, | |
| draft: false | |
| }); | |
| // Add labels | |
| await github.rest.issues.addLabels({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: pr.number, | |
| labels: ['dependencies', 'security', 'automated'] | |
| }); | |
| console.log(`Created PR #${pr.number}: ${pr.html_url}`); | |
| notify-security-team: | |
| name: Notify Security Team | |
| runs-on: ubuntu-latest | |
| needs: [check-dependencies, update-dependencies] | |
| if: always() && needs.check-dependencies.outputs.security-updates == 'true' | |
| steps: | |
| - name: Send security notification | |
| run: | | |
| if [ "${{ needs.update-dependencies.result }}" = "success" ]; then | |
| echo "✅ Security vulnerabilities have been automatically updated" | |
| echo "A pull request has been created for review" | |
| else | |
| echo "❌ Failed to automatically update security vulnerabilities" | |
| echo "Manual intervention may be required" | |
| fi | |
| echo "Repository: ${{ github.repository }}" | |
| echo "Workflow: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" |