Skip to content

feat: support DROP sentinel in gomod replace to remove orphaned requires#1086

Open
chrischangcode wants to merge 1 commit into
project-dalec:mainfrom
chrischangcode:feat/gomod-drop-require
Open

feat: support DROP sentinel in gomod replace to remove orphaned requires#1086
chrischangcode wants to merge 1 commit into
project-dalec:mainfrom
chrischangcode:feat/gomod-drop-require

Conversation

@chrischangcode

@chrischangcode chrischangcode commented Jun 10, 2026

Copy link
Copy Markdown

Problem

When a Go sub-module gets absorbed into its parent module in a newer version, upgrading the parent via a replace directive leaves an orphaned require in go.mod that can no longer be resolved.

Real-world example: google.golang.org/grpc/stats/opentelemetry was a separate module (with its own go.mod) up through grpc v1.68.x. Starting with grpc v1.79.0, it was merged into the main google.golang.org/grpc module — the code still exists as a package, but there is no longer a separate go.mod at that path.

When a CVE fix upgrades google.golang.org/grpc to v1.79.3 via a replace directive, go mod tidy fails because it cannot resolve the orphaned require google.golang.org/grpc/stats/opentelemetry v0.0.0-... — no module exists at that path in the newer version.

Current workaround

Spec authors must create a source patch that adds a stub go.mod file and a local directory replace pointing to it. This works but adds maintenance burden.

See Azure/dalec-build-defs#9887 for an example.

Solution

Add a dedicated Drop field to GomodEdits that emits go mod edit -droprequire=<module> arguments. The subsequent go mod tidy then cleanly resolves the dependency graph.

Spec syntax

sources:
  kube-state-metrics:
    generate:
      - gomod:
          edits:
            replace:
              - google.golang.org/grpc => google.golang.org/grpc@v1.79.3
            drop:
              - google.golang.org/grpc/stats/opentelemetry

Implementation

  • spec.go: Added Drop []string field to GomodEdits struct with documentation.
  • preprocess.go: Updated gomodEditArgs() to iterate Drop entries and emit -droprequire= arguments.
  • generator_gomod_test.go: Added tests covering: basic drop, multiple drops, mixed drop+replace, empty-path error, and nil-edits passthrough.
  • gomod-patch.sh: No changes needed — the shell script already iterates edit args line-by-line and passes each to go mod edit, which natively supports -droprequire=.

Why a dedicated Drop field?

Per reviewer feedback, a dedicated field is preferable to overloading Replace with a sentinel value:

  • Clear intentdrop: is unambiguous; readers don't need to know about magic values
  • Type-safe[]string for module paths, no struct needed
  • No collision risk — doesn't repurpose an existing field's semantics
  • Validates naturally — empty strings are the only invalid input

Verified

Tested locally against kubernetes/kube-state-metrics v2.16.0:

go mod edit \
  -replace google.golang.org/grpc=google.golang.org/grpc@v1.79.3 \
  -droprequire google.golang.org/grpc/stats/opentelemetry
go mod tidy   # succeeds
go build ./...  # succeeds

All existing tests pass (go test ./...).

@chrischangcode chrischangcode force-pushed the feat/gomod-drop-require branch from 0069362 to aa75591 Compare June 10, 2026 15:07
@chrischangcode chrischangcode marked this pull request as ready for review June 11, 2026 17:41
Copilot AI review requested due to automatic review settings June 11, 2026 17:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR adds support for dropping module requirements from go.mod via the existing replace directive mechanism, using a special sentinel value "DROP" as the replacement target to convert entries into -droprequire= arguments for go mod edit.

Changes:

  • Introduces a DropRequireSentinel constant and logic in gomodEditArgs to convert replace directives targeting "DROP" into -droprequire= arguments.
  • Updates documentation for gomodEditArgs to describe the new drop behavior.
  • Adds comprehensive test cases covering the drop-require feature, including case-insensitivity, mixed scenarios, and error handling.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
preprocess.go Adds the DropRequireSentinel constant, updates gomodEditArgs to handle the drop sentinel, and adds documentation.
generator_gomod_test.go Adds table-driven tests for the new drop-require functionality.

Comment thread preprocess.go Outdated
Comment thread preprocess.go Outdated
Comment thread preprocess.go Outdated
@cpuguy83

Copy link
Copy Markdown
Collaborator

Why isn't go mod tidy dropping this automatically if the module isn't required anymore?

@cpuguy83

Copy link
Copy Markdown
Collaborator

Ok I think I understand now.
I think it would be best to movet his to a Drop field rather than making Replace do it.

@chrischangcode

Copy link
Copy Markdown
Author

Ok I think I understand now. I think it would be best to movet his to a Drop field rather than making Replace do it.

Agreed! But yeah upstream go.mod required the deprecated package. https://github.com/kubernetes/kube-state-metrics/blob/release-2.16/go.mod#L241

I also think it'd be possible to add logic to calculate the replaces with more context of the overall dependency graph for more successful PRs.

https://github.com/Azure/dalec-build-defs/issues/9801

@chrischangcode chrischangcode force-pushed the feat/gomod-drop-require branch from aa75591 to 70cf052 Compare June 15, 2026 20:09
Add a dedicated Drop field to GomodEdits that emits go mod edit -droprequire
arguments. This handles cases where a sub-module has been absorbed into its
parent module in a newer version (e.g. google.golang.org/grpc/stats/opentelemetry
merged into google.golang.org/grpc at v1.79.0).

Spec syntax:
  sources:
    my-source:
      generate:
        - gomod:
            edits:
              replace:
                - google.golang.org/grpc => google.golang.org/grpc@v1.79.3
              drop:
                - google.golang.org/grpc/stats/opentelemetry

Addresses reviewer feedback to use a dedicated field rather than overloading
the Replace field with a DROP sentinel value.

Signed-off-by: Chris Chang <chrischang@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@chrischangcode chrischangcode force-pushed the feat/gomod-drop-require branch from 70cf052 to ecedb84 Compare June 15, 2026 20:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants