More
Choose

Building Your Own Umbraco Cloud Style Auto-Upgrades with GitHub Dependabot

Umbraco Cloud's auto-upgrade feature is one of its best, but you do not have to be on Cloud to get it. Here is how to build the same pattern on any self-hosted Umbraco project (GreenStack or otherwise) using GitHub Dependabot and Actions.

Read Post
Category:  Umbraco
Posted:  28th May 2026

Automated Umbraco upgrades are something any GreenStack customer is free to wire into their own projects. Patch releases including security patches can flow through your environments automatically. Minor versions can be auto-applied if you opt in. Major versions stay manual so you can plan the upgrade properly. It is the same pattern Umbraco Cloud uses for its own auto-upgrade feature, but the implementation lives entirely in your own GitHub organisation, which means you keep full control of the workflow, the rules, and the deployment pipeline. If you ever want to leave us, there is nothing on the source control side to migrate away from because nothing was ever tied to GreenStack in the first place.

The good news: it is all built from standard GitHub tooling. If you self-host Umbraco anywhere, GreenStack or otherwise, you can set this up yourself. This post walks through how.

What we are building

The behaviour we are aiming for, mirroring how Umbraco Cloud's own auto-upgrade works:

  • The behaviour we are aiming for, mirroring how Umbraco Cloud's own auto-upgrade works:

  • Patches are applied automatically by default, including security patches

  • Minor upgrades can be toggled on per project

  • Major upgrades stay manual

  • Upgrades apply to the left-most environment first (Development)

  • A health check verifies the homepage still returns HTTP 200 and the HTML matches a pre-upgrade snapshot

  • If the check passes, the upgrade promotes to the next environment in the chain

  • If the check fails, the deployment rolls back and you get a notification

We will deliver this with:

  • Dependabot raising PRs for new Umbraco versions on a schedule

  • A GitHub Actions workflow that auto-approves and auto-merges patch and minor updates

  • Branch protection that gates the merge on your CI passing

  • Your existing deployment pipeline doing the dev to staging to production promotion

The basic Dependabot setup

Dependabot reads its config from .github/dependabot.yml. The minimal version looks like this:

Commit and push, and within a few minutes Dependabot will scan your project files and start opening PRs for outdated NuGet packages. The directory value points at the folder containing your solution or .csproj. If yours lives in src, change this to /src.

Staying on Umbraco V17

V17 is the current Long-Term Support (LTS) release, with full support running until November 2028. For most production sites V17 is where you will want to sit for a good while, and you do not want Dependabot opening a PR that bumps you to V18 the moment it ships in Q2 2026. Major versions bring breaking changes, and the upgrade needs planning, testing, and a maintenance window.

Tell Dependabot to ignore major version bumps for Umbraco packages:

The wildcard Umbraco.Cms* covers the metapackage and all sub-packages (Umbraco.Cms.Core, Umbraco.Cms.Web.Common, Umbraco.Cms.Persistence.SqlServer, and so on). With this in place Dependabot will:

  • Open PRs for patch updates (V17.1.2 to V17.1.3)

  • Open PRs for minor updates (V17.1.x to V17.2.x)

  • Skip major updates (V17.x to V18.x)

When you are eventually ready to move on (whether that is the next LTS, or jumping onto an STS release sooner because you need a specific feature), the upgrade itself needs to happen locally. Pull the branch, bump the Umbraco packages by hand, work through any breaking changes, run any migrations, test thoroughly, and commit the upgraded version. Once that lands on your branch, Dependabot treats the new major as your baseline and resumes opening PRs for its patches and minors automatically. The ignore rule stays in place exactly as it is and continues to do its job for the next major after that.

If you use Umbraco Forms or other Umbraco add-ons, add them to the ignore list too:

This pattern is version-agnostic. The same config works whether your site is running V13, V14, V15, V16, or V17. On GreenStack we run sites across every currently supported Umbraco major in production, and the same Dependabot pattern applies to all of them. Just change the wildcard target version expectation in your head, the YAML itself does not need to know which major you are on.

Tracking updates across major versions

If you actively want to ride the latest Umbraco release as it ships, drop the ignore rules entirely. The default behaviour is to surface all updates, including majors:

The open-pull-requests-limit is worth bumping up here, since a fresh major release can trigger PRs across multiple Umbraco packages at once.

Grouping Umbraco packages

By default, Dependabot opens one PR per package. For Umbraco that means several PRs land at once for related packages that really should move together. Grouping fixes this:

Now all minor and patch updates to Umbraco packages arrive as a single PR. Major updates, if you allow them, still come through individually since they typically need more attention.

Auto-merging on dev and staging

This is where we start replicating the Cloud auto-upgrade behaviour. The pattern is:

  1. Dependabot raises a PR targeting your dev or develop branch

  2. CI runs (build, tests, smoke tests)

  3. A GitHub Actions workflow approves and enables auto-merge for patch and minor updates

  4. Branch protection holds the merge until all required checks pass

  5. Once merged, your deployment pipeline pushes the change to dev, then staging, with health checks at each stage

  6. Production stays behind a manual approval gate

Targeting a dev branch

