GitHub has made it as easy as six lines of YAML to get started with Dependabot, and I wanted to get as close to that as possible. Skip to the steps if you already know all the pieces.

Dependabot is fantastic. It produces beautiful merge requests (pretty please GitHub can you please change it to the name which makes sense?), one per dependency, with a conventional commit title, release notes, change log and link to a diff. GitLab is also fantastic, providing a free and open source project management system rivalling and often surpassing GitHub. Unfortunately Dependabot is now part of GitHub/Microsoft, and GitLab doesn’t yet have any decent dependency update feature (as far as I know). Fortunately our hero andrejs has done the legwork, and we can all enjoy the results.

Dependabot for GitLab is a complex beast, probably because Dependabot is complex under the hood. But a little digging reveals that the most common use case of just replicating the GitHub functionality is pretty simple.

The steps

  1. Create and merge .gitlab/dependabot.yml (example). Dependabot uses the version of this file on your default branch (SettingsRepositoryDefault branch) rather than your current one, so you’ll want to merge it first.
  2. While that’s getting merged, create a personal access token with the “api” scope.
  3. In SettingsCI/CDVariables add a variable called SETTINGS__GITLAB_ACCESS_TOKEN with the token generated above. Optionally set it to be both protected and masked.
  4. Change your gitlab-ci.yml file (example) to include the following:

    .dependabot:
      image:
        name: docker.io/andrcuns/dependabot-gitlab:0.11.0
        entrypoint: [""]
      variables:
        GIT_STRATEGY: none
        PACKAGE_MANAGER: $CI_JOB_NAME
        RAILS_ENV: production
        SETTINGS__GITLAB_URL: $CI_SERVER_URL
        SETTINGS__STANDALONE: "true"
      before_script:
        - cd /home/dependabot/app
      script:
        - bundle exec rake
          "dependabot:update[$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME,$PACKAGE_MANAGER,/]"
      rules:
        - if:
            '$CI_PIPELINE_SOURCE == "schedule" && $SCHEDULE_NAME == "dependabot"'
    
    gitsubmodule:
      extends: .dependabot
    
    pip:
      extends: .dependabot
    

    That last bit is much more complex, so I’ll go through it slowly:

    • .dependabot: starts a GitLab template, referenced as extends: .dependabot below.
    • The image: part is straight from the “standalone” repo. I’ve no idea why they set the entrypoint.
    • GIT_STRATEGY: none seems to skip a bunch of default actions when dealing with the repo.
    • PACKAGE_MANAGER links the name of the job (gitsubmodule and pip above) to the package-ecosystem property in .gitlab/dependabot.yml via the script command.
    • The rest of the variables I haven’t looked into, except to find that the job bombs if RAILS_ENV: production is not specified.
    • bundle exec rake "dependabot:update[$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME,$PACKAGE_MANAGER,/]" should handle most Dependabot use cases:
      • You shouldn’t need to touch $CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME; it’s basically saying I want to upgrade the dependencies in the repo where this job is running.
      • $PACKAGE_MANAGER and / are lookups for the package-ecosystem and directory properties in .gitlab/dependabot.yml.
    • You don’t want this job triggering every time you run a pipeline. if: […] ensures that it only runs when triggered via a schedule (CI/CDSchedules) with a variable SCHEDULE_NAME which has a value of dependabot.

That’s it. That was all the configuration necessary to get excellent merge requests like this one. If you want anything more complex I’d suggest checking out the Dependabot for GitLab repo.