Renovate Dependency Management Research

Research findings on Renovate’s Go language support, dependency grouping strategies, and automerge capabilities for Go projects.

This document presents comprehensive research on Renovate Bot’s capabilities for managing dependencies in Go projects. It covers Go language support, dependency grouping strategies, automerge capabilities, real-world examples, and best practices for implementing effective dependency automation.

Table of Contents

  1. Overview
  2. Go Language Support
  3. Dependency Grouping Strategies
  4. Automerge Capabilities
  5. Real-World Examples
  6. Best Practices and Recommendations

Overview

Renovate is an automated dependency update tool that provides comprehensive support for Go modules through its gomod manager. It offers powerful automation capabilities while maintaining security and stability through configurable safety mechanisms.

Key Capabilities

  • Automatic Detection: Scans repositories for go.mod files at any depth
  • SemVer Support: Understands semantic versioning and update types
  • Monorepo Grouping: Intelligently groups related dependencies
  • Automerge: Reduces manual work with configurable safety mechanisms
  • Security Integration: OSV vulnerability database integration
  • Customization: Extensive configuration options via packageRules

Go Language Support

Detection and Update Process

Renovate automatically detects Go modules by finding files matching /(^|/)go\.mod$/ and:

  1. Extracts existing dependencies from require statements
  2. Resolves each dependency’s source repository
  3. Checks for SemVer tags in the source repository
  4. Proposes pull requests when newer versions are available

go.mod and go.sum Handling

AspectBehavior
go.sum UpdatesAutomatically updated when dependencies change
go mod tidyOpt-in via postUpdateOptions: ["gomodTidy"]
VendoringAuto-detected via vendor/modules.txt, commits vendor/ changes
Major UpdatesRequires module path changes (e.g., /v2 suffix)

Indirect Dependencies

Default Behavior: Disabled to reduce noise

Enable with:

{
  "packageRules": [
    {
      "matchManagers": ["gomod"],
      "matchDepTypes": ["indirect"],
      "enabled": true
    }
  ]
}

Why it matters:

  • Hugo modules are often indirect dependencies
  • Enables updates to transitive dependencies with security patches
  • Critical for frameworks and libraries that others depend on

Hugo Module Support

Hugo uses Go modules for themes but has unique requirements:

Critical Configuration:

{
  "packageRules": [
    {
      "matchManagers": ["gomod"],
      "matchDepTypes": ["indirect"],
      "enabled": true
    }
  ]
}

Important: Do NOT use gomodTidy with Hugo modules - it will remove all dependencies since Hugo doesn’t import them as Go code. Hugo uses hugo mod tidy instead.

Post-Update Options

OptionCommandWhen to Use
gomodTidygo mod tidyStandard Go projects (NOT Hugo)
gomodUpdateImportPathsUses mod toolMajor version updates requiring import path changes
gomodTidyEgo mod tidy -eProjects with expected tidy errors
gomodMassagePre-processes replace directivesProjects with relative replace statements
goGeneratego generate ./...Projects with generated code

Recommended for Go projects:

{
  "postUpdateOptions": [
    "gomodTidy",
    "gomodUpdateImportPaths"
  ]
}

Go Toolchain Version Updates

Go 1.21+ introduced separate go and toolchain directives:

DirectiveMeaningDefault Renovate Behavior
go 1.22Minimum compatible versionDoes NOT update (opt-in)
toolchain go1.22.5Exact toolchain versionUpdates automatically

To enable go directive updates:

{
  "packageRules": [
    {
      "matchDatasources": ["golang-version"],
      "rangeStrategy": "bump"
    }
  ]
}

Dependency Grouping Strategies

Grouping reduces PR noise by combining related updates into single pull requests.

When to Group Dependencies

Group when:

  1. Same monorepo (OpenTelemetry, Kubernetes packages)
  2. Tightly coupled (react + react-dom)
  3. Framework components (all ESLint plugins)
  4. Noise reduction (type definitions, dev dependencies)

Keep separate when:

  1. Major updates (except monorepo packages)
  2. Different ecosystems (database driver + UI library)
  3. Different risk levels (production vs dev dependencies)
  4. Incompatible version requirements

Package Rules Structure

{
  "packageRules": [
    {
      // At least one match* property required
      "matchSourceUrls": ["https://github.com/open-telemetry/opentelemetry-go"],

      // At least one action property required
      "groupName": "OpenTelemetry packages",
      "automerge": true
    }
  ]
}

Match Logic:

  • Within a rule: ALL conditions must match (AND logic)
  • Exception: matchPackageNames and matchPackagePatterns are OR’d
  • Multiple rules: Last matching rule wins

Matching Strategies

