├── .gitignore ├── CODEOWNERS ├── go-example ├── README.md ├── main.go ├── go.mod └── go.sum ├── bundler-example ├── Gemfile └── Gemfile.lock ├── .github ├── dependabot │ ├── bundler.yml │ └── go.yml └── workflows │ └── example.yml ├── LICENSE ├── create.sh └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | result.jsonl 2 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @dependabot/maintainers 2 | -------------------------------------------------------------------------------- /go-example/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | This is an example Go project that will be updated using the example Dependabot CLI workflow. 4 | -------------------------------------------------------------------------------- /go-example/main.go: -------------------------------------------------------------------------------- 1 | package go_example 2 | 3 | import ( 4 | _ "golang.org/x/net/html" 5 | _ "golang.org/x/text" 6 | ) 7 | 8 | func main() {} 9 | -------------------------------------------------------------------------------- /go-example/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/dependabot/example-cli-usage/example 2 | 3 | go 1.24.2 4 | 5 | require ( 6 | golang.org/x/net v0.32.0 7 | golang.org/x/text v0.21.0 8 | ) 9 | -------------------------------------------------------------------------------- /bundler-example/Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "rubocop", "0.76.0" 6 | gem "toml-rb", "2.2.0" 7 | gem 'rack', git: 'git@github.com:rack/rack.git', tag: '2.1.4' 8 | -------------------------------------------------------------------------------- /go-example/go.sum: -------------------------------------------------------------------------------- 1 | golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= 2 | golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= 3 | golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= 4 | golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= 5 | -------------------------------------------------------------------------------- /bundler-example/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GIT 2 | remote: git@github.com:rack/rack.git 3 | revision: f3cf79d6460dc592767941806d1b2b7008f73e01 4 | tag: 2.1.4 5 | specs: 6 | rack (2.1.4) 7 | 8 | GEM 9 | remote: https://rubygems.org/ 10 | specs: 11 | ast (2.4.2) 12 | citrus (3.0.2) 13 | jaro_winkler (1.5.4) 14 | parallel (1.22.1) 15 | parser (3.1.2.0) 16 | ast (~> 2.4.1) 17 | rainbow (3.1.1) 18 | rubocop (0.76.0) 19 | jaro_winkler (~> 1.5.1) 20 | parallel (~> 1.10) 21 | parser (>= 2.6) 22 | rainbow (>= 2.2.2, < 4.0) 23 | ruby-progressbar (~> 1.7) 24 | unicode-display_width (>= 1.4.0, < 1.7) 25 | ruby-progressbar (1.11.0) 26 | toml-rb (2.2.0) 27 | citrus (~> 3.0, > 3.0) 28 | unicode-display_width (1.6.1) 29 | 30 | PLATFORMS 31 | ruby 32 | 33 | DEPENDENCIES 34 | rack! 35 | rubocop (= 0.76.0) 36 | toml-rb (= 2.2.0) 37 | 38 | BUNDLED WITH 39 | 2.1.4 40 | -------------------------------------------------------------------------------- /.github/dependabot/bundler.yml: -------------------------------------------------------------------------------- 1 | # This is the input to Dependabot CLI. 2 | # For more examples of what you can do, see the smoke tests: https://github.com/dependabot/smoke-tests/tree/main/tests 3 | 4 | job: 5 | # this is the directory defined in dependabot-core for the ecosystem 6 | package-manager: bundler 7 | allowed-updates: 8 | - dependency-type: direct 9 | update-type: all 10 | source: 11 | provider: github 12 | repo: dependabot/example-cli-usage 13 | # looks absolute, but this is relative to the root of the repo 14 | directory: /bundler-example 15 | branch: main 16 | dependency-groups: 17 | - name: everything 18 | rules: 19 | patterns: 20 | - "*" 21 | # credentials are optional, but are used to authenticate with private repos and registries when provided 22 | credentials: 23 | - type: git_source 24 | # Most credentials take a url or host 25 | host: github.com 26 | # Credentials will be either username/password or token 27 | username: x-access-token 28 | # Dependabot CLI will inject secrets from the environment 29 | password: $GITHUB_TOKEN 30 | -------------------------------------------------------------------------------- /.github/dependabot/go.yml: -------------------------------------------------------------------------------- 1 | # This is the input to Dependabot CLI. 2 | # For more examples of what you can do, see the smoke tests: https://github.com/dependabot/smoke-tests/tree/main/tests 3 | 4 | job: 5 | # this is the directory defined in dependabot-core for the ecosystem 6 | package-manager: go_modules 7 | allowed-updates: 8 | - dependency-type: direct 9 | update-type: all 10 | experiments: 11 | # unlike with hosted Dependabot, you can control this variable directly 12 | goprivate: "" 13 | source: 14 | provider: github 15 | repo: dependabot/example-cli-usage 16 | # looks absolute, but this is relative to the root of the repo 17 | directory: /go-example 18 | branch: main 19 | # credentials are optional, but are used to authenticate with private repos and registries when provided 20 | credentials: 21 | - type: git_source 22 | # Most credentials take a url or host 23 | host: github.com 24 | # Credentials will be either username/password or token 25 | username: x-access-token 26 | # Dependabot CLI will inject secrets from the environment 27 | password: $GITHUB_TOKEN 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Dependabot 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /create.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script takes a jsonl file as input which is the stdout of a Dependabot CLI run. 4 | # It takes the `type: create_pull_request` events and creates a pull request for each of them 5 | # by using git commands. 6 | 7 | # Note at this time there is minimal error handling. 8 | 9 | set -euo pipefail 10 | 11 | if [ $# -ne 1 ]; then 12 | echo "Usage: $0 " 13 | exit 1 14 | fi 15 | 16 | INPUT="$1" 17 | 18 | git config --global user.email "support@github.com" 19 | git config --global user.name "Dependabot Standalone" 20 | git config --global advice.detachedHead false 21 | 22 | # Parse each create_pull_request event 23 | jq -c 'select(.type == "create_pull_request")' "$INPUT" | while read -r event; do 24 | # Extract fields 25 | BASE_SHA=$(echo "$event" | jq -r '.data."base-commit-sha"') 26 | PR_TITLE=$(echo "$event" | jq -r '.data."pr-title"') 27 | PR_BODY=$(echo "$event" | jq -r '.data."pr-body"') 28 | COMMIT_MSG=$(echo "$event" | jq -r '.data."commit-message"') 29 | BRANCH_NAME="dependabot-$(echo -n "$COMMIT_MSG" | sha1sum | awk '{print $1}')" 30 | 31 | echo "Processing PR: $PR_TITLE" 32 | echo " Base SHA: $BASE_SHA" 33 | echo " Branch: $BRANCH_NAME" 34 | 35 | # Create and checkout new branch from base commit 36 | git fetch origin 37 | git checkout "$BASE_SHA" 38 | git checkout -b "$BRANCH_NAME" 39 | 40 | # Apply file changes 41 | echo "$event" | jq -c '.data."updated-dependency-files"[]' | while read -r file; do 42 | FILE_PATH=$(echo "$file" | jq -r '.directory + "/" + .name' | sed 's#^/##') 43 | DELETED=$(echo "$file" | jq -r '.deleted') 44 | if [ "$DELETED" = "true" ]; then 45 | git rm -f "$FILE_PATH" || true 46 | else 47 | mkdir -p "$(dirname "$FILE_PATH")" 48 | echo "$file" | jq -r '.content' > "$FILE_PATH" 49 | git add "$FILE_PATH" 50 | fi 51 | done 52 | 53 | # Commit and push 54 | git commit -m "$COMMIT_MSG" 55 | git push -f origin "$BRANCH_NAME" 56 | 57 | # Create PR using gh CLI 58 | gh pr create --title "$PR_TITLE" --body "$PR_BODY" --base main --head "$BRANCH_NAME" --label dependencies || true 59 | 60 | # Return to main branch for next PR 61 | git checkout main 62 | done 63 | -------------------------------------------------------------------------------- /.github/workflows/example.yml: -------------------------------------------------------------------------------- 1 | name: Run Dependabot 2 | on: 3 | workflow_dispatch: 4 | 5 | jobs: 6 | run-dependabot: 7 | permissions: 8 | # Important not to give Dependabot write access in case it runs arbitrary 9 | # code as some ecosystems do. 10 | contents: read 11 | runs-on: ubuntu-latest 12 | steps: 13 | # Checkout code to get the Dependabot CLI input file 14 | - name: Checkout code 15 | uses: actions/checkout@v4 16 | # Checkout to a directory to keep the working dir clean for the update. 17 | with: 18 | path: repo 19 | 20 | - name: Download CLI 21 | env: 22 | # To use GitHub CLI in a GitHub Actions workflow, set the GH_TOKEN environment variable. 23 | GH_TOKEN: ${{ github.token }} 24 | run: | 25 | gh release download --repo dependabot/cli -p "*linux-amd64.tar.gz" 26 | tar xzvf *.tar.gz >/dev/null 2>&1 27 | ./dependabot --version 28 | 29 | - name: Run Dependabot 30 | env: 31 | # GITHUB_TOKEN shows an example of how Dependabot CLI can be used with secrets. 32 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 33 | run: | 34 | # Run Dependabot CLI with options: 35 | # -f: the path to the job input 36 | # --local: use the locally checked out code instead of cloning each time 37 | # --timeout: the maximum time to wait for a job to finish 38 | ./dependabot update \ 39 | -f repo/.github/dependabot/go.yml \ 40 | --local repo \ 41 | --timeout 20m >> result.jsonl || true 42 | ./dependabot update \ 43 | -f repo/.github/dependabot/bundler.yml \ 44 | --local repo \ 45 | --timeout 20m >> result.jsonl || true 46 | 47 | - name: Upload result 48 | uses: actions/upload-artifact@v4 49 | with: 50 | name: dependabot-result 51 | path: result.jsonl 52 | 53 | create-prs: 54 | permissions: 55 | # This job creates PRs, so it needs write access. 56 | contents: write 57 | pull-requests: write 58 | runs-on: ubuntu-latest 59 | needs: run-dependabot 60 | steps: 61 | - name: Checkout code 62 | uses: actions/checkout@v4 63 | 64 | - name: Download result 65 | uses: actions/download-artifact@v4 66 | with: 67 | name: dependabot-result 68 | 69 | - name: Create PRs 70 | env: 71 | # To use GitHub CLI in a GitHub Actions workflow, set the GH_TOKEN environment variable. 72 | GH_TOKEN: ${{ github.token }} 73 | run: bash create.sh result.jsonl 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | Dependabot 6 | 7 |
8 | 9 | # Example Dependabot CLI Usage 10 | 11 | This repo serves as an example of how to use Dependabot CLI for updates. It is intended as a starting point for advanced users to run a self-hosted version of Dependabot within their own projects. 12 | 13 | For a hassle-free Dependabot experience, check out the hosted [Dependabot Service](https://docs.github.com/en/github/administering-a-repository/about-dependabot-version-updates). 14 | 15 | This repo uses an Action which downloads and runs Dependabot CLI. To run the Action you would go to [the Action in the Actions tab](https://github.com/dependabot/example-cli-usage/actions/workflows/example.yml), and run it. 16 | 17 | To see what the results look like, go check out the Pull Requests. 18 | 19 | While this example repo runs on GitHub Actions, none of the Dependabot bits are specific to GitHub, so it should be straightforward to port it to any other CI system. 20 | 21 | ## Implementation details 22 | 23 | The Action is defined at [.github/workflows/example.yml](.github/workflows/example.yml). 24 | 25 | It contains two jobs, the first downloads and runs Dependabot CLI. The inputs for the CLI runs are in [.github/dependabot](.github/dependabot). See the [Dependabot CLI repo](https://github.com/dependabot/cli) for more info on inputs such as credentials and groupings. 26 | 27 | The results are redirected to a file and uploaded as artifacts. 28 | 29 | The second job downloads the artifact and creates PRs from it using the script [create.sh](create.sh). 30 | 31 | The reason there are two jobs is Dependabot CLI should only run with read-only tokens as some ecosystems may execute arbitrary code. To achieve that in Actions we must use two jobs with `permissions` defined differently. 32 | 33 | Also take a look at the [Dependabot Smoke Tests repo](https://github.com/dependabot/smoke-tests/tree/main/tests) for example inputs and expected outputs. 34 | 35 | ## Where can I go for help? 36 | 37 | If you are having issues with the updates to a specific ecosystem, head over to [dependabot-core](https://github.com/dependabot/dependabot-core). 38 | 39 | If there is a problem with running the Dependabot CLI, report that in the [CLI repo](https://github.com/dependabot/cli). 40 | 41 | We do not provide direct support for the scripts and workflows in this repo, this is only to serve as an example. 42 | 43 | --------------------------------------------------------------------------------