Skip to content

Migrate to github.com/gobwas/glob v1.0.0 (glob.Glob replaced by *glob.Pattern) #15928

Description

@mjnowen

Component(s)

confmap

Is your feature request related to a problem? Please describe.

github.com/gobwas/glob has released v1.0.0, which is an API-breaking change
published without a major version suffix. The module path is still
github.com/gobwas/glob, not .../v2, so minimal version selection treats it
as an ordinary upgrade and confmap stops compiling as soon as anything in the
build graph selects it.

The breaking change: the glob.Glob interface is gone. Compile and
MustCompile now return the concrete *glob.Pattern, and malformed patterns are
reported as *glob.SyntaxError.

v0.2.3:

type Glob interface {
    Match(string) bool
}

func Compile(pattern string, separators ...rune) (Glob, error)
func MustCompile(pattern string, separators ...rune) Glob

v1.0.0:

type Pattern struct { /* ... */ }

func (p *Pattern) Match(s string) bool
func (p *Pattern) String() string
func (p *Pattern) Separators() []rune

func Compile(pattern string, separators ...rune) (*Pattern, error)
func MustCompile(pattern string, separators ...rune) *Pattern

confmap pins v0.2.3 and refers to the removed interface in one file,
confmap/internal/merge.go (v1.66.0):

  • line 25, var globs []glob.Glob
  • line 63, func isMatch(key string, globs []glob.Glob) bool

Steps to reproduce

From any module that depends on confmap:

go get github.com/gobwas/glob@v1.0.0
go build ./...

Result:

go.opentelemetry.io/collector/confmap/internal/merge.go:25:19: undefined: glob.Glob
go.opentelemetry.io/collector/confmap/internal/merge.go:63:39: undefined: glob.Glob

Because confmap is a transitive dependency of essentially every collector
distribution, the failure appears in packages the user does not own, and
golangci-lint reports it as a typecheck issue rather than a dependency
problem, which makes it hard to diagnose:

could not import go.opentelemetry.io/collector/confmap/confmaptest
  (.../confmap@v1.66.0/confmaptest/configtest.go:14:2: could not import
   go.opentelemetry.io/collector/confmap
   (.../confmap.go:9:2: could not import
    go.opentelemetry.io/collector/confmap/internal
    (-: # go.opentelemetry.io/collector/confmap/internal
    .../internal/merge.go:25:19: undefined: glob.Glob
    .../internal/merge.go:63:39: undefined: glob.Glob))) (typecheck)

This is easy to hit unintentionally. A downstream go get -t -u ./... in the
main module adds github.com/gobwas/glob v1.0.0 // indirect even though every
other module in the graph requires v0.2.3, and go mod graph then shows the
main module as the sole requirer of the incompatible version.

Describe the solution you'd like

Update confmap to github.com/gobwas/glob v1.0.0 and switch the two
references to the concrete pointer type:

--- a/confmap/internal/merge.go
+++ b/confmap/internal/merge.go
@@
-	var globs []glob.Glob
+	var globs []*glob.Pattern
 	for _, p := range patterns {
 		if g, err := glob.Compile(p); err == nil {
 			globs = append(globs, g)
 		}
 	}
@@
-func isMatch(key string, globs []glob.Glob) bool {
+func isMatch(key string, globs []*glob.Pattern) bool {

Nothing else should be required. Match(string) bool keeps the same signature
and semantics, and confmap already declares go 1.26.0, well above the
go 1.22.0 that glob v1.0.0 requires.

Two optional follow-ups in the same file, if maintainers want them:

  1. The three patterns (service::extensions, service::**::receivers,
    service::**::exporters) are compile-time constants, but mergeAppend
    recompiles them on every merge. They could be hoisted to package-level
    glob.MustCompile values, which also removes the silently swallowed
    err == nil check that currently drops a pattern from the match set if it
    ever fails to compile.
  2. glob v1.0.0 reports compile failures as *glob.SyntaxError with a byte
    offset, so if the error is ever surfaced rather than ignored, the message can
    point at the offending position in the pattern.

Describe alternatives you've considered

  • Leaving the pin at v0.2.3. This works in CI today, but every consumer that
    runs go get -u gets a broken build in a dependency they did not touch. There
    is no retract and no /v2 path upstream to prevent the selection.
  • A replace github.com/gobwas/glob => github.com/gobwas/glob v0.2.3 in
    downstream go.mod files. This is the workaround consumers need right now,
    but it does not belong in published modules and is not discoverable from the
    error message.

Additional context

  • merge.go is only reached when the confmap.enableMergeAppendOption feature
    gate is enabled (Conf.Merge in confmap/internal/conf.go:100), but the
    package fails to compile regardless of the gate, so the gate does not
    limit the blast radius.

  • The same migration is needed in contrib, in
    pkg/ottl/ottlfuncs/func_replace_all_matches.go and
    pkg/ottl/ottlfuncs/func_replace_match.go, which are the only direct users of
    gobwas/glob there. Both repos need the change before consumers can upgrade
    end to end.

  • glob v0.2.3 predates Go modules and ships no go.mod, so go get -u gives
    no signal that v1.0.0 is breaking.

Tip

No response

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestneeds triageNew item requiring triage

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions