Skip to content

Commit a33899e

Browse files
lukasmetznerjooola
andauthored
docs: experimental features (#680)
We currently do not have a standardized approach for communicating experimental features, such as public betas or the utility functions included in our exp package. This PR documents our understanding of experimental features, how to flag them as such, and updates existing features accordingly. --------- Co-authored-by: Jonas L. <jooola@users.noreply.github.com> Co-authored-by: jo <ljonas@riseup.net>
1 parent cdef517 commit a33899e

9 files changed

Lines changed: 71 additions & 1 deletion

File tree

README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,20 @@ func main() {
5050
}
5151
```
5252

53+
## Experimental features
54+
55+
Experimental features are published as part of our regular releases (e.g. a product
56+
public beta). During an experimental phase, breaking changes on those features may occur
57+
within minor releases.
58+
59+
While experimental features will be announced in the release notes, you can also find
60+
whether a struct or function is experimental in its Go code comment:
61+
62+
```go
63+
// Experimental: $PRODUCT is experimental, breaking changes may occur within minor releases.
64+
// See https://docs.hetzner.cloud/changelog#$SLUG for more details.
65+
```
66+
5367
## Upgrading
5468

5569
### Support
@@ -83,6 +97,36 @@ This matches the official [Go Release Policy](https://go.dev/doc/devel/release#p
8397

8498
When the minimum required Go version is changed, it is announced in the release notes for that version.
8599

100+
## Development
101+
102+
### Experimental Features
103+
104+
When adding an experimental feature:
105+
106+
1. Add the marker comment above the declaration:
107+
108+
```go
109+
// Experimental: $PRODUCT is experimental, breaking changes may occur within minor releases.
110+
```
111+
112+
2. Include a link to the changelog entry:
113+
114+
```go
115+
// See https://docs.hetzner.cloud/changelog#slug for more details.
116+
```
117+
118+
3. Add an announcement to the release notes.
119+
120+
Example:
121+
122+
```go
123+
// String returns a pointer to the passed string s.
124+
//
125+
// Experimental: Product is experimental, breaking changes may occur within minor releases.
126+
// See https://docs.hetzner.cloud/changelog#slug for more details.
127+
func String(s string) *string { return Ptr(s) }
128+
```
129+
86130
## License
87131

88132
MIT license

hcloud/exp/actionutil/actions.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package actionutil
33
import "github.com/hetznercloud/hcloud-go/v2/hcloud"
44

55
// AppendNext return the action and the next actions in a new slice.
6+
//
7+
// Experimental: `exp` package is experimental, breaking changes may occur within minor releases.
68
func AppendNext(action *hcloud.Action, nextActions []*hcloud.Action) []*hcloud.Action {
79
all := make([]*hcloud.Action, 0, 1+len(nextActions))
810
all = append(all, action)

hcloud/exp/ctxutil/ctxutil.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ type key struct{}
1212
var opPathKey = key{}
1313

1414
// SetOpPath processes the operation path and save it in the context before returning it.
15+
//
16+
// Experimental: `exp` package is experimental, breaking changes may occur within minor releases.
1517
func SetOpPath(ctx context.Context, path string) context.Context {
1618
path, _, _ = strings.Cut(path, "?")
1719
path = strings.ReplaceAll(path, "%d", "-")
@@ -21,6 +23,8 @@ func SetOpPath(ctx context.Context, path string) context.Context {
2123
}
2224

2325
// OpPath returns the operation path from the context.
26+
//
27+
// Experimental: `exp` package is experimental, breaking changes may occur within minor releases.
2428
func OpPath(ctx context.Context) string {
2529
result, ok := ctx.Value(opPathKey).(string)
2630
if !ok {

hcloud/exp/doc.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
// Package exp is a namespace that holds experimental features for the `hcloud-go` library.
22
//
3-
// Breaking changes may occur without notice. Do not use in production!
3+
// Experimental: `exp` package is experimental, breaking changes may occur within minor releases.
44
package exp

hcloud/exp/kit/envutil/env.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import (
1414
// For both cases, the returned value may be empty.
1515
//
1616
// The value from the environment takes precedence over the value from the file.
17+
//
18+
// Experimental: `exp` package is experimental, breaking changes may occur within minor releases.
1719
func LookupEnvWithFile(key string) (string, error) {
1820
// Check if the value is set in the environment (e.g. HCLOUD_TOKEN)
1921
value, ok := os.LookupEnv(key)

hcloud/exp/kit/randutil/id.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88

99
// GenerateID returns a hex encoded random string with a len of 8 chars similar to
1010
// "2873fce7".
11+
//
12+
// Experimental: `exp` package is experimental, breaking changes may occur within minor releases.
1113
func GenerateID() string {
1214
b := make([]byte, 4)
1315
_, err := rand.Read(b)

hcloud/exp/kit/sshutil/ssh_key.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111

1212
// GenerateKeyPair generates a new ed25519 ssh key pair, and returns the private key and
1313
// the public key respectively.
14+
//
15+
// Experimental: `exp` package is experimental, breaking changes may occur within minor releases.
1416
func GenerateKeyPair() ([]byte, []byte, error) {
1517
pub, priv, err := ed25519.GenerateKey(nil)
1618
if err != nil {
@@ -54,6 +56,8 @@ type privateKeyWithPublicKey interface {
5456
}
5557

5658
// GeneratePublicKey generate a public key from the provided private key.
59+
//
60+
// Experimental: `exp` package is experimental, breaking changes may occur within minor releases.
5761
func GeneratePublicKey(privBytes []byte) ([]byte, error) {
5862
priv, err := ssh.ParseRawPrivateKey(privBytes)
5963
if err != nil {
@@ -74,6 +78,8 @@ func GeneratePublicKey(privBytes []byte) ([]byte, error) {
7478
}
7579

7680
// GetPublicKeyFingerprint generate the finger print for the provided public key.
81+
//
82+
// Experimental: `exp` package is experimental, breaking changes may occur within minor releases.
7783
func GetPublicKeyFingerprint(pubBytes []byte) (string, error) {
7884
pub, _, _, _, err := ssh.ParseAuthorizedKey(pubBytes)
7985
if err != nil {

hcloud/exp/labelutil/selector.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
// resources have all specified labels set.
1111
//
1212
// The selector string can be used to filter resources when listing, for example with [hcloud.ServerClient.AllWithOpts()].
13+
//
14+
// Experimental: `exp` package is experimental, breaking changes may occur within minor releases.
1315
func Selector(labels map[string]string) string {
1416
selectors := make([]string, 0, len(labels))
1517

hcloud/exp/mockutil/http.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ type Request struct {
2828
}
2929

3030
// Handler is using a [Server] to mock http requests provided by the user.
31+
//
32+
// Experimental: `exp` package is experimental, breaking changes may occur within minor releases.
3133
func Handler(t *testing.T, requests []Request) http.HandlerFunc {
3234
t.Helper()
3335

@@ -38,6 +40,8 @@ func Handler(t *testing.T, requests []Request) http.HandlerFunc {
3840
}
3941

4042
// NewServer returns a new mock server that closes itself at the end of the test.
43+
//
44+
// Experimental: `exp` package is experimental, breaking changes may occur within minor releases.
4145
func NewServer(t *testing.T, requests []Request) *Server {
4246
t.Helper()
4347

@@ -56,6 +60,8 @@ func NewServer(t *testing.T, requests []Request) *Server {
5660
// iterated over.
5761
//
5862
// A Server must be created using the [NewServer] function.
63+
//
64+
// Experimental: `exp` package is experimental, breaking changes may occur within minor releases.
5965
type Server struct {
6066
*httptest.Server
6167

@@ -66,6 +72,8 @@ type Server struct {
6672
}
6773

6874
// Expect adds requests to the list of requests expected by the [Server].
75+
//
76+
// Experimental: `exp` package is experimental, breaking changes may occur within minor releases.
6977
func (m *Server) Expect(requests []Request) {
7078
m.requests = append(m.requests, requests...)
7179
}

0 commit comments

Comments
 (0)