By default Dependabot opens PRs against your default branch (usually main). If your Git flow has a separate develop branch that deploys to your dev environment, point Dependabot at it with target-branch:

PRs now land on develop, get tested and merged there, deploy to dev, and a human can later promote to staging and production via normal PRs.

If your team works on main and uses environment promotion via the deployment pipeline rather than separate branches, leave target-branch off. The auto-merge workflow below works either way.

The auto-merge workflow

Create .github/workflows/dependabot-auto-merge.yml:

Walking through what it does:

  • Triggers on any PR opened or updated

  • Only runs if the PR author is dependabot[bot], so it cannot be misused on human PRs

  • Reads metadata from the Dependabot PR to find out what kind of update it is

  • Approves and enables auto-merge for patch and minor updates only

  • Major updates fall through to manual review, exactly as Umbraco Cloud does

A note on tokens: the default GITHUB_TOKEN is fine for the merge itself, but actions triggered by that merge will not run because GitHub prevents recursive workflow triggers from the default token. If you need post-merge workflows (such as a deployment) to fire automatically, swap in a Personal Access Token or GitHub App token via secrets.DEPENDABOT_TOKEN instead.

Branch protection is not optional

gh pr merge --auto enables auto-merge, but the PR will not actually merge until your branch protection rules are satisfied. This is the gate that makes auto-merge safe rather than reckless.

In your repository settings, under Branches, protect your target branch (whether main, develop, or whatever you use) with:

  • Require status checks to pass before merging

  • Select your build and test workflows as required checks

  • Require branches to be up to date before merging

  • Require at least one approving review (the workflow above provides this)

Without those rules, auto-merge will happily push a broken build into your environment. With them, a failing build blocks the merge and the PR sits there waiting for you to investigate.

Recreating the Umbraco Cloud health check

Cloud's health check is essentially "does the homepage still load and look like it did before the upgrade?" This part is intentionally separate from the Dependabot config and the auto-merge workflow above. The check needs to run after a deployment has actually completed, so it belongs in whichever GitHub Actions workflow handles your dev and staging deployments, not in dependabot.yml. As a starting point, drop a step like this into your deployment job:

That is the same idea Cloud uses, just expressed in your own pipeline. If the smoke test fails, the deployment job fails, the promotion to staging does not happen, and you get a notification. Rollback behaviour depends on your deployment tooling: blue/green deployments and Docker tags both make this straightforward, and on GreenStack we use a similar pattern internally for our own platform updates.

For more thorough checks, consider Playwright or Cypress against a known-good page set. The cost is build time, the benefit is confidence that nothing visually obvious has broken.

A complete example

Here is a config that pulls everything together:

  • Stays on Umbraco V17

  • Groups Umbraco patches and minors into one PR

  • Targets the develop branch so auto-merged updates flow through dev first

  • Allows all updates for third-party packages

  • Runs on Mondays at 07:00 UK time

  • Adds labels to the PRs

Pair that with the auto-merge workflow above, lock down branch protection on develop, and add the smoke test from the previous section into your deployment workflow (it is not part of the Dependabot config or the auto-merge workflow, so it does need wiring in separately). Your dev environment now keeps itself patched in the same hands-off way an Umbraco Cloud project does.

A few things worth knowing

Dependabot can also keep your GitHub Actions workflows up to date. Add a second entry to the updates array with package-ecosystem: "github-actions" and directory: "/". It pays off when an action you use silently deprecates.

If you run several Umbraco solutions in a monorepo, each one needs its own updates entry with the appropriate directory.

You can point Dependabot at private NuGet feeds (Azure Artifacts, GitHub Packages, MyGet) by adding a registries section. GitHub's Dependabot documentation covers the auth options.

If you want to be extra cautious, add a cooldown period (a recent Dependabot feature) so that a package needs to have been on NuGet for a few days before Dependabot raises a PR. That avoids you being the first to deploy a buggy patch.

Wrap up

You will not get a one-click portal toggle out of this, and you have to do the branch protection and deployment pipeline work yourself. What you do get is the same essential workflow: dependency updates land continuously, get tested automatically, flow through your environments with health checks at each step, and only break out of automation when something needs a human eye.

For most self-hosted Umbraco setups, that is plenty. Start with weekly Dependabot, layer on auto-merge for patches and minors, hook a smoke test into your dev and staging deployments, and keep production behind a manual gate. Once it is running, the only Umbraco updates you need to think about are the major versions, which is exactly the point.

Want a hand setting this up?

If you have read this far and thought "great, but I have actual product work to be getting on with," we are happy to help GreenStack customers get this in place. We can sanity-check your Dependabot config, the auto-merge workflow, the branch protection rules, and the smoke tests against the rest of your repository, on whichever Umbraco major your project is on (we currently host sites in production across V13 through V17, and any new major as soon as it is released).

Everything still lives in your GitHub organisation. We do not host your source code, we do not lock you into a proprietary Git workflow, and if you decide to move on you take the whole setup with you. We are just the team that can wire it up alongside you if you would rather not do it from scratch.

Get in touch if you would like to talk through what this could look like for your sites.