Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 7 additions & 20 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,10 @@ updates:
reviewers:
- "rjmurillo"
- "mattkotsenas"
- package-ecosystem: nuget
directory: "/"
schedule:
interval: "daily"
time: "08:30"
ignore:
# Microsoft.CodeAnalysis.* packages defined in the analyzer project can impact compatibility with older SDKs for
# our users. We don't want to bump these without first considering the user impact.
#
# We don't wildcard Microsoft.CodeAnalysis.* here though, as there are testing libraries and analyzers that
# can be upgraded without impacting our users.
- dependency-name: "Microsoft.CodeAnalysis.CSharp"
- dependency-name: "Microsoft.CodeAnalysis.CSharp.Workspaces"
- dependency-name: "Microsoft.CodeAnalysis.Common"
- dependency-name: "Microsoft.CodeAnalysis.Workspaces.Common"
# Analyzer-shipped BCL packages must match minimum supported SDK host.
# See: https://github.com/rjmurillo/moq.analyzers/issues/850
- dependency-name: "System.Collections.Immutable"
- dependency-name: "System.Reflection.Metadata"
- dependency-name: "Microsoft.CodeAnalysis.AnalyzerUtilities"
# NuGet dependency management is handled by Renovate (see renovate.json).
# Dependabot NuGet PRs were disabled because:
# 1. PR titles use "Bump X from A to B" format, which fails the required
# "Validate PR title" check (conventional commits required).
# 2. Both bots created duplicate PRs for every package update.
# 3. Renovate supports better grouping, automerge rules, and conventional
# commit formatting out of the box.
25 changes: 0 additions & 25 deletions .github/workflows/auto-approve-and-merge-renovate.yml

This file was deleted.

55 changes: 36 additions & 19 deletions .github/workflows/dependabot-approve-and-auto-merge.yml
Original file line number Diff line number Diff line change
@@ -1,33 +1,50 @@
name: Dependabot Pull Request Approve and Merge
on: pull_request_target
permissions:
pull-requests: write
contents: write
name: Auto-Approve and Auto-Merge Bot PRs
on:
pull_request_target:
types: [opened, synchronize, reopened]

Comment thread
rjmurillo marked this conversation as resolved.
jobs:
dependabot:
name: Dependabot (GitHub Actions)
permissions:
contents: write
pull-requests: write
runs-on: ubuntu-24.04-arm
# Checking the actor will prevent your Action run failing on non-Dependabot
# PRs but also ensures that it only does work for Dependabot PRs.
if: ${{ github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]' }}
if: github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]'
steps:
# This first step will fail if there's no metadata and so the approval
# will not occur.
- name: Dependabot metadata
- name: Fetch metadata
id: dependabot-metadata
uses: dependabot/fetch-metadata@v2.5.0
with:
github-token: "${{ secrets.GH_ACTIONS_PR_WRITE }}"
# Here the PR gets approved.
- name: Approve a PR

- name: Approve PR
run: gh pr review --approve "$PR_URL"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GITHUB_TOKEN: ${{ secrets.GH_ACTIONS_PR_WRITE }}
# Finally, this sets the PR to allow auto-merging for patch and minor
# updates if all checks pass
- name: Enable auto-merge for Dependabot PRs
if: ${{ steps.dependabot-metadata.outputs.update-type != 'version-update:semver-major' }}
GH_TOKEN: ${{ secrets.GH_ACTIONS_PR_WRITE }}

- name: Enable auto-merge for non-major updates
if: steps.dependabot-metadata.outputs.update-type != 'version-update:semver-major'
run: gh pr merge --auto --squash "$PR_URL"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GITHUB_TOKEN: ${{ secrets.GH_ACTIONS_PR_WRITE }}
GH_TOKEN: ${{ secrets.GH_ACTIONS_PR_WRITE }}

renovate:
name: Renovate
permissions:
pull-requests: write
runs-on: ubuntu-24.04-arm
if: github.actor == 'renovate[bot]'
steps:
# Renovate handles auto-merge decisions via platformAutomerge and
# per-package automerge rules in renovate.json. This workflow only
# provides the required approval. Packages with automerge: false
# (analyzer-compat, benchmark-tooling) will not have auto-merge
# enabled by Renovate, so they require manual merge after review.
- name: Approve PR
run: gh pr review --approve "$PR_URL"
env:
GH_TOKEN: ${{ secrets.GH_ACTIONS_PR_WRITE }}
PR_URL: ${{ github.event.pull_request.html_url }}
Comment thread
rjmurillo marked this conversation as resolved.
15 changes: 0 additions & 15 deletions .github/workflows/dependabot-auto-approve.yml

This file was deleted.

