-
Notifications
You must be signed in to change notification settings - Fork 4
Auto approve dependabot #36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
simongdavies
merged 3 commits into
hyperlight-dev:main
from
simongdavies:auto-approve-dependabot
Apr 9, 2026
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,23 +1,26 @@ | ||
| # To get started with Dependabot version updates, you'll need to specify which | ||
| # package ecosystems to update and where the package manifests are located. | ||
| # Please see the documentation for all configuration options: | ||
| # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file | ||
|
|
||
| version: 2 | ||
| updates: | ||
| updates: | ||
| - package-ecosystem: "github-actions" | ||
| directory: "/" | ||
| schedule: | ||
| interval: "daily" | ||
| time: "03:00" | ||
| open-pull-requests-limit: 20 | ||
|
|
||
| - package-ecosystem: "cargo" | ||
| directories: | ||
| - "/" | ||
| directories: | ||
| - "/src/sandbox/runtime" | ||
| - "/src/code-validator/guest" | ||
| schedule: | ||
| interval: "daily" | ||
| time: "03:00" | ||
| open-pull-requests-limit: 20 | ||
|
|
||
| - package-ecosystem: "npm" | ||
| directory: "/src/js-host-api" | ||
| directories: | ||
| - "/" | ||
| - "/src/code-validator/guest" | ||
| schedule: | ||
| interval: "daily" | ||
| time: "03:00" | ||
| open-pull-requests-limit: 20 |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| name: Auto Merge Dependabot PRs | ||
|
|
||
| on: | ||
| schedule: | ||
| # Run daily at 04:00 UTC since dependabot runs at 03:00 UTC | ||
| - cron: '0 4 * * *' | ||
| workflow_dispatch: # Allow manual trigger | ||
|
|
||
| # This workflow uses a GitHub App token to approve and merge Dependabot PRs | ||
| # The token is created using the `actions/create-github-app-token` action | ||
| # The token is used so that the updates are made by the GitHub App instead of GitHub Actions | ||
| # and will show up as such in the PR comments and history | ||
| # In addition, the token is scoped to only the permissions needed for this workflow | ||
| # see https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/making-authenticated-api-requests-with-a-github-app-in-a-github-actions-workflow for details | ||
|
|
||
| jobs: | ||
| auto-merge-dependabot: | ||
| permissions: | ||
| contents: read | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
|
|
||
| # Gets the GitHub App token | ||
| - uses: actions/create-github-app-token@v3 | ||
| id: get-app-token | ||
| with: | ||
| # required | ||
| app-id: ${{ secrets.DEPENDABOT_APP_ID }} | ||
| private-key: ${{ secrets.DEPENDABOT_APP_KEY }} | ||
| permission-pull-requests: write | ||
| permission-contents: write | ||
| permission-checks: read | ||
| permission-actions: read | ||
|
|
||
| - name: Checkout code | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| token: ${{ steps.get-app-token.outputs.token }} | ||
| persist-credentials: false | ||
|
|
||
| - name: Setup GitHub CLI | ||
| run: | | ||
| # GitHub CLI is pre-installed on GitHub-hosted runners | ||
| gh --version | ||
|
|
||
| - name: Make script executable | ||
| run: chmod +x ./scripts/auto-approve-dependabot.sh | ||
|
|
||
| - name: Run auto approve script | ||
| env: | ||
| GITHUB_TOKEN: ${{ steps.get-app-token.outputs.token }} | ||
| run: ./scripts/auto-approve-dependabot.sh ${{ github.repository }} |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,160 @@ | ||
| #!/bin/bash | ||
| set -e | ||
| set -o pipefail | ||
|
|
||
| # This script checks for open PRs from dependabot that have all checks passing and have not been | ||
| # modified by another user, and approves+merges them automatically. | ||
| # To be run as a GitHub action. | ||
|
|
||
| # Check if repository argument is provided | ||
| if [ -z "$1" ]; then | ||
| echo "Error: Repository name not provided." | ||
| echo "Usage: $0 <owner/repo>" | ||
| echo "Example: $0 hyperlight-dev/hyperlight" | ||
| exit 1 | ||
| fi | ||
|
|
||
| REPO="$1" | ||
| echo "Checking for open Dependabot PRs to approve and merge in $REPO..." | ||
|
|
||
| # Get all open PRs from dependabot | ||
| # We filter so that only PRs that are not from forks and are in branches starting with "dependabot/cargo" are included. | ||
| dependabot_prs=$(gh pr list -R "$REPO" --author "dependabot[bot]" --state open --json number,title,reviews,headRepositoryOwner,headRefName | jq --arg repo_owner "$(echo "$REPO" | cut -d'/' -f1)" '[.[] | select(.headRepositoryOwner.login == $repo_owner and (.headRefName | startswith("dependabot/cargo")))]') | ||
| # Exit early if no PRs found | ||
| if [ -z "$dependabot_prs" ] || [ "$dependabot_prs" = "[]" ]; then | ||
| echo "No open Dependabot PRs found in $REPO" | ||
| exit 0 | ||
| fi | ||
|
|
||
| # Count how many PRs we found | ||
| pr_count=$(echo "$dependabot_prs" | jq 'length') | ||
| echo "Found $pr_count open Dependabot PRs in $REPO" | ||
|
|
||
| # Process each PR | ||
| echo "$dependabot_prs" | jq -c '.[]' | while read -r pr; do | ||
| pr_number=$(echo "$pr" | jq -r '.number') | ||
| pr_title=$(echo "$pr" | jq -r '.title') | ||
|
|
||
| echo "Processing PR #$pr_number: $pr_title" | ||
|
|
||
| # Check if PR only modifies allowed files | ||
| pr_files=$(gh pr view "$pr_number" -R "$REPO" --json files) | ||
| invalid_files=$(echo "$pr_files" | jq -r '.files[].path' | grep -v -E '(Cargo\.toml|Cargo\.lock)' || true) | ||
|
|
||
| if [ -n "$invalid_files" ]; then | ||
| echo " ❌ PR #$pr_number modifies files that are not allowed for auto-merge:" | ||
| printf '%s\n' "$invalid_files" | sed 's/^/ - /' | ||
| echo " ℹ️ Only changes to Cargo.toml and Cargo.lock are allowed" | ||
| continue | ||
| fi | ||
|
|
||
| echo " ✅ PR #$pr_number only modifies allowed files (Cargo.toml and Cargo.lock)" | ||
|
|
||
| # First, get detailed PR information including all checks | ||
| pr_details=$(gh pr view "$pr_number" -R "$REPO" --json statusCheckRollup,state) | ||
|
|
||
| # Check if all status checks have passed (regardless of required or not) | ||
| all_checks_pass=true | ||
| has_pending_checks=false | ||
| failed_checks="" | ||
|
|
||
| # First identify checks that are still in progress | ||
| pending_checks=$(echo "$pr_details" | jq -r '.statusCheckRollup[] | select(.status == "IN_PROGRESS" or .status == "QUEUED" or .status == "PENDING") | .name') | ||
|
|
||
| # Check for permission-required checks | ||
| permission_required_checks=$(echo "$pr_details" | jq -r '.statusCheckRollup[] | select(.status == "WAITING" or .status == "ACTION_REQUIRED" or (.status == "QUEUED" and .conclusion == null and .detailsUrl != null and (.detailsUrl | contains("waiting-for-approval")))) | .name') | ||
|
|
||
| # Don't approve if there are checks required that need permission to run | ||
| if [ -n "$permission_required_checks" ]; then | ||
| echo " 🔐 PR #$pr_number has checks waiting for permission:" | ||
| echo "$permission_required_checks" | sed 's/^/ - /' | ||
| echo " ❌ Skipping auto-approval due to permission-required checks" | ||
| continue | ||
| fi | ||
|
|
||
| if [ -n "$pending_checks" ]; then | ||
| echo " ⏳ PR #$pr_number has pending checks:" | ||
| echo "$pending_checks" | sed 's/^/ - /' | ||
| echo " ℹ️ We will still approve the PR so it can merge automatically once all checks pass" | ||
| has_pending_checks=true | ||
| fi | ||
|
|
||
| # Check for failed checks - only include checks that have a conclusion and are not still running | ||
| # Explicitly exclude checks with status IN_PROGRESS, QUEUED, or PENDING | ||
| failed_checks=$(echo "$pr_details" | jq -r '.statusCheckRollup[] | | ||
| select(.conclusion != null and | ||
| .conclusion != "SUCCESS" and | ||
| .conclusion != "NEUTRAL" and | ||
| .conclusion != "SKIPPED" and | ||
| .status != "IN_PROGRESS" and | ||
| .status != "QUEUED" and | ||
| .status != "PENDING") | .name') | ||
|
|
||
| if [ -n "$failed_checks" ]; then | ||
| echo " ❌ PR #$pr_number has failed checks:" | ||
| echo "$failed_checks" | sed 's/^/ - /' | ||
| all_checks_pass=false | ||
| continue | ||
| fi | ||
|
|
||
| # If we've reached here, either all checks have passed or some are pending | ||
| if [ "$has_pending_checks" = false ]; then | ||
| echo " ✅ All status checks passed for PR #$pr_number" | ||
| fi | ||
|
|
||
| # Check if PR has been modified by someone other than dependabot | ||
| pr_commits=$(gh pr view "$pr_number" -R "$REPO" --json commits) | ||
| non_dependabot_authors=$(echo "$pr_commits" | jq -r '.commits[].authors[].login' | grep -v -e "dependabot\[bot\]" -e "^$" || true) | ||
|
|
||
| if [ -n "$non_dependabot_authors" ]; then | ||
| echo " ❌ PR #$pr_number has been modified by users other than dependabot: $non_dependabot_authors" | ||
| continue | ||
| fi | ||
|
|
||
| # Check if PR needs approval (i.e., hasn't been approved already) | ||
| already_approved=$(echo "$pr" | jq -r '.reviews[] | select(.state == "APPROVED") | .state' | grep -c "APPROVED" || true) | ||
|
|
||
| if [ "$already_approved" -eq 0 ]; then | ||
| echo " ✅ Approving PR #$pr_number" | ||
| gh pr review "$pr_number" -R "$REPO" --approve -b "Automatically approved by dependabot auto-approve workflow" | ||
| else | ||
| echo " ℹ️ PR #$pr_number is already approved" | ||
| fi | ||
|
|
||
| if [ "$has_pending_checks" = true ] || [ "$all_checks_pass" = true ]; then | ||
| # Check if PR is draft and whether it is up-to-date with base branch | ||
| pr_merge_info=$(gh pr view "$pr_number" -R "$REPO" --json isDraft,mergeStateStatus) | ||
| is_draft=$(echo "$pr_merge_info" | jq -r '.isDraft') | ||
| merge_status=$(echo "$pr_merge_info" | jq -r '.mergeStateStatus') | ||
|
|
||
| if [ "$is_draft" = "true" ]; then | ||
| echo " ⚠️ PR #$pr_number is a draft PR; skipping merge" | ||
| continue | ||
| fi | ||
|
|
||
| if [ "$merge_status" != "CLEAN" ]; then | ||
| echo " ⚠️ PR #$pr_number is not up to date (status: $merge_status)" | ||
| # Enable auto-merge to merge once checks pass | ||
| echo " ✅ Enabling auto-merge (squash strategy) for PR #$pr_number" | ||
| if gh pr merge "$pr_number" -R "$REPO" --auto --squash; then | ||
| echo " ✅ Auto-merge enabled for PR #$pr_number" | ||
| else | ||
| echo " ⚠️ Failed to enable auto-merge for PR #$pr_number; continuing to next PR" | ||
| continue | ||
| fi | ||
| else | ||
| echo " ✅ PR #$pr_number is up to date with base branch" | ||
| # PR is already clean/mergeable - merge directly instead of enabling auto-merge | ||
| echo " ✅ Merging PR #$pr_number directly (squash strategy)" | ||
| if gh pr merge "$pr_number" -R "$REPO" --squash; then | ||
| echo " ✅ PR #$pr_number merged successfully" | ||
| else | ||
| echo " ⚠️ Failed to merge PR #$pr_number; continuing to next PR" | ||
| continue | ||
| fi | ||
| fi | ||
| fi | ||
|
|
||
| done | ||
|
|
||
| echo "Finished processing Dependabot PRs for $REPO" | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.