diff --git a/README.md b/README.md index 3dae9185..f454c3dd 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,20 @@ func main() { } ``` +## Experimental features + +Experimental features are published as part of our regular releases (e.g. a product +public beta). During an experimental phase, breaking changes on those features may occur +within minor releases. + +While experimental features will be announced in the release notes, you can also find +whether a struct or function is experimental in its Go code comment: + +```go +// Experimental: $PRODUCT is experimental, breaking changes may occur within minor releases. +// See https://docs.hetzner.cloud/changelog#$SLUG for more details. +``` + ## Upgrading ### Support @@ -83,6 +97,36 @@ This matches the official [Go Release Policy](https://go.dev/doc/devel/release#p When the minimum required Go version is changed, it is announced in the release notes for that version. +## Development + +### Experimental Features + +When adding an experimental feature: + +1. Add the marker comment above the declaration: + + ```go + // Experimental: $PRODUCT is experimental, breaking changes may occur within minor releases. + ``` + +2. Include a link to the changelog entry: + + ```go + // See https://docs.hetzner.cloud/changelog#slug for more details. + ``` + +3. Add an announcement to the release notes. + +Example: + +```go +// String returns a pointer to the passed string s. +// +// Experimental: Product is experimental, breaking changes may occur within minor releases. +// See https://docs.hetzner.cloud/changelog#slug for more details. +func String(s string) *string { return Ptr(s) } +``` + ## License MIT license diff --git a/hcloud/exp/actionutil/actions.go b/hcloud/exp/actionutil/actions.go index f20109d3..8423a93a 100644 --- a/hcloud/exp/actionutil/actions.go +++ b/hcloud/exp/actionutil/actions.go @@ -3,6 +3,8 @@ package actionutil import "github.com/hetznercloud/hcloud-go/v2/hcloud" // AppendNext return the action and the next actions in a new slice. +// +// Experimental: `exp` package is experimental, breaking changes may occur within minor releases. func AppendNext(action *hcloud.Action, nextActions []*hcloud.Action) []*hcloud.Action { all := make([]*hcloud.Action, 0, 1+len(nextActions)) all = append(all, action) diff --git a/hcloud/exp/ctxutil/ctxutil.go b/hcloud/exp/ctxutil/ctxutil.go index de0ce95f..d9bc2d26 100644 --- a/hcloud/exp/ctxutil/ctxutil.go +++ b/hcloud/exp/ctxutil/ctxutil.go @@ -12,6 +12,8 @@ type key struct{} var opPathKey = key{} // SetOpPath processes the operation path and save it in the context before returning it. +// +// Experimental: `exp` package is experimental, breaking changes may occur within minor releases. func SetOpPath(ctx context.Context, path string) context.Context { path, _, _ = strings.Cut(path, "?") path = strings.ReplaceAll(path, "%d", "-") @@ -21,6 +23,8 @@ func SetOpPath(ctx context.Context, path string) context.Context { } // OpPath returns the operation path from the context. +// +// Experimental: `exp` package is experimental, breaking changes may occur within minor releases. func OpPath(ctx context.Context) string { result, ok := ctx.Value(opPathKey).(string) if !ok { diff --git a/hcloud/exp/doc.go b/hcloud/exp/doc.go index 96506ae2..2999aae1 100644 --- a/hcloud/exp/doc.go +++ b/hcloud/exp/doc.go @@ -1,4 +1,4 @@ // Package exp is a namespace that holds experimental features for the `hcloud-go` library. // -// Breaking changes may occur without notice. Do not use in production! +// Experimental: `exp` package is experimental, breaking changes may occur within minor releases. package exp diff --git a/hcloud/exp/kit/envutil/env.go b/hcloud/exp/kit/envutil/env.go index 7e6aa6ee..05ea76de 100644 --- a/hcloud/exp/kit/envutil/env.go +++ b/hcloud/exp/kit/envutil/env.go @@ -14,6 +14,8 @@ import ( // For both cases, the returned value may be empty. // // The value from the environment takes precedence over the value from the file. +// +// Experimental: `exp` package is experimental, breaking changes may occur within minor releases. func LookupEnvWithFile(key string) (string, error) { // Check if the value is set in the environment (e.g. HCLOUD_TOKEN) value, ok := os.LookupEnv(key) diff --git a/hcloud/exp/kit/randutil/id.go b/hcloud/exp/kit/randutil/id.go index 75dab5f4..b568dc94 100644 --- a/hcloud/exp/kit/randutil/id.go +++ b/hcloud/exp/kit/randutil/id.go @@ -8,6 +8,8 @@ import ( // GenerateID returns a hex encoded random string with a len of 8 chars similar to // "2873fce7". +// +// Experimental: `exp` package is experimental, breaking changes may occur within minor releases. func GenerateID() string { b := make([]byte, 4) _, err := rand.Read(b) diff --git a/hcloud/exp/kit/sshutil/ssh_key.go b/hcloud/exp/kit/sshutil/ssh_key.go index 4465d5c7..c6834841 100644 --- a/hcloud/exp/kit/sshutil/ssh_key.go +++ b/hcloud/exp/kit/sshutil/ssh_key.go @@ -11,6 +11,8 @@ import ( // GenerateKeyPair generates a new ed25519 ssh key pair, and returns the private key and // the public key respectively. +// +// Experimental: `exp` package is experimental, breaking changes may occur within minor releases. func GenerateKeyPair() ([]byte, []byte, error) { pub, priv, err := ed25519.GenerateKey(nil) if err != nil { @@ -54,6 +56,8 @@ type privateKeyWithPublicKey interface { } // GeneratePublicKey generate a public key from the provided private key. +// +// Experimental: `exp` package is experimental, breaking changes may occur within minor releases. func GeneratePublicKey(privBytes []byte) ([]byte, error) { priv, err := ssh.ParseRawPrivateKey(privBytes) if err != nil { @@ -74,6 +78,8 @@ func GeneratePublicKey(privBytes []byte) ([]byte, error) { } // GetPublicKeyFingerprint generate the finger print for the provided public key. +// +// Experimental: `exp` package is experimental, breaking changes may occur within minor releases. func GetPublicKeyFingerprint(pubBytes []byte) (string, error) { pub, _, _, _, err := ssh.ParseAuthorizedKey(pubBytes) if err != nil { diff --git a/hcloud/exp/labelutil/selector.go b/hcloud/exp/labelutil/selector.go index 0d9d5006..303b64a5 100644 --- a/hcloud/exp/labelutil/selector.go +++ b/hcloud/exp/labelutil/selector.go @@ -10,6 +10,8 @@ import ( // resources have all specified labels set. // // The selector string can be used to filter resources when listing, for example with [hcloud.ServerClient.AllWithOpts()]. +// +// Experimental: `exp` package is experimental, breaking changes may occur within minor releases. func Selector(labels map[string]string) string { selectors := make([]string, 0, len(labels)) diff --git a/hcloud/exp/mockutil/http.go b/hcloud/exp/mockutil/http.go index 26ff4874..26a26baf 100644 --- a/hcloud/exp/mockutil/http.go +++ b/hcloud/exp/mockutil/http.go @@ -28,6 +28,8 @@ type Request struct { } // Handler is using a [Server] to mock http requests provided by the user. +// +// Experimental: `exp` package is experimental, breaking changes may occur within minor releases. func Handler(t *testing.T, requests []Request) http.HandlerFunc { t.Helper() @@ -38,6 +40,8 @@ func Handler(t *testing.T, requests []Request) http.HandlerFunc { } // NewServer returns a new mock server that closes itself at the end of the test. +// +// Experimental: `exp` package is experimental, breaking changes may occur within minor releases. func NewServer(t *testing.T, requests []Request) *Server { t.Helper() @@ -56,6 +60,8 @@ func NewServer(t *testing.T, requests []Request) *Server { // iterated over. // // A Server must be created using the [NewServer] function. +// +// Experimental: `exp` package is experimental, breaking changes may occur within minor releases. type Server struct { *httptest.Server @@ -66,6 +72,8 @@ type Server struct { } // Expect adds requests to the list of requests expected by the [Server]. +// +// Experimental: `exp` package is experimental, breaking changes may occur within minor releases. func (m *Server) Expect(requests []Request) { m.requests = append(m.requests, requests...) }