22 changes: 0 additions & 22 deletions .github/workflows/dependabot-auto-merge.yml

This file was deleted.

119 changes: 119 additions & 0 deletions docs/dependency-management.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Dependency Management

This project uses **Renovate** as the primary dependency update bot. Dependabot is retained only for GitHub Actions updates.

Comment thread
rjmurillo marked this conversation as resolved.
## Package Categories

Dependencies fall into distinct categories with different upgrade policies.

### Shipped (in analyzer nupkg) - EXTREME CAUTION

These packages are bundled in the analyzer NuGet package and run inside the **user's** compiler host (Visual Studio, dotnet CLI). Version constraints are critical because users may run older SDKs.

| Package | Central Pin | Constraint |
|---------|------------|------------|
| Microsoft.CodeAnalysis.CSharp | 4.8 | Minimum supported VS/SDK version |
| Microsoft.CodeAnalysis.CSharp.Workspaces | 4.8 | Same as above |
| Microsoft.CodeAnalysis.AnalyzerUtilities | 3.3.4 | Must reference SCI <= 8.0.0.0 |
| System.Collections.Immutable | 8.0.0 | Must not exceed .NET 8 SDK host assembly version |
| System.Formats.Asn1 | 10.0.0 | Transitive pin in shipped section; flagged for host compat review |
| System.Reflection.Metadata | (transitive, no central pin) | Must not exceed .NET 8 SDK host assembly version |

