Skip to content

Dependabot

Dependabot #7

Workflow file for this run

name: Dependabot
on:
pull_request:
types: [opened, synchronize, reopened]
schedule:
# Monthly lock file maintenance on first Monday at 6 AM
- cron: '0 6 1 * 1'
workflow_dispatch:
concurrency:
group: "dependency-updates-${{ github.ref }}"
cancel-in-progress: true
jobs:
config:
name: Get Configuration
runs-on: ubuntu-latest
outputs:
default-python-version: ${{ steps.config.outputs.default-python-version }}
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Get project configuration
id: config
uses: ./.github/actions/get-config
setup-cache:
name: Setup Cache
needs: config
uses: ./.github/workflows/cache-management.yml
with:
cache-type: dependencies
cache-key-base: dependabot
python-version: ${{ needs.config.outputs.default-python-version }}
update-uv-lock:
name: Update UV Lock File
if: github.actor == 'dependabot[bot]' && github.event_name == 'pull_request'
runs-on: ubuntu-latest
needs: [config, setup-cache]
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0
- name: Setup Python and UV
uses: ./.github/actions/setup-uv-cached
with:
cache-key: ${{ needs.setup-cache.outputs.cache-key }}
fail-on-cache-miss: false
- name: Update UV lock file
run: |
uv lock
- name: Commit updated lock file
run: |
make ci-git-setup
if [[ -n $(git status --porcelain) ]]; then
git add uv.lock
git commit -m "chore: update uv.lock after dependabot changes"
git push
else
echo "No changes to commit"
fi
auto-merge:
name: Auto-merge
if: github.actor == 'dependabot[bot]' && github.event_name == 'pull_request'
runs-on: ubuntu-latest
needs: [update-uv-lock]
permissions:
contents: write
pull-requests: write
checks: read
steps:
- name: Check if PR is ready for auto-merge
id: check-automerge
uses: actions/github-script@v9
with:
script: |
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number
});
// SECURITY: Sanitize inputs to prevent injection
const title = pr.title.toLowerCase().replace(/[^a-z0-9\-\s]/g, '');
const allowedLabels = ['patch', 'minor', 'major', 'dependencies', 'dev-dependencies', 'security'];
const labels = pr.labels
.map(label => label.name)
.filter(name => allowedLabels.includes(name));
// Auto-merge conditions
const isPatch = title.includes('patch') || labels.includes('patch');
const isMinor = title.includes('minor') || labels.includes('minor');
const isDev = title.includes('dev-dependencies') || labels.includes('dependencies');
const shouldAutoMerge = isPatch || (isMinor && isDev);
console.log(`Sanitized title: ${title}`);
console.log(`Filtered labels: ${labels.join(', ')}`);
console.log(`Should auto-merge: ${shouldAutoMerge}`);
return shouldAutoMerge;
- name: Wait for checks to complete
if: steps.check-automerge.outputs.result == 'true'
uses: actions/github-script@v9
with:
script: |
const maxWaitTime = 10 * 60 * 1000; // 10 minutes
const checkInterval = 30 * 1000; // 30 seconds
const startTime = Date.now();
while (Date.now() - startTime < maxWaitTime) {
const { data: checks } = await github.rest.checks.listForRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: context.payload.pull_request.head.sha
});
const relevantChecks = checks.check_runs.filter(check =>
!check.name.includes('auto-merge') &&
!check.name.includes('dependabot')
);
const allCompleted = relevantChecks.every(check =>
check.status === 'completed'
);
const allSuccessful = relevantChecks.every(check =>
check.conclusion === 'success' || check.conclusion === 'neutral'
);
if (allCompleted && allSuccessful) {
console.log('All checks passed!');
return true;
}
if (allCompleted && !allSuccessful) {
console.log('Some checks failed, not auto-merging');
return false;
}
console.log('Waiting for checks to complete...');
await new Promise(resolve => setTimeout(resolve, checkInterval));
}
console.log('Timeout waiting for checks');
return false;
- name: Auto-merge PR
if: steps.check-automerge.outputs.result == 'true'
uses: actions/github-script@v9
with:
script: |
await github.rest.pulls.merge({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
merge_method: 'squash',
commit_title: `${context.payload.pull_request.title} (#${context.issue.number})`,
commit_message: 'Auto-merged by Dependabot workflow'
});
monthly-maintenance:
name: Monthly Maintenance
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
needs: [config, setup-cache]
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Python and UV
uses: ./.github/actions/setup-uv-cached
with:
cache-key: ${{ needs.setup-cache.outputs.cache-key }}
fail-on-cache-miss: false
- name: Update all dependencies
run: |
echo "Updating all dependencies..."
uv lock --upgrade
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "chore: monthly dependency maintenance"
title: "chore: monthly dependency maintenance"
body: |
## Monthly Dependency Maintenance
This PR updates all dependencies to their latest compatible versions.
### Changes
- Updated `uv.lock` with latest dependency versions
- Automated monthly maintenance run
### Review Notes
- Check for any breaking changes in updated dependencies
- Verify all tests pass before merging
- Review security advisories for updated packages
branch: chore/monthly-dependency-maintenance
delete-branch: true
labels: |
dependencies
maintenance
automated