@@ -13,186 +13,114 @@ The warnings use CI-specific formats:
1313- Azure DevOps: ##vso[task.logissue type=warning] command
1414
1515Warnings are only emitted when:
16- 1. Running in a detected CI environment
16+ 1. Building in a detected CI environment
17172. The deprecated backend was explicitly specified by the user
1818 (not auto-selected by systemcrypto)
1919
2020This helps users migrate away from the specific backend experiments without
2121breaking existing tooling that might parse stdout/stderr, and avoids
2222warning when systemcrypto automatically selects a backend.
2323---
24- src/crypto/internal/backend/cng_windows.go | 4 +
25- src/crypto/internal/backend/darwin_darwin.go | 4 +
26- .../backend/deprecation/deprecation.go | 96 +++++++++++++++++++
27- .../internal/opensslsetup/opensslsetup.go | 4 +
28- 4 files changed, 108 insertions(+)
29- create mode 100644 src/crypto/internal/backend/deprecation/deprecation.go
24+ src/cmd/go/main.go | 3 ++
25+ src/internal/buildcfg/exp.go | 67 ++++++++++++++++++++++++++++++++++++
26+ 2 files changed, 70 insertions(+)
3027
31- diff --git a/src/crypto/internal/backend/cng_windows.go b/src/crypto/internal/backend/cng_windows.go
32- index c5bffa7b6c3949..5ed99891b74c67 100644
33- --- a/src/crypto/internal/backend/cng_windows.go
34- +++ b/src/crypto/internal/backend/cng_windows.go
35- @@ -12,6 +12,7 @@ package backend
36- import (
37- "crypto"
38- "crypto/cipher"
39- + "crypto/internal/backend/deprecation"
40- "crypto/internal/backend/fips140"
41- "crypto/internal/boring/sig"
42- "hash"
43- @@ -21,6 +22,9 @@ import (
44- )
28+ diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go
29+ index 67dbcb2e7a3cb9..1730261a3b1ba6 100644
30+ --- a/src/cmd/go/main.go
31+ +++ b/src/cmd/go/main.go
32+ @@ -305,6 +305,9 @@ func invoke(cmd *base.Command, args []string) {
33+ }
34+ }
4535
46- func init() {
47- + // Emit deprecation warning in CI environments
48- + deprecation.WarnCryptoBackendDeprecated("cngcrypto")
49- +
50- fn := func() bool {
51- enabled, err := cng.FIPS()
52- if err != nil {
53- diff --git a/src/crypto/internal/backend/darwin_darwin.go b/src/crypto/internal/backend/darwin_darwin.go
54- index fea0f284de2439..3b8da177cf3c40 100644
55- --- a/src/crypto/internal/backend/darwin_darwin.go
56- +++ b/src/crypto/internal/backend/darwin_darwin.go
57- @@ -12,6 +12,7 @@ package backend
36+ + // Check for deprecated crypto backends and emit warnings in CI environments
37+ + buildcfg.CheckDeprecatedCryptoBackends()
38+ +
39+ // Set environment (GOOS, GOARCH, etc) explicitly.
40+ // In theory all the commands we invoke should have
41+ // the same default computation of these as we do,
42+ diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go
43+ index 9ea95a9df726d1..2a96ad274329f9 100644
44+ --- a/src/internal/buildcfg/exp.go
45+ +++ b/src/internal/buildcfg/exp.go
46+ @@ -7,6 +7,7 @@ package buildcfg
5847 import (
59- "crypto"
60- "crypto/cipher"
61- + "crypto/internal/backend/deprecation"
62- "crypto/internal/backend/fips140"
63- "crypto/internal/boring/sig"
64- "crypto/internal/fips140/nistec"
65- @@ -23,6 +24,9 @@ import (
66- )
67-
68- func init() {
69- + // Emit deprecation warning in CI environments
70- + deprecation.WarnCryptoBackendDeprecated("darwincrypto")
71- +
72- // Darwin is considered FIPS compliant.
73- if err := fips140.Check(func() bool { return true }); err != nil {
74- panic("darwincrypto: " + err.Error())
75- diff --git a/src/crypto/internal/backend/deprecation/deprecation.go b/src/crypto/internal/backend/deprecation/deprecation.go
76- new file mode 100644
77- index 00000000000000..0e02fcad6bffa1
78- --- /dev/null
79- +++ b/src/crypto/internal/backend/deprecation/deprecation.go
80- @@ -0,0 +1,96 @@
81- + // Package deprecation provides utilities for emitting deprecation warnings
82- + // in CI environments without affecting normal program output.
83- +
84- + package deprecation
85- +
86- + import (
87- + "fmt"
48+ "errors"
49+ "fmt"
8850+ "os"
89- + "syscall"
90- + )
91- +
92- + // WarnCryptoBackendDeprecated emits a deprecation warning for specific crypto backends
93- + // in CI environments using their respective warning formats, but only if the user
94- + // explicitly specified that backend (not if systemcrypto auto-selected it).
95- + func WarnCryptoBackendDeprecated(backend string) {
96- + // Don't warn if this backend was auto-selected by systemcrypto
97- + if isBackendAutoSelected(backend) {
51+ "reflect"
52+ "slices"
53+ "strings"
54+ @@ -235,6 +236,72 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) {
55+ return flags, nil
56+ }
57+
58+ + // CheckDeprecatedCryptoBackends emits deprecation warnings for specific crypto backends
59+ + // in CI environments when the user explicitly specified those backends.
60+ + // This should be called once at the start of the go command.
61+ + func CheckDeprecatedCryptoBackends() {
62+ + goexp := os.Getenv("GOEXPERIMENT")
63+ + if goexp == "" {
64+ + // No explicit GOEXPERIMENT set, so systemcrypto is the default
65+ + // No need to warn about auto-selection
9866+ return
9967+ }
10068+
101- + if isGitHubActions() {
102- + emitGitHubActionsWarning(backend)
103- + } else if isAzureDevOps() {
104- + emitAzureDevOpsWarning(backend)
105- + }
106- + // For other environments, we don't emit warnings to avoid breaking
107- + // users who might be parsing stdout/stderr
108- + }
109- +
110- + // isBackendAutoSelected checks if the backend was auto-selected by systemcrypto
111- + // rather than explicitly chosen by the user
112- + func isBackendAutoSelected(backend string) bool {
113- + goexperiment, _ := syscall.Getenv("GOEXPERIMENT")
69+ + // Check each deprecated backend that might be explicitly specified
70+ + deprecatedBackends := []string{"opensslcrypto", "cngcrypto", "darwincrypto"}
11471+
115- + // If GOEXPERIMENT is empty, systemcrypto is the default in Go 1.25+
116- + if goexperiment == "" {
117- + return true
72+ + for _, backend := range deprecatedBackends {
73+ + if isBackendExplicitlySpecified(backend, goexp) {
74+ + emitDeprecationWarning(backend)
75+ + }
11876+ }
119- +
120- + // Check if the user explicitly specified this deprecated backend
121- + return !isBackendExplicitlySpecified(backend, goexperiment)
12277+ }
12378+
12479+ // isBackendExplicitlySpecified checks if the specific backend was explicitly
12580+ // specified in the GOEXPERIMENT string
12681+ func isBackendExplicitlySpecified(backend, goexperiment string) bool {
12782+ // Parse the comma-separated GOEXPERIMENT string
128- + for i := 0; i < len(goexperiment); {
129- + // Find the start of the next experiment name
130- + start := i
131- + for i < len(goexperiment) && goexperiment[i] != ',' {
132- + i++
133- + }
134- + experiment := goexperiment[start:i]
135- + if experiment == backend {
83+ + for f := range strings.SplitSeq(goexperiment, ",") {
84+ + if f == backend {
13685+ return true
13786+ }
138- + if i < len(goexperiment) {
139- + i++ // skip the comma
140- + }
14187+ }
14288+ return false
14389+ }
14490+
91+ + // emitDeprecationWarning outputs a deprecation warning in CI environments
92+ + func emitDeprecationWarning(backend string) {
93+ + if isGitHubActions() {
94+ + fmt.Fprintf(os.Stderr,
95+ + "::warning title=GOEXPERIMENT_DEPRECATED::GOEXPERIMENT=%s is deprecated. Use GOEXPERIMENT=systemcrypto instead, or remove GOEXPERIMENT entirely as systemcrypto is now the default.\n",
96+ + backend)
97+ + } else if isAzureDevOps() {
98+ + fmt.Fprintf(os.Stderr,
99+ + "##vso[task.logissue type=warning;code=GOEXPERIMENT_DEPRECATED;]GOEXPERIMENT=%s is deprecated. Use GOEXPERIMENT=systemcrypto instead, or remove GOEXPERIMENT entirely as systemcrypto is now the default.\n",
100+ + backend)
101+ + }
102+ + // For other environments, we don't emit warnings to avoid breaking
103+ + // users who might be parsing stdout/stderr
104+ + }
105+ +
145106+ // isGitHubActions detects if we're running in GitHub Actions
146107+ func isGitHubActions() bool {
147- + githubActions, _ := syscall.Getenv("GITHUB_ACTIONS")
148- + return githubActions == "true"
108+ + return os.Getenv("GITHUB_ACTIONS") == "true"
149109+ }
150110+
151111+ // isAzureDevOps detects if we're running in Azure DevOps
152112+ func isAzureDevOps() bool {
153113+ // Azure DevOps sets TF_BUILD=True
154- + tfBuild, _ := syscall .Getenv("TF_BUILD")
114+ + tfBuild := os .Getenv("TF_BUILD")
155115+ if tfBuild == "True" || tfBuild == "true" {
156116+ return true
157117+ }
158118+
159119+ // Also check for SYSTEM_TEAMFOUNDATIONCOLLECTIONURI which is commonly set
160- + tfsUri, exists := syscall .Getenv("SYSTEM_TEAMFOUNDATIONCOLLECTIONURI")
161- + return exists && tfsUri != ""
120+ + tfsUri := os .Getenv("SYSTEM_TEAMFOUNDATIONCOLLECTIONURI")
121+ + return tfsUri != ""
162122+ }
163123+
164- + // emitGitHubActionsWarning outputs a GitHub Actions warning
165- + func emitGitHubActionsWarning(backend string) {
166- + fmt.Fprintf(os.Stderr,
167- + "::warning title=GOEXPERIMENT_DEPRECATED::GOEXPERIMENT=%s is deprecated. Use GOEXPERIMENT=systemcrypto instead, or remove GOEXPERIMENT entirely as systemcrypto is now the default.\n",
168- + backend)
169- + }
170- +
171- + // emitAzureDevOpsWarning outputs an Azure DevOps warning
172- + func emitAzureDevOpsWarning(backend string) {
173- + fmt.Fprintf(os.Stderr,
174- + "##vso[task.logissue type=warning;code=GOEXPERIMENT_DEPRECATED;]GOEXPERIMENT=%s is deprecated. Use GOEXPERIMENT=systemcrypto instead, or remove GOEXPERIMENT entirely as systemcrypto is now the default.\n",
175- + backend)
176- + }
177- diff --git a/src/crypto/internal/backend/internal/opensslsetup/opensslsetup.go b/src/crypto/internal/backend/internal/opensslsetup/opensslsetup.go
178- index d816f1be17b6a1..31c48b8d2036c7 100644
179- --- a/src/crypto/internal/backend/internal/opensslsetup/opensslsetup.go
180- +++ b/src/crypto/internal/backend/internal/opensslsetup/opensslsetup.go
181- @@ -10,6 +10,7 @@
182- package opensslsetup
183-
184- import (
185- + "crypto/internal/backend/deprecation"
186- "syscall"
187-
188- "github.com/golang-fips/openssl/v2"
189- @@ -23,6 +24,9 @@ var knownVersions = [...]string{"3", "1.1", "11", "111"}
190- const lcryptoPrefix = "libcrypto.so."
191-
192- func init() {
193- + // Emit deprecation warning in CI environments
194- + deprecation.WarnCryptoBackendDeprecated("opensslcrypto")
195- +
196- lib := library()
197- if err := openssl.Init(lib); err != nil {
198- panic("opensslcrypto: can't initialize OpenSSL " + lib + ": " + err.Error())
124+ // String returns the canonical GOEXPERIMENT string to enable this experiment
125+ // configuration. (Experiments in the same state as in the baseline are elided.)
126+ func (exp *ExperimentFlags) String() string {
0 commit comments