**Why this matters:** In v0.4.0, a transitive dependency bump pushed SCI to 10.0.0.0, causing CS8032 assembly load failures for every user on .NET 8 SDK. See [issue #850](https://github.com/rjmurillo/moq.analyzers/issues/850).

**Upgrade policy:**

- `Microsoft.CodeAnalysis.*` core packages are **ignored** in the Renovate config (`ignoreDeps`). Dependabot does not manage NuGet packages. Update manually when raising the minimum supported SDK version.
- `System.Collections.Immutable`, `System.Formats.Asn1`, `System.Reflection.Metadata`, and `AnalyzerUtilities` have `automerge: false` and the `analyzer-compat` label. Every update requires manual validation that assembly versions stay within host bounds.
- The `ValidateAnalyzerHostCompatibility` MSBuild target and `AnalyzerAssemblyCompatibilityTests` enforce this at build and test time.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Comment thread
coderabbitai[bot] marked this conversation as resolved.
### Build-time Code Analysis - SAFE

These run only during builds and are not shipped. Updates do not affect end users. See [`build/targets/codeanalysis/Packages.props`](../build/targets/codeanalysis/Packages.props) for the full list.

Representative packages:

| Package | Location |
|---------|----------|
| Meziantou.Analyzer | build/targets/codeanalysis/Packages.props |
| SonarAnalyzer.CSharp | build/targets/codeanalysis/Packages.props |
| Roslynator.Analyzers | build/targets/codeanalysis/Packages.props |
| StyleCop.Analyzers | build/targets/codeanalysis/Packages.props |
| Microsoft.CodeAnalysis.Analyzers | build/targets/codeanalysis/Packages.props |

**Upgrade policy:** Automerge minor/patch. Major versions may introduce new warnings that break the build (warnings are errors). Review new rules before merging major bumps.

### Test Framework - SAFE

Test-only dependencies with no shipped impact. See [`build/targets/tests/Packages.props`](../build/targets/tests/Packages.props) for the full list.

Representative packages:

| Package | Location |
|---------|----------|
| Verify.Xunit | build/targets/tests/Packages.props |
| xunit | build/targets/tests/Packages.props |
| Microsoft.NET.Test.Sdk | build/targets/tests/Packages.props |
| coverlet.msbuild | build/targets/tests/Packages.props |

**Upgrade policy:** Automerge minor/patch. CI validates compatibility.

### Benchmark Tooling - COORDINATED

BenchmarkDotNet and Perfolizer have intertwined version requirements. BenchmarkDotNet declares a minimum Perfolizer version and a minimum Microsoft.CodeAnalysis.CSharp version.

| Package | Central Pin | Notes |
|---------|------------|-------|
| BenchmarkDotNet | Directory.Packages.props | Transitive dep on Perfolizer and Roslyn |
| Perfolizer | Directory.Packages.props | Used directly by PerfDiff tool |

**Upgrade policy:** Grouped in Renovate as `benchmark-tooling` with `automerge: false`. Both packages must be updated together. The benchmark project uses `VersionOverride` for packages whose central pins are constrained by shipped analyzer compatibility (e.g., `System.Collections.Immutable`).

### PerfDiff Tool - SPECIAL HANDLING

The PerfDiff tool (`src/tools/PerfDiff/`) uses System.CommandLine, which had breaking API changes between beta and stable releases. The `IConsole` interface was removed in 2.0.3.

| Package | Status |
|---------|--------|
| System.CommandLine | **Disabled** in Renovate until PerfDiff is rewritten |
| System.CommandLine.Rendering | **Disabled** (folded into main package in stable release) |

**Why disabled:** The perf CI check builds PerfDiff on-demand. It is excluded from the normal build/test matrix. Updates that break PerfDiff only surface as `perf` check failures, which are a required status check.

### Build Infrastructure - MODERATE CAUTION

| Package | Location | Notes |
|---------|----------|-------|
| Polyfill | build/targets/compiler/Packages.props | Compiler polyfills |
| DotNet.ReproducibleBuilds | build/targets/reproducible/Packages.props | Build reproducibility |
| DotNet.ReproducibleBuilds.Isolated | global.json (msbuild-sdks) | MSBuild SDK isolation |
| Nerdbank.GitVersioning | Directory.Packages.props | Version calculation |

**Upgrade policy:** Automerge minor/patch for stable versions. ReproducibleBuilds and Isolated should be updated together (same release cadence).

## Configuration Files

| File | Purpose |
|------|---------|
| `renovate.json` | Renovate bot configuration (primary dependency bot) |
| `.github/dependabot.yml` | Dependabot configuration (GitHub Actions only) |
| `Directory.Packages.props` | Central package version management |
| `build/targets/*/Packages.props` | Category-specific package versions |

## VersionOverride Pattern

Non-shipped projects (benchmarks, PerfDiff) that need higher versions of centrally pinned packages use `VersionOverride` in their `.csproj`:

```xml
<!-- Benchmarks are not shipped. Allow higher SCI for TraceEvent dependency. -->
<PackageReference Include="System.Collections.Immutable" VersionOverride="10.0.0" />
```

This allows the central pin (8.0.0) to protect shipped analyzer DLLs while letting tools use newer versions.

## Workflow

A single consolidated workflow (`.github/workflows/dependabot-approve-and-auto-merge.yml`) handles auto-approval for both Dependabot and Renovate PRs.

- **Dependabot** (GitHub Actions only): The workflow approves the PR and enables auto-merge for non-major updates. Major version gating uses `dependabot/fetch-metadata` output.
Comment thread
rjmurillo marked this conversation as resolved.
- **Renovate** (NuGet): The workflow only approves the PR. Auto-merge is controlled entirely by Renovate via `platformAutomerge: true` and per-package `automerge` rules in `renovate.json`. Packages with `automerge: false` (e.g., `analyzer-compat`, `benchmark-tooling`) require manual merge after review.
Comment thread
rjmurillo marked this conversation as resolved.
Comment thread
rjmurillo marked this conversation as resolved.
30 changes: 28 additions & 2 deletions renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
"extends": [
"config:recommended"
],
Comment thread
rjmurillo marked this conversation as resolved.
"enabledManagers": ["nuget"],
"ignoreDeps": [
"Microsoft.CodeAnalysis.CSharp",
"Microsoft.CodeAnalysis.CSharp.Workspaces",
"Microsoft.CodeAnalysis.Common",
"Microsoft.CodeAnalysis.Workspaces.Common"
],
"packageRules": [
{
"description": "Automerge non-major updates for development dependencies",
Expand All @@ -22,14 +29,33 @@
"automerge": true
},
{
"description": "Analyzer-shipped BCL packages must match minimum supported SDK host. Manual review required.",
"description": "Analyzer-shipped BCL packages must match minimum supported SDK host. Manual review required. See: https://github.com/rjmurillo/moq.analyzers/issues/850",
"matchPackageNames": [
"System.Collections.Immutable",
"System.Formats.Asn1",
"System.Reflection.Metadata",
"Microsoft.CodeAnalysis.AnalyzerUtilities"
],
"automerge": false,
"labels": ["analyzer-compat"]
"addLabels": ["analyzer-compat"]
Comment thread
rjmurillo marked this conversation as resolved.
},
{
"description": "Benchmark tooling (BenchmarkDotNet, Perfolizer) requires coordinated updates due to transitive dependency constraints. See docs/dependency-management.md.",
"matchPackageNames": [
"BenchmarkDotNet",
"Perfolizer"
],
"groupName": "benchmark-tooling",
"automerge": false,
"addLabels": ["benchmark-tooling"]
},
{
"description": "System.CommandLine requires PerfDiff code changes when updated. See: https://github.com/rjmurillo/moq.analyzers/issues/914",
"matchPackageNames": [
"System.CommandLine",
"System.CommandLine.Rendering"
],
"enabled": false
}
],
"platformAutomerge": true
Expand Down
Loading