StrategyUse CaseExample
matchSourceUrlsGitHub monoreposOpenTelemetry, Kubernetes
matchPackageNamesExact package namesgolang.org/x/** (glob pattern)
matchPackagePatternsRegex/glob patterns@types/*, ^angular
matchDatasourcesBy package managergo, npm, docker
matchUpdateTypesBy SemVer typemajor, minor, patch

Monorepo Grouping Patterns

Common monorepo grouping examples:

{
  "packageRules": [
    {
      "groupName": "opentelemetry-go and opentelemetry-go-contrib monorepos",
      "matchSourceUrls": [
        "https://github.com/open-telemetry/opentelemetry-go",
        "https://github.com/open-telemetry/opentelemetry-go-contrib"
      ],
      "matchUpdateTypes": ["digest", "patch", "minor", "major"]
    },
    {
      "groupName": "golang.org/x monorepo",
      "matchDatasources": ["go"],
      "matchPackageNames": ["golang.org/x/**"],
      "matchUpdateTypes": ["digest", "patch", "minor", "major"]
    }
  ]
}

Benefits:

  • Ensures compatible versions across related packages
  • Single PR for coordinated releases
  • Reduces merge conflicts
  • Easier testing of combined updates

Update Type Filtering

Available types:

TypeExampleRisk Level
lockFileMaintenanceLock file refreshLowest
patch1.0.0 → 1.0.1Very low
minor1.0.0 → 1.1.0Low
major1.0.0 → 2.0.0Higher
digestDocker SHA updatesLow

Common pattern:

{
  "packageRules": [
    {
      "matchUpdateTypes": ["minor", "patch"],
      "automerge": true
    },
    {
      "matchUpdateTypes": ["major"],
      "dependencyDashboardApproval": true
    }
  ]
}

Automerge Capabilities

Automerge drastically decreases the burden of handling dependency update PRs while maintaining safety through status checks and conditions.

Safety Mechanisms

Built-in protections:

  1. Status Check Requirements - All CI tests must pass
  2. Branch Up-to-Date - Branch must be current with base branch
  3. Conservative Defaults - Will not merge until all checks pass
  4. One at a Time - Only one PR per target branch per run

Prerequisites:

  • Comprehensive test coverage
  • Reliable CI/CD pipeline
  • Configured status checks in branch protection rules

Branch Protection Requirements

RequirementConfiguration
GitHub Status ChecksAt least one required check configured
Allow Auto-MergeMust be enabled in repository settings
Committer PermissionsRenovate bot must be allowed committer
Review BypassOptional: Add Renovate to bypass list

Platform Automerge vs Renovate Automerge

AspectPlatform AutomergeRenovate Automerge
SpeedFaster (1 run)Slower (2+ runs)
ScheduleCannot honor automergeScheduleCan honor schedule
ControlPlatform manages mergeRenovate manages merge
ConfigurationplatformAutomerge: trueplatformAutomerge: false

Stability Days and Confidence

Stability Days (minimumReleaseAge):

{
  "minimumReleaseAge": "14 days"
}

Purpose: Delays updates to let community identify issues first

Security Best Practice: Set to “14 days” for third-party dependencies to allow time for malicious packages to be detected and removed from registries.

Merge Confidence (requires Mend.io API key):

LevelMeaningFactors
Very HighExcellent adoption, age, CI statusRecommended for automerge
HighGood adoption and ageSafe for patch automerge
NeutralAverage confidenceManual review recommended
LowLimited dataRequires approval

Major vs Non-Major Strategy

Recommended approach:

{
  "packageRules": [
    {
      "description": "Automerge non-major updates",
      "matchUpdateTypes": ["minor", "patch"],
      "automerge": true
    },
    {
      "description": "Require approval for major updates",
      "matchUpdateTypes": ["major"],
      "dependencyDashboardApproval": true
    }
  ]
}

Rationale:

  • Minor and patch shouldn’t have breaking changes (per SemVer)
  • Major updates may require code changes
  • Pre-1.0.0 dependencies can break at any time

Exclude pre-1.0.0:

{
  "matchUpdateTypes": ["minor", "patch"],
  "matchCurrentVersion": "!/^0/",
  "automerge": true
}

Scheduling Options

Automerge Schedule:

{
  "schedule": ["before 4am"],
  "automergeSchedule": ["after 11pm", "before 4am"],
  "platformAutomerge": false
}

Schedule presets:

  • schedule:daily - Daily before 4 AM
  • schedule:weekly - Monday mornings before 4 AM
  • schedule:monthly - First day of month before 4 AM

Timezone configuration:

{
  "timezone": "America/New_York"
}

Risks and Mitigations

RiskMitigation
Supply chain attacksUse minimumReleaseAge: "14 days"
Inadequate test coverageEnsure comprehensive CI before enabling
Missing status checksConfigure at least one required check
Bypassed reviewsLimit to devDependencies and patch updates

Real-World Examples

Example 1: k8sgpt-ai Project

Configuration highlights:

{
  "extends": ["config:base"],
  "postUpdateOptions": ["gomodTidy", "gomodMassage"],
  "packageRules": [
    {
      "groupName": "kubernetes packages",
      "matchPackageNames": ["k8s.io/**", "sigs.k8s.io/**"]
    },
    {
      "matchUpdateTypes": ["minor", "patch"],
      "automerge": true
    }
  ]
}

Key patterns:

  • Groups all Kubernetes packages together
  • Enables automerge for non-major updates
  • Uses gomodMassage for relative replace directives

Example 2: SAP dns-masquerading-operator

Version constraint handling:

{
  "postUpdateOptions": ["gomodUpdateImportPaths"],
  "packageRules": [
    {
      "matchDatasources": ["golang-version"],
      "rangeStrategy": "bump"
    },
    {
      "matchPackageNames": ["k8s.io/client-go"],
      "allowedVersions": "<1.4.0"
    }
  ]
}

Key patterns:

  • Configures Go version bumping
  • Restricts specific package versions
  • Updates import paths automatically

Example 3: Multi-Workspace Monorepo

From Jamie Tanna’s blog:

{
  "extends": ["config:best-practices"],
  "packageRules": [
    {
      "matchFileNames": ["projects/internal/**"],
      "matchManagers": ["gomod"],
      "groupName": "Internal services dependencies",
      "schedule": ["before 6am on Monday"]
    },
    {
      "matchFileNames": ["projects/internal/apk-builder/**"],
      "reviewers": ["team:platform"]
    }
  ]
}

Key patterns:

  • Per-directory configuration
  • Team-based reviewer assignment
  • Service-specific scheduling

Hugo-Specific Configuration

Basic Hugo module setup:

{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": ["config:base"],
  "ignorePaths": ["exampleSite/**"],
  "packageRules": [
    {
      "matchManagers": ["gomod"],
      "matchDepTypes": ["indirect"],
      "enabled": true
    }
  ]
}

Ignoring specific Hugo themes:

{
  "packageRules": [
    {
      "description": "Disable Docsy theme updates - customized theme",
      "matchPackageNames": ["github.com/google/docsy"],
      "matchManagers": ["gomod"],
      "enabled": false
    }
  ]
}

Complete Hugo documentation site example:

{
  "extends": ["config:best-practices"],
  "ignorePaths": ["docs/exampleSite/**"],
  "packageRules": [
    {
      "description": "Enable Hugo module updates (indirect deps)",
      "matchManagers": ["gomod"],
      "matchDepTypes": ["indirect"],
      "matchFileNames": ["docs/go.mod"],
      "enabled": true
    },
    {
      "description": "Ignore Docsy theme - customized",
      "matchPackageNames": ["github.com/google/docsy"],
      "enabled": false
    },
    {
      "description": "Automerge minor Hugo module updates",
      "matchFileNames": ["docs/go.mod"],
      "matchUpdateTypes": ["minor", "patch"],
      "automerge": true
    }
  ]
}

Best Practices and Recommendations

Core Configuration Patterns

Based on research findings, these are recommended configuration patterns for Go projects:

1. Add Stability Days for Security

{
  "minimumReleaseAge": "7 days"
}

Benefits:

  • Gives community time to identify issues in new releases
  • Reduces risk of incorporating compromised packages
  • Can be overridden for security patches

For critical production systems, consider:

{
  "minimumReleaseAge": "14 days"
}

2. Exclude Pre-1.0.0 from Automerge

{
  "packageRules": [
    {
      "description": "Automerge non-major updates (excluding pre-1.0.0)",
      "matchUpdateTypes": ["minor", "patch"],
      "matchCurrentVersion": "!/^0/",
      "automerge": true
    }
  ]
}

Rationale: Pre-1.0.0 dependencies can introduce breaking changes in minor/patch updates per SemVer specification.

3. Require Dashboard Approval for Major Updates

{
  "packageRules": [
    {
      "description": "Require approval for major updates",
      "matchUpdateTypes": ["major"],
      "dependencyDashboardApproval": true
    }
  ]
}

Benefits:

  • Major updates appear in Dependency Dashboard for manual review
  • Prevents unexpected breaking changes
  • Allows batch approval of major updates

4. Add Explicit Automerge Schedule

{
  "automergeSchedule": ["after 11pm", "before 4am"],
  "platformAutomerge": false
}

Benefits:

  • More restrictive than PR creation schedule
  • Reduces risk of disruption during work hours
  • Note: Requires platformAutomerge: false to be honored

5. Add Timezone Clarity

{
  "timezone": "UTC"
}

Benefits:

  • Makes timezone explicit in configuration
  • Adjust to team’s timezone if needed (e.g., “America/New_York”)

6. Bypass Stability Days for Security Patches

{
  "packageRules": [
    {
      "description": "Skip stability days for security patches",
      "matchUpdateTypes": ["patch"],
      "matchPatchVersions": "security",
      "minimumReleaseAge": "0 days",
      "automerge": true
    }
  ]
}

Benefits:

  • Security patches merge immediately
  • Non-security patches wait for stability period

Comprehensive Configuration Example

A well-balanced configuration combining security, automation, and stability:

{
  "extends": ["config:best-practices"],
  "osvVulnerabilityAlerts": true,
  "minimumReleaseAge": "7 days",
  "timezone": "UTC",
  "schedule": ["before 4am"],
  "automergeSchedule": ["after 11pm", "before 4am"],
  "platformAutomerge": false,
  "baseBranchPatterns": ["main"],
  "labels": ["dependencies"],
  "packageRules": [
    {
      "description": "Automerge non-major updates (excluding pre-1.0.0)",
      "matchUpdateTypes": ["minor", "patch"],
      "matchCurrentVersion": "!/^0/",
      "automerge": true
    },
    {
      "description": "Require approval for major updates",
      "matchUpdateTypes": ["major"],
      "dependencyDashboardApproval": true
    },
    {
      "description": "Skip stability days for security patches",
      "matchUpdateTypes": ["patch"],
      "matchPatchVersions": "security",
      "minimumReleaseAge": "0 days",
      "automerge": true
    },
    {
      "matchManagers": ["gomod"],
      "matchDepTypes": ["indirect"],
      "enabled": true
    },
    {
      "groupName": "opentelemetry-go and opentelemetry-go-contrib monorepos",
      "matchSourceUrls": [
        "https://github.com/open-telemetry/opentelemetry-go",
        "https://github.com/open-telemetry/opentelemetry-go-contrib"
      ],
      "matchUpdateTypes": ["digest", "patch", "minor", "major"]
    },
    {
      "groupName": "google.golang.org/genproto/googleapis monorepo",
      "matchDatasources": ["go"],
      "matchPackageNames": ["google.golang.org/genproto/googleapis/**"],
      "matchUpdateTypes": ["digest", "patch", "minor", "major"]
    },
    {
      "groupName": "golang.org/x monorepo",
      "matchDatasources": ["go"],
      "matchPackageNames": ["golang.org/x/**"],
      "matchUpdateTypes": ["digest", "patch", "minor", "major"]
    }
  ],
  "postUpdateOptions": ["gomodTidy", "gomodUpdateImportPaths"]
}

General Best Practices

  1. Start Conservative - Begin with non-major automerge only, expand as confidence grows

  2. Group Thoughtfully - Monorepo packages should be grouped, but avoid over-grouping unrelated dependencies

  3. Monitor Automerge Results - Track success rates and adjust configuration based on actual outcomes

  4. Use Stability Days - For production systems, 7-14 day delays add valuable safety against supply chain attacks

  5. Enable Indirect Dependencies - Critical for Go projects, especially those with Hugo modules or library dependencies

  6. Document Hugo Module Handling - Ensure contributors understand why gomodTidy is disabled for Hugo projects

When NOT to Use Automerge

Consider disabling automerge for:

  1. Core Framework Dependencies

    • Major version updates of base frameworks
    • SDK updates that may affect API compatibility
    • Router or server framework major versions
  2. gRPC and Protobuf

    • Major version updates can break API compatibility
    • Requires manual testing across service boundaries
  3. Custom or Forked Dependencies

    • Customized themes or libraries
    • Internal forks requiring careful version management
  4. Pre-1.0.0 Dependencies

    • Breaking changes can occur in minor/patch versions
    • Requires manual review for each update

Sources

Official Renovate Documentation

Mend/WhiteSource Resources

Community Resources

Real-World Examples


Conclusion

Renovate provides powerful automation for managing dependencies in Go projects with comprehensive support for:

  • Security-first approach via OSV vulnerability scanning and configurable safety mechanisms
  • Intelligent automation through monorepo grouping and selective automerge
  • Developer-friendly scheduling and automatic labeling
  • Go-specific features including indirect dependency handling, major version path updates, and Hugo module support

The combination of stability days, pre-1.0.0 exclusions, dashboard approval for major updates, and thoughtful automerge policies creates a balanced approach between automation and safety.

Renovate’s Go support is comprehensive, with special handling for Hugo modules, major version upgrades, and post-update cleanup making it well-suited for modern Go development workflows.