diff --git a/go b/go index cbab448de1..a415314c0b 160000 --- a/go +++ b/go @@ -1 +1 @@ -Subproject commit cbab448de1c562e417b179d29f99758f4680630b +Subproject commit a415314c0bdec971ecd503471c804ec0208c6a2b diff --git a/patches/0001-Vendor-external-dependencies.patch b/patches/0001-Vendor-external-dependencies.patch index a8aa09ff43..d1d33b7842 100644 --- a/patches/0001-Vendor-external-dependencies.patch +++ b/patches/0001-Vendor-external-dependencies.patch @@ -18,8 +18,8 @@ Use a 'go' that was recently built by the current branch to ensure stable result .../go-infra/telemetry/config/config.json | 73 + .../go-infra/telemetry/counter/counter.go | 63 + .../telemetry/internal/appinsights/README.md | 12 + - .../telemetry/internal/appinsights/client.go | 169 ++ - .../internal/appinsights/inmemorychannel.go | 341 +++ + .../telemetry/internal/appinsights/client.go | 192 ++ + .../internal/appinsights/inmemorychannel.go | 349 +++ .../internal/contracts/contexttagkeys.go | 50 + .../internal/contracts/envelope.go | 123 + .../internal/contracts/response.go | 32 + @@ -27,10 +27,10 @@ Use a 'go' that was recently built by the current branch to ensure stable result .../telemetry/internal/appinsights/package.go | 13 + .../internal/appinsights/telemetrycontext.go | 44 + .../internal/appinsights/transmitter.go | 172 ++ - .../telemetry/internal/config/config.go | 63 + - .../telemetry/internal/telemetry/proginfo.go | 43 + + .../telemetry/internal/config/config.go | 78 + + .../telemetry/internal/telemetry/proginfo.go | 46 + .../telemetry/internal/telemetry/telemetry.go | 32 + - .../microsoft/go-infra/telemetry/telemetry.go | 125 + + .../microsoft/go-infra/telemetry/telemetry.go | 144 + src/cmd/vendor/modules.txt | 11 + src/crypto/internal/backend/deps_ignore.go | 22 + src/go.mod | 6 + @@ -269,7 +269,7 @@ Use a 'go' that was recently built by the current branch to ensure stable result .../internal/subtle/aliasing.go | 32 + .../internal/sysdll/sys_windows.go | 55 + src/vendor/modules.txt | 23 + - 261 files changed, 34032 insertions(+), 7 deletions(-) + 261 files changed, 34100 insertions(+), 7 deletions(-) create mode 100644 src/cmd/internal/telemetry/counter/deps_ignore.go create mode 100644 src/cmd/vendor/github.com/microsoft/go-infra/telemetry/LICENSE create mode 100644 src/cmd/vendor/github.com/microsoft/go-infra/telemetry/README.md @@ -525,28 +525,28 @@ Use a 'go' that was recently built by the current branch to ensure stable result create mode 100644 src/vendor/github.com/microsoft/go-crypto-winnative/internal/sysdll/sys_windows.go diff --git a/src/cmd/go.mod b/src/cmd/go.mod -index 3bc983397186a6..6556bfdbe3f0a4 100644 +index d15db1306b8e0b..d9db8bce7b540b 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -4,6 +4,8 @@ go 1.27 require ( github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 -+ github.com/microsoft/go-infra/telemetry v0.0.0-20260128082012-a1498e2b57dd ++ github.com/microsoft/go-infra/telemetry v0.0.0-20260407113113-dbc3015a3e9c + github.com/microsoft/go-infra/telemetry/config v0.0.0-20260128082012-a1498e2b57dd golang.org/x/arch v0.23.1-0.20260109160903-657d90bd6695 golang.org/x/build v0.0.0-20260122183339-3ba88df37c64 - golang.org/x/mod v0.32.0 + golang.org/x/mod v0.34.0 diff --git a/src/cmd/go.sum b/src/cmd/go.sum -index 224585feb6332d..ebf6a4c11e165e 100644 +index 23627773f00451..1b41d11a010450 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -4,6 +4,10 @@ github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/v github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= github.com/ianlancetaylor/demangle v0.0.0-20250417193237-f615e6bd150b h1:ogbOPx86mIhFy764gGkqnkFC8m5PJA7sPzlk9ppLVQA= github.com/ianlancetaylor/demangle v0.0.0-20250417193237-f615e6bd150b/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= -+github.com/microsoft/go-infra/telemetry v0.0.0-20260128082012-a1498e2b57dd h1:XE6HF7LVJ7/gD0mPMaIHJak0IFP683EUBzqx6+HxPu8= -+github.com/microsoft/go-infra/telemetry v0.0.0-20260128082012-a1498e2b57dd/go.mod h1:XQP+NhZgM1i1+asOSnAFPRzv2HhQibhk6k6FIllx8/Y= ++github.com/microsoft/go-infra/telemetry v0.0.0-20260407113113-dbc3015a3e9c h1:qOt7PpDH8k4734emsdXNylY79cY2qOHubeVP8Z/5iwI= ++github.com/microsoft/go-infra/telemetry v0.0.0-20260407113113-dbc3015a3e9c/go.mod h1:LxxLUDlqi1gwmGrnh1slAFqnEhZnKjn37MABZ6xJs44= +github.com/microsoft/go-infra/telemetry/config v0.0.0-20260128082012-a1498e2b57dd h1:vNA5PIOnvHfH7O9GUOZXKUakJpdE7+PzsF641y7Zly0= +github.com/microsoft/go-infra/telemetry/config v0.0.0-20260128082012-a1498e2b57dd/go.mod h1:t6u8QcO4tExYT4+NEB0XqR0ObiUvLe0D8ZpxFobGuA8= github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68= @@ -830,10 +830,10 @@ index 00000000000000..2e96890f60b871 +- Improve testing. diff --git a/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/internal/appinsights/client.go b/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/internal/appinsights/client.go new file mode 100644 -index 00000000000000..8e280f7c675a46 +index 00000000000000..c3dd88924fdcfa --- /dev/null +++ b/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/internal/appinsights/client.go -@@ -0,0 +1,169 @@ +@@ -0,0 +1,192 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + @@ -898,7 +898,9 @@ index 00000000000000..8e280f7c675a46 + +// init initializes the client. +// It is safe to call this method multiple times concurrently. -+func (c *Client) init() { ++// Returns true if the client is initialized after the call, false if init ++// is called after the client has been stopped or closed. ++func (c *Client) init() bool { + c.initOnce.Do(func() { + if c.InstrumentationKey == "" { + panic("instrumentation key is required") @@ -916,6 +918,17 @@ index 00000000000000..8e280f7c675a46 + go c.channel.acceptLoop() + c.initialized.Store(true) + }) ++ return c.initialized.Load() ++ ++} ++ ++// cancel tries to prevent the client from being initialized. ++// It is safe to call this method multiple times concurrently. ++// Returns true if the client is not initialized after the call, false if cancel ++// is called after the client has been initialized. ++func (c *Client) cancel() bool { ++ c.initOnce.Do(func() {}) ++ return !c.initialized.Load() +} + +func setupContext(instrumentationKey string, tags map[string]string) *telemetryContext { @@ -952,7 +965,9 @@ index 00000000000000..8e280f7c675a46 +// Close flushes and tears down the submission goroutine and closes internal channels. +// Waits until all pending telemetry items have been submitted. +func (c *Client) Close(ctx context.Context) { -+ if !c.initialized.Load() { ++ // Synchronize with any in-progress init so we don't miss ++ // a channel that is about to be created. ++ if c.cancel() { + return + } + c.channel.close(ctx) @@ -962,6 +977,11 @@ index 00000000000000..8e280f7c675a46 +// Any telemetry waiting to be sent is discarded. +// This is a more abrupt version of [Client.Close]. +func (c *Client) Stop() { ++ // Synchronize with any in-progress init so we don't miss ++ // a channel that is about to be created. ++ if c.cancel() { ++ return ++ } + c.channel.stop() +} + @@ -970,7 +990,10 @@ index 00000000000000..8e280f7c675a46 + if n == 0 || (c.UploadFilter != nil && !c.UploadFilter(data.Name)) { + return + } -+ c.init() ++ if !c.init() { ++ // Stop or Close consumed initOnce before init could run. ++ return ++ } + ev := c.context.envelop(data) + if err := ev.Sanitize(); err != nil { + c.channel.warn("tags were not sanitary and have been sanitized", "error", err) @@ -1005,10 +1028,10 @@ index 00000000000000..8e280f7c675a46 +} diff --git a/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/internal/appinsights/inmemorychannel.go b/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/internal/appinsights/inmemorychannel.go new file mode 100644 -index 00000000000000..af13a2102d2933 +index 00000000000000..abc091e2b5c6b8 --- /dev/null +++ b/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/internal/appinsights/inmemorychannel.go -@@ -0,0 +1,341 @@ +@@ -0,0 +1,349 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + @@ -1055,6 +1078,7 @@ index 00000000000000..af13a2102d2933 + + throttled atomic.Bool + closed atomic.Bool ++ closeOnce sync.Once + sendQueue []*[]batchItem + sendQueueMu sync.Mutex + sendMu sync.Mutex @@ -1115,8 +1139,12 @@ index 00000000000000..af13a2102d2933 + +// Queues a single telemetry item +func (channel *inMemoryChannel) send(item *contracts.Envelope) { -+ if item != nil && !channel.closed.Load() { -+ channel.collectChan <- item ++ if item == nil || channel.closed.Load() { ++ return ++ } ++ select { ++ case channel.collectChan <- item: ++ case <-channel.cancelCtx.Done(): + } +} + @@ -1125,7 +1153,10 @@ index 00000000000000..af13a2102d2933 + if channel.closed.Load() { + return + } -+ channel.flushChan <- struct{}{} ++ select { ++ case channel.flushChan <- struct{}{}: ++ case <-channel.cancelCtx.Done(): ++ } +} + +func (channel *inMemoryChannel) retry(throttled bool, retryAfter time.Time, items []batchItem) { @@ -1138,13 +1169,11 @@ index 00000000000000..af13a2102d2933 +var errClosed = errors.New("client closed") + +func (channel *inMemoryChannel) stop() { -+ if channel.closed.Load() { -+ return -+ } -+ -+ channel.closed.Store(true) -+ channel.cancelCauseFunc(errStopped) -+ channel.checkInflight() ++ channel.closeOnce.Do(func() { ++ channel.closed.Store(true) ++ channel.cancelCauseFunc(errStopped) ++ channel.checkInflight() ++ }) +} + +// close flushes and tears down the submission goroutine and closes internal @@ -1152,19 +1181,21 @@ index 00000000000000..af13a2102d2933 +// (it is then safe to shut down without losing telemetry) or when +// the context is canceled. +func (channel *inMemoryChannel) close(ctx context.Context) { -+ if channel.closed.Load() { -+ return -+ } -+ -+ channel.closed.Store(true) -+ channel.flushChan <- struct{}{} -+ select { -+ case <-ctx.Done(): -+ channel.cancelCauseFunc(context.Cause(ctx)) -+ case <-channel.cancelCtx.Done(): -+ // Successfully flushed -+ } -+ channel.checkInflight() ++ channel.closeOnce.Do(func() { ++ channel.closed.Store(true) ++ select { ++ case channel.flushChan <- struct{}{}: ++ case <-channel.cancelCtx.Done(): ++ // acceptLoop already exited. ++ } ++ select { ++ case <-ctx.Done(): ++ channel.cancelCauseFunc(context.Cause(ctx)) ++ case <-channel.cancelCtx.Done(): ++ // Successfully flushed ++ } ++ channel.checkInflight() ++ }) +} + +func (channel *inMemoryChannel) checkInflight() { @@ -1861,10 +1892,10 @@ index 00000000000000..0299c87c81cb41 +} diff --git a/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/internal/config/config.go b/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/internal/config/config.go new file mode 100644 -index 00000000000000..7980b1505b2caa +index 00000000000000..1cb6c22a7bcd72 --- /dev/null +++ b/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/internal/config/config.go -@@ -0,0 +1,63 @@ +@@ -0,0 +1,78 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + @@ -1914,8 +1945,12 @@ index 00000000000000..7980b1505b2caa +} + +// Expand takes a counter defined with buckets and expands it into distinct -+// strings for each bucket. ++// strings for each bucket. If the counter ends with "*" (e.g. "go/package:*"), ++// it is returned as-is to indicate a wildcard prefix match. +func Expand(counter string) []string { ++ if strings.HasSuffix(counter, "*") { ++ return []string{counter} ++ } + prefix, rest, hasBuckets := strings.Cut(counter, "{") + var counters []string + if hasBuckets { @@ -1928,12 +1963,23 @@ index 00000000000000..7980b1505b2caa + } + return counters +} ++ ++// IsWildcard reports whether the counter name is a wildcard pattern. ++func IsWildcard(name string) bool { ++ return strings.HasSuffix(name, "*") ++} ++ ++// WildcardPrefix returns the prefix of a wildcard counter name, ++// stripping the trailing "*". ++func WildcardPrefix(name string) string { ++ return strings.TrimSuffix(name, "*") ++} diff --git a/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/internal/telemetry/proginfo.go b/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/internal/telemetry/proginfo.go new file mode 100644 -index 00000000000000..f6183bdf3dbf1b +index 00000000000000..4dd4b5b3243a0d --- /dev/null +++ b/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/internal/telemetry/proginfo.go -@@ -0,0 +1,43 @@ +@@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + @@ -1953,7 +1999,7 @@ index 00000000000000..f6183bdf3dbf1b +// the Go version, and will typically be of the form "go1.2.3", not a semantic +// version of the form "v1.2.3". Go versions may also include spaces and +// special characters. -+func ProgramInfo(info *debug.BuildInfo) (goVers, progPath string) { ++func ProgramInfo(info *debug.BuildInfo, trimTestSuffix bool) (goVers, progPath string) { + goVers = info.GoVersion + if strings.Contains(goVers, "devel") || strings.Contains(goVers, "-") || !version.IsValid(goVers) { + if v, rest, ok := strings.Cut(goVers, "-microsoft"); ok && @@ -1974,6 +2020,9 @@ index 00000000000000..f6183bdf3dbf1b + if progPath == "" { + progPath = strings.TrimSuffix(filepath.Base(os.Args[0]), ".exe") + } ++ if trimTestSuffix { ++ progPath, _ = strings.CutSuffix(progPath, ".test") // Remove ".test" suffix added by "go test" ++ } + + return goVers, progPath +} @@ -2017,10 +2066,10 @@ index 00000000000000..02d112edb8ad3e +} diff --git a/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/telemetry.go b/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/telemetry.go new file mode 100644 -index 00000000000000..d592037b570130 +index 00000000000000..e50deaa4189b18 --- /dev/null +++ b/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/telemetry.go -@@ -0,0 +1,125 @@ +@@ -0,0 +1,144 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + @@ -2033,6 +2082,7 @@ index 00000000000000..d592037b570130 + "runtime" + "runtime/debug" + "slices" ++ "strings" + "time" + + "github.com/microsoft/go-infra/telemetry/internal/appinsights" @@ -2068,12 +2118,16 @@ index 00000000000000..d592037b570130 + // upload configuration does not explicitly include them. + AllowGoDevel bool + ++ // If true, remove ".test" suffix from program name when running tests. ++ TrimTestSuffix bool ++ + // Logger specifies a structured logger. + // If nil nothing is logged. + Logger *slog.Logger +} + +var countersToUpload map[string]struct{} ++var wildcardPrefixes []string + +// Start initializes telemetry using the specified configuration. +func Start(cfg Config) { @@ -2094,7 +2148,7 @@ index 00000000000000..d592037b570130 + if !ok { + panic("failed to read build info for telemetry") + } -+ ver, prog := telemetry.ProgramInfo(bi) ++ ver, prog := telemetry.ProgramInfo(bi, cfg.TrimTestSuffix) + if ver == "devel" { + if !cfg.AllowGoDevel { + // If the Go version is a development version and we are not allowing @@ -2110,12 +2164,19 @@ index 00000000000000..d592037b570130 + return // Program not configured for telemetry + } + countersToUpload = make(map[string]struct{}) ++ wildcardPrefixes = nil + for _, c := range uploadConfig.Programs[progIdx].Counters { + if c.Name == "" { + continue // Skip empty counter names + } + for _, e := range config.Expand(c.Name) { -+ countersToUpload[e] = struct{}{} ++ if config.IsWildcard(e) { ++ if prefix := config.WildcardPrefix(e); prefix != "" { ++ wildcardPrefixes = append(wildcardPrefixes, prefix) ++ } ++ } else { ++ countersToUpload[e] = struct{}{} ++ } + } + } + @@ -2143,19 +2204,26 @@ index 00000000000000..d592037b570130 +} + +func uploadFilter(name string) bool { -+ _, ok := countersToUpload[name] -+ return ok ++ if _, ok := countersToUpload[name]; ok { ++ return true ++ } ++ for _, prefix := range wildcardPrefixes { ++ if strings.HasPrefix(name, prefix) { ++ return true ++ } ++ } ++ return false +} diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt -index ceed574b32b507..e29e38f7da3cb3 100644 +index 7b5b9aa37f749c..1f05d26a591c8d 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -16,6 +16,17 @@ github.com/google/pprof/third_party/svgpan # github.com/ianlancetaylor/demangle v0.0.0-20250417193237-f615e6bd150b ## explicit; go 1.13 github.com/ianlancetaylor/demangle -+# github.com/microsoft/go-infra/telemetry v0.0.0-20260128082012-a1498e2b57dd -+## explicit; go 1.24 ++# github.com/microsoft/go-infra/telemetry v0.0.0-20260407113113-dbc3015a3e9c ++## explicit; go 1.25 +github.com/microsoft/go-infra/telemetry +github.com/microsoft/go-infra/telemetry/counter +github.com/microsoft/go-infra/telemetry/internal/appinsights @@ -2197,11 +2265,11 @@ index 00000000000000..ae4055d2d71303 +// that are used by the backend package. This allows to track +// their versions in a single patch file. diff --git a/src/go.mod b/src/go.mod -index d6c515017a7009..17efde8b19a412 100644 +index 2ac54d7b35e011..15c3ae9e5d1138 100644 --- a/src/go.mod +++ b/src/go.mod @@ -11,3 +11,9 @@ require ( - golang.org/x/sys v0.40.1-0.20260116220947-d25a7aaff8c2 // indirect + golang.org/x/sys v0.42.1-0.20260320201212-a76ec62d6c53 // indirect golang.org/x/text v0.33.1-0.20260122225119-3264de9174be // indirect ) + @@ -2211,7 +2279,7 @@ index d6c515017a7009..17efde8b19a412 100644 + github.com/microsoft/go-crypto-winnative v0.0.0-20260307231751-f82d13314c5c +) diff --git a/src/go.sum b/src/go.sum -index 2223d2a7c231c1..0f168e2048a2e2 100644 +index ba6fd0576632d4..fa636b09d87598 100644 --- a/src/go.sum +++ b/src/go.sum @@ -1,3 +1,9 @@ @@ -2225,10 +2293,10 @@ index 2223d2a7c231c1..0f168e2048a2e2 100644 golang.org/x/crypto v0.47.1-0.20260113154411-7d0074ccc6f1/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= golang.org/x/net v0.49.1-0.20260122225915-f2078620ee33 h1:pNHjOZ0w6qb8R9EDmEsBXmV4o2YKLvtRiEk4q5gN5Hg= diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go -index 863882aebf583e..a0436aa1901b7e 100644 +index b01136376ef951..469f9ad34cec7b 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go -@@ -154,6 +154,13 @@ var depsRules = ` +@@ -152,6 +152,13 @@ var depsRules = ` < internal/syscall/execenv < SYSCALL; @@ -2242,7 +2310,7 @@ index 863882aebf583e..a0436aa1901b7e 100644 # TIME is SYSCALL plus the core packages about time, including context. SYSCALL < time/tzdata -@@ -547,16 +554,46 @@ var depsRules = ` +@@ -545,16 +552,46 @@ var depsRules = ` NONE < crypto/internal/boring/sig, crypto/internal/boring/syso; sync/atomic < crypto/internal/boring/bcache; @@ -2294,7 +2362,7 @@ index 863882aebf583e..a0436aa1901b7e 100644 < crypto/internal/boring < crypto/boring < crypto/internal/rand -@@ -578,6 +615,10 @@ var depsRules = ` +@@ -576,6 +613,10 @@ var depsRules = ` # CRYPTO-MATH is crypto that exposes math/big APIs - no cgo, net; fmt now ok. @@ -2305,7 +2373,7 @@ index 863882aebf583e..a0436aa1901b7e 100644 CRYPTO, FMT, math/big, internal/saferio < crypto/internal/boring/bbig < crypto/internal/fips140cache -@@ -924,7 +965,7 @@ var buildIgnore = []byte("\n//go:build ignore") +@@ -926,7 +967,7 @@ var buildIgnore = []byte("\n//go:build ignore") func findImports(pkg string) ([]string, error) { vpkg := pkg @@ -2314,7 +2382,7 @@ index 863882aebf583e..a0436aa1901b7e 100644 vpkg = "vendor/" + pkg } dir := filepath.Join(Default.GOROOT, "src", vpkg) -@@ -934,7 +975,7 @@ func findImports(pkg string) ([]string, error) { +@@ -936,7 +977,7 @@ func findImports(pkg string) ([]string, error) { } var imports []string var haveImport = map[string]bool{} @@ -38188,7 +38256,7 @@ index 00000000000000..1722410e5af193 + return getSystemDirectory() + "\\" + dll +} diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt -index 48967bc9ee3bd2..203fcbdad089ae 100644 +index e8c6f1efb099eb..537ba69a0046d4 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -1,3 +1,26 @@ diff --git a/patches/0009-Add-appinsights-telemetry.patch b/patches/0009-Add-appinsights-telemetry.patch index edbc0e10aa..88461d5a0c 100644 --- a/patches/0009-Add-appinsights-telemetry.patch +++ b/patches/0009-Add-appinsights-telemetry.patch @@ -4,14 +4,14 @@ Date: Thu, 29 May 2025 14:53:58 +0200 Subject: [PATCH] Add appinsights telemetry --- - README.md | 15 ++++++ + README.md | 15 +++++ src/cmd/go/main.go | 8 +++ - src/cmd/go/mstelemetry_test.go | 52 +++++++++++++++++++ - src/cmd/go/script_test.go | 8 +++ - src/cmd/go/scriptcmds_test.go | 11 ++++ - src/cmd/internal/telemetry/counter/counter.go | 48 ++++++++++++++++- - .../telemetry/counter/counter_bootstrap.go | 3 ++ - 7 files changed, 144 insertions(+), 1 deletion(-) + src/cmd/go/mstelemetry_test.go | 56 +++++++++++++++++++ + src/cmd/go/script_test.go | 10 ++++ + src/cmd/go/scriptcmds_test.go | 22 ++++++++ + src/cmd/internal/telemetry/counter/counter.go | 54 +++++++++++++++++- + .../telemetry/counter/counter_bootstrap.go | 3 + + 7 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 src/cmd/go/mstelemetry_test.go diff --git a/README.md b/README.md @@ -39,10 +39,10 @@ index 71c9d1dc299388..8cab5daec4da54 100644 +these practices. \ No newline at end of file diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go -index e81969ca4a3144..67dbcb2e7a3cb9 100644 +index 8cdfd9196e4cb1..3f4a4d8f912969 100644 --- a/src/cmd/go/main.go +++ b/src/cmd/go/main.go -@@ -111,6 +111,14 @@ func main() { +@@ -110,6 +110,14 @@ func main() { } flag.Usage = base.Usage flag.Parse() @@ -59,10 +59,10 @@ index e81969ca4a3144..67dbcb2e7a3cb9 100644 diff --git a/src/cmd/go/mstelemetry_test.go b/src/cmd/go/mstelemetry_test.go new file mode 100644 -index 00000000000000..6993137ad56e8c +index 00000000000000..010270fb6ad4cf --- /dev/null +++ b/src/cmd/go/mstelemetry_test.go -@@ -0,0 +1,52 @@ +@@ -0,0 +1,56 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. @@ -115,11 +115,15 @@ index 00000000000000..6993137ad56e8c + appInsightsRequests.Add(1) + fmt.Fprint(w, `{"itemsReceived": 1, "itemsAccepted": 1}`) +} ++ ++func appInsightsTotalRequests() int64 { ++ return appInsightsRequests.Load() ++} diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go -index 1345ea8bb8e530..e2b75957e21d3a 100644 +index f84a42352c5768..7521ce3db4af9f 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go -@@ -60,6 +60,7 @@ func TestScript(t *testing.T) { +@@ -62,6 +62,7 @@ func TestScript(t *testing.T) { } StartProxy() @@ -127,21 +131,23 @@ index 1345ea8bb8e530..e2b75957e21d3a 100644 var ( ctx = context.Background() -@@ -254,6 +255,8 @@ func scriptEnv(srv *vcstest.Server, srvCertFile string) ([]string, error) { +@@ -256,6 +257,10 @@ func scriptEnv(srv *vcstest.Server, srvCertFile string) ([]string, error) { "HGRCPATH=", "GOTOOLCHAIN=auto", "MS_GOTOOLCHAIN_ALLOW_NON_LOCAL=1", // allow non-local toolchains, some tests expect GOTOOLCHAIN to be honored + "MS_GOTOOLCHAIN_TELEMETRY_ENDPOINT=" + appInsightsURL, -+ "MS_GOTOOLCHAIN_TELEMETRY_ALLOW_GO_DEVEL=1", // allow telemetry for Go development versions ++ "MS_GOTOOLCHAIN_TELEMETRY_ALLOW_GO_DEVEL=1", // allow telemetry for Go development versions ++ "MS_GOTOOLCHAIN_TELEMETRY_VERBOSE=2", // enable verbose telemetry logging to help diagnose test failures ++ "MS_GOTOOLCHAIN_TELEMETRY_TRIM_TEST_SUFFIX=1", // trim ".test" suffix from program name for telemetry purposes when running tests "newline=\n", } -@@ -408,6 +411,11 @@ func checkCounters(t *testing.T, telemetryDir string) { +@@ -410,6 +415,11 @@ func checkCounters(t *testing.T, telemetryDir string) { t.Fatal("go was invoked but no counters were incremented") } } -+ if _, ok := scriptGoBuildInvoked.Load(testing.TB(t)); ok { -+ if appInsightsRequests.Load() == 0 { ++ if _, ok := scriptGoBuildSucceeded.Load(testing.TB(t)); ok { ++ if appInsightsTotalRequests() == 0 { + t.Fatal("go was invoked but no App Insights request were recorded") + } + } @@ -149,18 +155,18 @@ index 1345ea8bb8e530..e2b75957e21d3a 100644 // Copied from https://go.googlesource.com/telemetry/+/5f08a0cbff3f/internal/telemetry/mode.go#122 diff --git a/src/cmd/go/scriptcmds_test.go b/src/cmd/go/scriptcmds_test.go -index ced8d880e9ae3a..b3ad521ff94873 100644 +index 8195e830caa31b..882aeecfa562b9 100644 --- a/src/cmd/go/scriptcmds_test.go +++ b/src/cmd/go/scriptcmds_test.go -@@ -71,6 +71,7 @@ func scriptCC(cmdExec script.Cmd) script.Cmd { +@@ -72,6 +72,7 @@ func scriptCC(cmdExec script.Cmd) script.Cmd { } var scriptGoInvoked sync.Map // testing.TB → go command was invoked -+var scriptGoBuildInvoked sync.Map ++var scriptGoBuildSucceeded sync.Map // scriptGo runs the go command. func scriptGo(cancel func(*exec.Cmd) error, waitDelay time.Duration) script.Cmd { -@@ -85,6 +86,16 @@ func scriptGo(cancel func(*exec.Cmd) error, waitDelay time.Duration) script.Cmd +@@ -86,6 +87,27 @@ func scriptGo(cancel func(*exec.Cmd) error, waitDelay time.Duration) script.Cmd if !dup { t.Cleanup(func() { scriptGoInvoked.Delete(t) }) } @@ -168,17 +174,28 @@ index ced8d880e9ae3a..b3ad521ff94873 100644 + // If the first argument is a subcommand, record it. + switch s[0] { + case "build", "install", "run": -+ _, dup = scriptGoBuildInvoked.LoadOrStore(t, true) -+ if !dup { -+ t.Cleanup(func() { scriptGoBuildInvoked.Delete(t) }) ++ wait, err := cmd.Run(state, s...) ++ if err != nil { ++ return wait, err + } ++ waitAndRecord := func(state *script.State) (stdout, stderr string, err error) { ++ stdout, stderr, err = wait(state) ++ if err == nil { ++ _, dup = scriptGoBuildSucceeded.LoadOrStore(t, true) ++ if !dup { ++ t.Cleanup(func() { scriptGoBuildSucceeded.Delete(t) }) ++ } ++ } ++ return stdout, stderr, err ++ } ++ return waitAndRecord, nil + } + } return cmd.Run(state, s...) }) } diff --git a/src/cmd/internal/telemetry/counter/counter.go b/src/cmd/internal/telemetry/counter/counter.go -index 5cef0b0041551a..2c1b8143d60764 100644 +index 5cef0b0041551a..8c2bae0e613c92 100644 --- a/src/cmd/internal/telemetry/counter/counter.go +++ b/src/cmd/internal/telemetry/counter/counter.go @@ -7,10 +7,24 @@ @@ -206,7 +223,7 @@ index 5cef0b0041551a..2c1b8143d60764 100644 ) var openCalled bool -@@ -24,9 +38,38 @@ func Open() { +@@ -24,9 +38,44 @@ func Open() { counter.OpenDir(os.Getenv("TEST_TELEMETRY_DIR")) } @@ -216,8 +233,13 @@ index 5cef0b0041551a..2c1b8143d60764 100644 + return + } + var logger *slog.Logger -+ if os.Getenv("MS_GOTOOLCHAIN_TELEMETRY_VERBOSE") == "1" { -+ logger = slog.Default() ++ level := slog.LevelWarn ++ switch os.Getenv("MS_GOTOOLCHAIN_TELEMETRY_VERBOSE") { ++ case "2": ++ level = slog.LevelInfo ++ fallthrough ++ case "1": ++ logger = slog.New(slog.NewTextHandler(log.Default().Writer(), &slog.HandlerOptions{Level: level})) + } + mstelemetry.Start(mstelemetry.Config{ + InstrumentationKey: appInsightsInstrumentationKey, @@ -225,6 +247,7 @@ index 5cef0b0041551a..2c1b8143d60764 100644 + AllowGoDevel: os.Getenv("MS_GOTOOLCHAIN_TELEMETRY_ALLOW_GO_DEVEL") == "1", + UploadConfig: msconfig.Config, + Logger: logger, ++ TrimTestSuffix: os.Getenv("MS_GOTOOLCHAIN_TELEMETRY_TRIM_TEST_SUFFIX") == "1", + }) +} + @@ -245,7 +268,7 @@ index 5cef0b0041551a..2c1b8143d60764 100644 } // New returns a counter with the given name. -@@ -44,6 +87,7 @@ func NewStack(name string, depth int) *counter.StackCounter { +@@ -44,6 +93,7 @@ func NewStack(name string, depth int) *counter.StackCounter { // the concatenation of prefix and the flag name. func CountFlags(prefix string, flagSet flag.FlagSet) { counter.CountFlags(prefix, flagSet) @@ -253,7 +276,7 @@ index 5cef0b0041551a..2c1b8143d60764 100644 } // CountFlagValue creates a counter for the flag value -@@ -56,7 +100,9 @@ func CountFlagValue(prefix string, flagSet flag.FlagSet, flagName string) { +@@ -56,7 +106,9 @@ func CountFlagValue(prefix string, flagSet flag.FlagSet, flagName string) { // TODO(matloob): Add this to x/telemetry? flagSet.Visit(func(f *flag.Flag) { if f.Name == flagName { diff --git a/patches/0010-Implement-ms_tls_config_schannel-experiment.patch b/patches/0010-Implement-ms_tls_config_schannel-experiment.patch index 81b90dd13e..0b01dccf68 100644 --- a/patches/0010-Implement-ms_tls_config_schannel-experiment.patch +++ b/patches/0010-Implement-ms_tls_config_schannel-experiment.patch @@ -24,7 +24,7 @@ Subject: [PATCH] Implement ms_tls_config_schannel experiment create mode 100644 src/internal/goexperiment/exp_ms_tls_config_schannel_on.go diff --git a/src/crypto/tls/fips140_test.go b/src/crypto/tls/fips140_test.go -index 96273c0fe0ea2f..11d32bbc1c2551 100644 +index 5a72c493e03eba..930d8c6d134e94 100644 --- a/src/crypto/tls/fips140_test.go +++ b/src/crypto/tls/fips140_test.go @@ -14,6 +14,7 @@ import ( @@ -35,7 +35,7 @@ index 96273c0fe0ea2f..11d32bbc1c2551 100644 "internal/obscuretestdata" "internal/testenv" "math/big" -@@ -191,6 +192,9 @@ func TestFIPSServerCipherSuites(t *testing.T) { +@@ -190,6 +191,9 @@ func TestFIPSServerCipherSuites(t *testing.T) { } serverConfig.BuildNameToCertificate() t.Run(fmt.Sprintf("suite=%s", CipherSuiteName(id)), func(t *testing.T) { @@ -467,7 +467,7 @@ index 00000000000000..b1bdb31863cc7a + } +} diff --git a/src/crypto/tls/tls_test.go b/src/crypto/tls/tls_test.go -index 4513008a5f930e..e1f868e7086061 100644 +index 4df1aed1706c74..f447dc3432945a 100644 --- a/src/crypto/tls/tls_test.go +++ b/src/crypto/tls/tls_test.go @@ -21,6 +21,7 @@ import ( @@ -553,13 +553,13 @@ index 00000000000000..a2dbc6187da2a0 +const MS_TLS_Config_Schannel = true +const MS_TLS_Config_SchannelInt = 1 diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go -index be2104e8f5a437..bbe0c40b404a66 100644 +index 86c5570bf12edb..66051d85e2ea23 100644 --- a/src/internal/goexperiment/flags.go +++ b/src/internal/goexperiment/flags.go -@@ -150,4 +150,12 @@ type Flags struct { - - // RuntimeSecret enables the runtime/secret package. - RuntimeSecret bool +@@ -151,4 +151,12 @@ type Flags struct { + // from interleaved key/elem slots (KVKVKVKV) to split key and elem + // arrays (KKKKVVVV). + MapSplitGroup bool + + // MS_TLS_Config_Schannel enables the filtering and ordering of cipher + // suites according to the Windows Schannel settings. @@ -640,7 +640,7 @@ index 09be2eb0807932..b74b311279e81f 100644 + } +} diff --git a/src/internal/syscall/windows/zsyscall_windows.go b/src/internal/syscall/windows/zsyscall_windows.go -index 9526e855e8f1ba..49873764aea3a1 100644 +index 5bc228e63069ca..b4959928a817aa 100644 --- a/src/internal/syscall/windows/zsyscall_windows.go +++ b/src/internal/syscall/windows/zsyscall_windows.go @@ -38,6 +38,7 @@ func errnoErr(e syscall.Errno) error { @@ -660,7 +660,7 @@ index 9526e855e8f1ba..49873764aea3a1 100644 procProcessPrng = modbcryptprimitives.NewProc("ProcessPrng") procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses") procCreateEventW = modkernel32.NewProc("CreateEventW") -@@ -271,6 +274,19 @@ func SetTokenInformation(tokenHandle syscall.Token, tokenInformationClass uint32 +@@ -272,6 +275,19 @@ func SetTokenInformation(tokenHandle syscall.Token, tokenInformationClass uint32 return } diff --git a/patches/0012-Align-TLS-settings-with-Microsoft-policies.patch b/patches/0012-Align-TLS-settings-with-Microsoft-policies.patch index 66a028bae4..90880488ca 100644 --- a/patches/0012-Align-TLS-settings-with-Microsoft-policies.patch +++ b/patches/0012-Align-TLS-settings-with-Microsoft-policies.patch @@ -4,26 +4,27 @@ Date: Fri, 12 Dec 2025 16:46:44 +0100 Subject: [PATCH] Align TLS settings with Microsoft policies --- - doc/godebug.md | 9 + - src/crypto/tls/common.go | 9 +- - src/crypto/tls/defaults.go | 47 ++- - src/crypto/tls/defaults_microsoft.go | 153 +++++++ - src/crypto/tls/handshake_client.go | 21 +- - src/crypto/tls/handshake_client_test.go | 17 +- - src/crypto/tls/handshake_server_tls13.go | 22 +- - src/crypto/tls/handshake_test.go | 3 + - src/crypto/tls/microsoft_test.go | 483 +++++++++++++++++++++++ - src/crypto/tls/schannel_windows.go | 7 + - src/internal/godebugs/table.go | 2 + - 11 files changed, 749 insertions(+), 24 deletions(-) + doc/godebug.md | 9 + + src/crypto/tls/common.go | 9 +- + src/crypto/tls/defaults.go | 47 +- + src/crypto/tls/defaults_microsoft.go | 153 ++++++ + src/crypto/tls/handshake_client.go | 21 +- + src/crypto/tls/handshake_client_test.go | 17 +- + src/crypto/tls/handshake_server_tls13.go | 22 +- + src/crypto/tls/handshake_test.go | 3 + + src/crypto/tls/microsoft_test.go | 483 ++++++++++++++++++ + src/crypto/tls/schannel_windows.go | 7 + + src/internal/godebugs/table.go | 2 + + src/net/http/internal/http2/transport_test.go | 2 + + 12 files changed, 751 insertions(+), 24 deletions(-) create mode 100644 src/crypto/tls/defaults_microsoft.go create mode 100644 src/crypto/tls/microsoft_test.go diff --git a/doc/godebug.md b/doc/godebug.md -index 7184b2aaf1ce67..07fc1ea6d19970 100644 +index 4935d64850883d..1736fd71017add 100644 --- a/doc/godebug.md +++ b/doc/godebug.md -@@ -197,6 +197,15 @@ APIs ignore the random `io.Reader` parameter. For Go 1.26, it defaults +@@ -207,6 +207,15 @@ APIs ignore the random `io.Reader` parameter. For Go 1.26, it defaults to `cryptocustomrand=0`, ignoring the random parameters. Using `cryptocustomrand=1` reverts to the pre-Go 1.26 behavior. @@ -907,10 +908,10 @@ index cccfb8866f88ab..b2896e95e74686 100644 cipherSuitesPreferenceOrderNoAES = cipherSuitesPreferenceOrder defaultCipherSuitesTLS13NoAES = defaultCipherSuitesTLS13 diff --git a/src/internal/godebugs/table.go b/src/internal/godebugs/table.go -index 10c4eb715e99e4..edf933b0a770bd 100644 +index 7ddfad14ea1be0..1ba17bc136710f 100644 --- a/src/internal/godebugs/table.go +++ b/src/internal/godebugs/table.go -@@ -48,6 +48,8 @@ var All = []Info{ +@@ -49,6 +49,8 @@ var All = []Info{ {Name: "httpservecontentkeepheaders", Package: "net/http", Changed: 23, Old: "1"}, {Name: "installgoroot", Package: "go/build"}, {Name: "jstmpllitinterp", Package: "html/template", Opaque: true}, // bug #66217: remove Opaque @@ -919,3 +920,23 @@ index 10c4eb715e99e4..edf933b0a770bd 100644 //{Name: "multipartfiles", Package: "mime/multipart"}, {Name: "multipartmaxheaders", Package: "mime/multipart"}, {Name: "multipartmaxparts", Package: "mime/multipart"}, +diff --git a/src/net/http/internal/http2/transport_test.go b/src/net/http/internal/http2/transport_test.go +index 955c2208ad4a86..0f5dc2ab51c728 100644 +--- a/src/net/http/internal/http2/transport_test.go ++++ b/src/net/http/internal/http2/transport_test.go +@@ -15,6 +15,7 @@ import ( + "errors" + "flag" + "fmt" ++ "internal/testenv" + "io" + "log" + "math/rand" +@@ -2744,6 +2745,7 @@ func testTransportCloseAfterLostPing(t testing.TB) { + } + + func TestTransportPingWriteBlocks(t *testing.T) { ++ testenv.SetGODEBUG(t, "ms_tlsprofile=off") + ts := newTestServer(t, + func(w http.ResponseWriter, r *http.Request) {}, + ) diff --git a/patches/0013-Add-Microsoft-version-information.patch b/patches/0013-Add-Microsoft-version-information.patch index c9446d530c..1772907eea 100644 --- a/patches/0013-Add-Microsoft-version-information.patch +++ b/patches/0013-Add-Microsoft-version-information.patch @@ -17,7 +17,7 @@ Microsoft build of Go version string. doc/godebug.md | 9 ++ src/cmd/dist/build.go | 16 ++ src/cmd/dist/buildruntime.go | 1 + - src/cmd/go/go_ms_test.go | 149 ++++++++++++++++++ + src/cmd/go/go_ms_test.go | 151 ++++++++++++++++++ src/cmd/go/internal/cache/hash.go | 6 + src/cmd/go/internal/load/pkg.go | 2 + .../testdata/script/gotoolchain_local_ms.txt | 46 ++++++ @@ -26,15 +26,15 @@ Microsoft build of Go version string. src/internal/godebugs/table.go | 1 + src/runtime/extern.go | 25 ++- src/runtime/runtime1.go | 4 + - 12 files changed, 322 insertions(+), 8 deletions(-) + 12 files changed, 324 insertions(+), 8 deletions(-) create mode 100644 src/cmd/go/go_ms_test.go create mode 100644 src/cmd/go/testdata/script/gotoolchain_local_ms.txt diff --git a/doc/godebug.md b/doc/godebug.md -index 4c95ceb09bcbbe..6b052d8ce29b6a 100644 +index 1736fd71017add..114079d8f99527 100644 --- a/doc/godebug.md +++ b/doc/godebug.md -@@ -192,6 +192,15 @@ Microsoft build of Go 1.26 added a new `ms_tlsprofile` setting that controls the +@@ -216,6 +216,15 @@ Microsoft build of Go 1.26 added a new `ms_tlsprofile` setting that controls the - "default": use the recommended Microsoft TLS settings. This is the default. - "off": use the default upstream Go TLS settings. @@ -51,10 +51,10 @@ index 4c95ceb09bcbbe..6b052d8ce29b6a 100644 Go 1.25 added a new `decoratemappings` setting that controls whether the Go diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go -index 917f682fd4bfaf..85512e38220de6 100644 +index ec10d9597b69fc..cd2b83cb6150b0 100644 --- a/src/cmd/dist/build.go +++ b/src/cmd/dist/build.go -@@ -450,6 +450,22 @@ func findgoversion() string { +@@ -454,6 +454,22 @@ func findgoversion() string { return version } @@ -91,10 +91,10 @@ index 87e88671763996..dccdca982300d7 100644 fmt.Fprintf(&buf, "const DefaultGOFIPS140 = `%s`\n", gofips140) diff --git a/src/cmd/go/go_ms_test.go b/src/cmd/go/go_ms_test.go new file mode 100644 -index 00000000000000..6f431716475ebf +index 00000000000000..635c40dec22dd8 --- /dev/null +++ b/src/cmd/go/go_ms_test.go -@@ -0,0 +1,149 @@ +@@ -0,0 +1,151 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. @@ -122,6 +122,7 @@ index 00000000000000..6f431716475ebf + t.Run("ms_version="+test.name, func(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() ++ tg.parallel() + tg.setenv("GODEBUG", "ms_version="+test.ms_version) + // Check "go version" output. + tg.run("version") @@ -136,6 +137,7 @@ index 00000000000000..6f431716475ebf +func TestMicrosoftBuildInfoVersion(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() ++ tg.parallel() + v, msVersion, ok := msReadBuildInfo(t, tg.goTool()) + if strings.HasSuffix(v, "-microsoft") { + t.Errorf("buildinfo GoVersion = %q, want no -microsoft suffix", v) @@ -334,10 +336,10 @@ index 00000000000000..24538695be2cf2 +go version +stdout go1.501 diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go -index 0140c385e47991..727a992bdf7a11 100644 +index 5e592c7c6697d7..df70274e03b5df 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go -@@ -186,15 +186,20 @@ func Main(arch *sys.Arch, theArch Arch) { +@@ -188,15 +188,20 @@ func Main(arch *sys.Arch, theArch Arch) { addstrdata1(ctxt, "runtime.defaultGOROOT="+buildcfg.GOROOT) } @@ -364,7 +366,7 @@ index 0140c385e47991..727a992bdf7a11 100644 // TODO(matloob): define these above and then check flag values here if ctxt.Arch.Family == sys.AMD64 && buildcfg.GOOS == "plan9" { -@@ -210,10 +215,28 @@ func Main(arch *sys.Arch, theArch Arch) { +@@ -212,10 +217,28 @@ func Main(arch *sys.Arch, theArch Arch) { objabi.Flagfn1("X", "add string value `definition` of the form importpath.name=value", func(s string) { addstrdata1(ctxt, s) }) objabi.Flagcount("v", "print link trace", &ctxt.Debugvlog) objabi.Flagfn1("importcfg", "read import configuration from `file`", ctxt.readImportCfg) @@ -443,7 +445,7 @@ index 89fd74eb823162..f6d6a78531fc75 100644 var Error error diff --git a/src/internal/godebugs/table.go b/src/internal/godebugs/table.go -index 7a5ea67c7dca33..d3e5b7b71d528c 100644 +index 1ba17bc136710f..a3868ad860ed4a 100644 --- a/src/internal/godebugs/table.go +++ b/src/internal/godebugs/table.go @@ -51,6 +51,7 @@ var All = []Info{ @@ -455,10 +457,10 @@ index 7a5ea67c7dca33..d3e5b7b71d528c 100644 {Name: "multipartmaxheaders", Package: "mime/multipart"}, {Name: "multipartmaxparts", Package: "mime/multipart"}, diff --git a/src/runtime/extern.go b/src/runtime/extern.go -index a9f97a1a045525..991d5ef22c5df5 100644 +index a69f4aaede794d..f5c35867b78e26 100644 --- a/src/runtime/extern.go +++ b/src/runtime/extern.go -@@ -367,11 +367,34 @@ func GOROOT() string { +@@ -369,11 +369,34 @@ func GOROOT() string { // This is accessed by "go version ". var buildVersion string @@ -495,10 +497,10 @@ index a9f97a1a045525..991d5ef22c5df5 100644 // GOOS is the running program's operating system target: diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go -index 965ff8ab5167d5..2674b5d8844b18 100644 +index 8da3682261bf9f..3b4531df8a5ec1 100644 --- a/src/runtime/runtime1.go +++ b/src/runtime/runtime1.go -@@ -364,6 +364,9 @@ var debug struct { +@@ -365,6 +365,9 @@ var debug struct { // tracebacklabels controls the inclusion of goroutine labels in the // goroutine status header line. tracebacklabels atomic.Int32 @@ -508,8 +510,8 @@ index 965ff8ab5167d5..2674b5d8844b18 100644 } var dbgvars = []*dbgVar{ -@@ -401,6 +404,7 @@ var dbgvars = []*dbgVar{ - {name: "tracebacklabels", atomic: &debug.tracebacklabels, def: 0}, +@@ -402,6 +405,7 @@ var dbgvars = []*dbgVar{ + {name: "tracebacklabels", atomic: &debug.tracebacklabels, def: 1}, {name: "tracefpunwindoff", value: &debug.tracefpunwindoff}, {name: "updatemaxprocs", value: &debug.updatemaxprocs, def: 1}, + {name: "ms_version", atomic: &debug.msversion, def: 0}, diff --git a/patches/0016-Skip-http2-tests.patch b/patches/0016-Skip-http2-tests.patch new file mode 100644 index 0000000000..39b7477f35 --- /dev/null +++ b/patches/0016-Skip-http2-tests.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: bot-for-go[bot] <199222863+bot-for-go[bot]@users.noreply.github.com> +Date: Wed, 8 Apr 2026 12:15:13 +0200 +Subject: [PATCH] Skip http2 tests + +http2 tests can't be run in FIPS mode due to a weird interaction between +crypto and test/synctest bubbles. + +Tracked at https://github.com/golang/go/issues/78557 +--- + src/net/http/internal/http2/http2_test.go | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/src/net/http/internal/http2/http2_test.go b/src/net/http/internal/http2/http2_test.go +index ad1b9a6d06e773..7e7042796a12d8 100644 +--- a/src/net/http/internal/http2/http2_test.go ++++ b/src/net/http/internal/http2/http2_test.go +@@ -5,6 +5,7 @@ + package http2 + + import ( ++ "crypto/fips140" + "flag" + "fmt" + "os" +@@ -28,6 +29,15 @@ func init() { + flag.BoolVar(&VerboseLogs, "verboseh2", VerboseLogs, "Verbose HTTP/2 debug logging") + } + ++func TestMain(m *testing.M) { ++ if fips140.Enabled() { ++ // TODO: Remove once https://github.com/golang/go/issues/78557 is resolved. ++ os.Exit(0) ++ } ++ ++ os.Exit(m.Run()) ++} ++ + func TestSettingString(t *testing.T) { + tests := []struct { + s Setting diff --git a/patches/0017-Port-minimum-Windows-target-version-fallback.patch b/patches/0017-Port-minimum-Windows-target-version-fallback.patch new file mode 100644 index 0000000000..9cbca31251 --- /dev/null +++ b/patches/0017-Port-minimum-Windows-target-version-fallback.patch @@ -0,0 +1,167 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: bot-for-go[bot] <199222863+bot-for-go[bot]@users.noreply.github.com> +Date: Wed, 8 Apr 2026 12:19:33 +0200 +Subject: [PATCH] Port minimum Windows target version fallback + +Remove once https://go-review.googlesource.com/c/go/+/763960 is merged. +--- + src/cmd/link/internal/ld/lib.go | 105 ++++++++++++++++++++++++++------ + 1 file changed, 85 insertions(+), 20 deletions(-) + +diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go +index 6499182422863c..2f5feb5490809a 100644 +--- a/src/cmd/link/internal/ld/lib.go ++++ b/src/cmd/link/internal/ld/lib.go +@@ -34,6 +34,7 @@ import ( + "bytes" + "debug/elf" + "debug/macho" ++ "debug/pe" + "encoding/base64" + "encoding/binary" + "fmt" +@@ -1467,7 +1468,7 @@ func (ctxt *Link) hostlink() { + // Only macOS supports unmapped segments such as our __DWARF segment. + combineDwarf := ctxt.IsDarwin() && !*FlagW && machoPlatform == PLATFORM_MACOS + +- var isMSVC bool // used on Windows ++ var isMSVC, isLLD bool // used on Windows + wlPrefix := "-Wl,--" + + switch ctxt.HeadType { +@@ -1521,6 +1522,9 @@ func (ctxt *Link) hostlink() { + } + case objabi.Hwindows: + isMSVC = ctxt.isMSVC() ++ if !isMSVC { ++ isLLD = ctxt.isLLD() ++ } + if isMSVC { + // For various options, MSVC lld-link only accepts one dash. + // TODO: It seems mingw clang supports one or two dashes, +@@ -1543,10 +1547,22 @@ func (ctxt *Link) hostlink() { + argv = append(argv, wlPrefix+"nxcompat") + + if !isMSVC { +- argv = append(argv, fmt.Sprintf("-Wl,--major-os-version=%d", PeMinimumTargetMajorVersion)) +- argv = append(argv, fmt.Sprintf("-Wl,--minor-os-version=%d", PeMinimumTargetMinorVersion)) +- argv = append(argv, fmt.Sprintf("-Wl,--major-subsystem-version=%d", PeMinimumTargetMajorVersion)) +- argv = append(argv, fmt.Sprintf("-Wl,--minor-subsystem-version=%d", PeMinimumTargetMinorVersion)) ++ peMajorVersion := PeMinimumTargetMajorVersion ++ peMinorVersion := PeMinimumTargetMinorVersion ++ if peMajorVersion >= 10 && !isLLD && ++ !peHasLoadConfigDirectorySupport(ctxt.Arch, argv[0]) { ++ // The external linker doesn't support wiring up ++ // _load_config_used to the PE Load Configuration ++ // Directory. Windows 10+ validates this directory, ++ // so fall back to an older version to avoid ++ // load failures. ++ peMajorVersion = 6 ++ peMinorVersion = 1 ++ } ++ argv = append(argv, fmt.Sprintf("-Wl,--major-os-version=%d", peMajorVersion)) ++ argv = append(argv, fmt.Sprintf("-Wl,--minor-os-version=%d", peMinorVersion)) ++ argv = append(argv, fmt.Sprintf("-Wl,--major-subsystem-version=%d", peMajorVersion)) ++ argv = append(argv, fmt.Sprintf("-Wl,--minor-subsystem-version=%d", peMinorVersion)) + } + case objabi.Haix: + argv = append(argv, "-pthread") +@@ -1971,23 +1987,9 @@ func (ctxt *Link) hostlink() { + checkStatic(p) + } + if ctxt.HeadType == objabi.Hwindows { +- // Determine which linker we're using. Add in the extldflags in +- // case used has specified "-fuse-ld=...". +- extld := ctxt.extld() +- name, args := extld[0], extld[1:] +- args = append(args, trimLinkerArgv(flagExtldflags)...) +- args = append(args, "-Wl,--version") +- cmd := exec.Command(name, args...) +- usingLLD := false +- if out, err := cmd.CombinedOutput(); err == nil { +- if bytes.Contains(out, []byte("LLD ")) { +- usingLLD = true +- } +- } +- + // use gcc linker script to work around gcc bug + // (see https://golang.org/issue/20183 for details). +- if !usingLLD { ++ if !isLLD { + p := writeGDBLinkerScript() + argv = append(argv, "-Wl,-T,"+p) + } +@@ -2240,6 +2242,54 @@ func linkerFlagSupported(arch *sys.Arch, linker, altLinker, flag string) bool { + return err == nil && !bytes.Contains(out, []byte("unrecognized")) && !bytes.Contains(out, []byte("unknown")) + } + ++// peHasLoadConfigDirectorySupport checks whether the external linker ++// populates the PE Load Configuration Directory data directory entry ++// when it encounters a _load_config_used symbol. ++// ++// GNU ld gained this support in binutils 2.45. MSVC link.exe and ++// LLVM lld-link have always supported it. ++func peHasLoadConfigDirectorySupport(arch *sys.Arch, linker string) bool { ++ src := filepath.Join(*flagTmpdir, "loadcfg_test.c") ++ if err := os.WriteFile(src, []byte(` ++#ifdef _WIN64 ++typedef unsigned long long uintptr; ++#else ++typedef unsigned long uintptr; ++#endif ++const uintptr _load_config_used[2] = { sizeof(_load_config_used), 0 }; ++int main() { return 0; } ++`), 0666); err != nil { ++ return false ++ } ++ ++ outPath := filepath.Join(*flagTmpdir, "loadcfg_test.exe") ++ flags := hostlinkArchArgs(arch) ++ flags = append(flags, "-o", outPath, src) ++ cmd := exec.Command(linker, flags...) ++ cmd.Env = append([]string{"LC_ALL=C"}, os.Environ()...) ++ if err := cmd.Run(); err != nil { ++ return false ++ } ++ ++ f, err := pe.Open(outPath) ++ if err != nil { ++ return false ++ } ++ defer f.Close() ++ ++ switch oh := f.OptionalHeader.(type) { ++ case *pe.OptionalHeader64: ++ if int(pe.IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG) < len(oh.DataDirectory) { ++ return oh.DataDirectory[pe.IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress != 0 ++ } ++ case *pe.OptionalHeader32: ++ if int(pe.IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG) < len(oh.DataDirectory) { ++ return oh.DataDirectory[pe.IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress != 0 ++ } ++ } ++ return false ++} ++ + // trimLinkerArgv returns a new copy of argv that does not include flags + // that are not relevant for testing whether some linker option works. + func trimLinkerArgv(argv []string) []string { +@@ -3139,3 +3189,18 @@ func (ctxt *Link) isMSVC() bool { + } + return false + } ++ ++// isLLD reports whether the C toolchain is using LLD as the linker. ++func (ctxt *Link) isLLD() bool { ++ extld := ctxt.extld() ++ name, args := extld[0], extld[1:] ++ args = append(args, trimLinkerArgv(flagExtldflags)...) ++ args = append(args, "-Wl,--version") ++ cmd := exec.Command(name, args...) ++ if out, err := cmd.CombinedOutput(); err == nil { ++ if bytes.Contains(out, []byte("LLD ")) { ++ return true ++ } ++ } ++ return false ++}