Skip to content

Commit 00a7448

Browse files
authored
feat: support nexus api-version header (#345)
Updated the Go SDK to set the `API-Version` header to the Nexus OpenAPI specification version when making API requests. Closes SSE-61.
1 parent 5196849 commit 00a7448

File tree

7 files changed

+115
-11
lines changed

7 files changed

+115
-11
lines changed

.github/ISSUE_TEMPLATE/release_checklist.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ labels: release
1111
After completing each task put an `x` in the corresponding box,
1212
and paste the link to the relevant PR.
1313
-->
14-
- [ ] Make sure the [VERSION](https://github.com/oxidecomputer/oxide.go/blob/main/VERSION) and [oxide/version.go](https://github.com/oxidecomputer/oxide.go/blob/main/oxide/version.go) files have the new version you want to release.
14+
- [ ] Make sure the [VERSION](https://github.com/oxidecomputer/oxide.go/blob/main/VERSION) file has the new version you want to release.
1515
- [ ] Make sure the changelog file in the `.changelog/` directory is set to the new version you want to release.
1616
- [ ] Make sure all examples and docs reference the new version.
1717
- [ ] Make sure you've pulled the latest tag on main, and generate changelog by running `make changelog`. Add the date of the release to the title, and update associated Oxide API version.
1818
- [ ] Release the new version by running `make tag`.
1919
- [ ] Update GitHub release description with release notes generated from `make changelog`.
2020
- [ ] Create a release branch from the commit of the release tag.
21-
- [ ] Bump the version in [VERSION](https://github.com/oxidecomputer/oxide.go/blob/main/VERSION) and [oxide/version.go](https://github.com/oxidecomputer/oxide.go/blob/main/oxide/version.go).
21+
- [ ] Bump the version in [VERSION](https://github.com/oxidecomputer/oxide.go/blob/main/VERSION) and run `make generate` to update the generated files.
2222
- [ ] Create a new file for the next release in [.changelog/](https://github.com/oxidecomputer/oxide.go/blob/main/.changelog/).

CONTRIBUTING.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@ $ make all
1616

1717
## Releasing a new SDK version
1818

19-
1. Make sure the following files have the new version you want to release.
20-
- [`VERSION`](./VERSION)
21-
- [`oxide/version.go`](./oxide/version.go)
19+
1. Update the [`VERSION`](./VERSION) file with the new version you want to release.
20+
- The [`oxide/version.go`](./oxide/version.go) file will be automatically updated when you run `make generate`
2221
2. Make sure you have run `make all` and pushed any changes. The release
2322
will fail if running `make all` causes any changes to the generated
2423
code.

internal/generate/main.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ func generateSDK() error {
4444
}
4545
}
4646

47+
sdkVersionFile := "../VERSION"
48+
sdkVersion, err := loadSDKVersionFromFile(sdkVersionFile)
49+
if err != nil {
50+
return err
51+
}
52+
4753
typesFile := "../../oxide/types.go"
4854
if err := generateTypes(typesFile, spec); err != nil {
4955
return err
@@ -59,9 +65,34 @@ func generateSDK() error {
5965
return err
6066
}
6167

68+
versionFile := "../../oxide/version.go"
69+
if err := generateVersion(versionFile, spec, sdkVersion); err != nil {
70+
return err
71+
}
72+
6273
return nil
6374
}
6475

76+
func loadSDKVersionFromFile(file string) (string, error) {
77+
wd, err := os.Getwd()
78+
if err != nil {
79+
return "", fmt.Errorf("error getting current working directory: %w", err)
80+
}
81+
82+
f := filepath.Join(filepath.Dir(wd), file)
83+
version, err := os.ReadFile(f)
84+
if err != nil {
85+
return "", fmt.Errorf("error retrieving SDK version: %w", err)
86+
}
87+
88+
sdkVersion := strings.TrimSpace(string(version))
89+
if sdkVersion == "" {
90+
return "", fmt.Errorf("sdk version cannot be empty: %s", file)
91+
}
92+
93+
return sdkVersion, nil
94+
}
95+
6596
func loadAPIFromFile(file string) (*openapi3.T, error) {
6697
wd, err := os.Getwd()
6798
if err != nil {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// sdkVersion is the Oxide Go SDK sdkVersion. This is used to dynamically
2+
// populate the user agent for [Client]. It is purposefully unexported to
3+
// prevent external users from reading it. The value of this comes from the
4+
// VERSION file in the root of this repository.
5+
const sdkVersion = "{{ .SDKVersion }}"
6+
7+
// openAPIVersion is the OpenAPI specification version the Oxide Go SDK was
8+
// generated from. This is used to dynamically populate the 'API-Version' header
9+
// for [Client]. It is purposefully unexported to prevent external users from
10+
// reading it. The value of this comes from the OpenAPI specification associated
11+
// with the OMICRON_VERSION file in the root of this repository.
12+
const openAPIVersion = "{{ .OpenAPIVersion }}"

internal/generate/version.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
5+
package main
6+
7+
import (
8+
"fmt"
9+
"text/template"
10+
11+
"github.com/getkin/kin-openapi/openapi3"
12+
)
13+
14+
// generateVersion generates the version.go file with both SDK and API versions.
15+
func generateVersion(file string, spec *openapi3.T, sdkVersion string) error {
16+
f, err := openGeneratedFile(file)
17+
if err != nil {
18+
return err
19+
}
20+
defer f.Close()
21+
22+
apiVersion := ""
23+
if spec.Info != nil && spec.Info.Version != "" {
24+
apiVersion = spec.Info.Version
25+
}
26+
if apiVersion == "" {
27+
return fmt.Errorf("failed generating %s: api version cannnot be empty", file)
28+
}
29+
30+
t, err := template.ParseFiles("./templates/version.tpl")
31+
if err != nil {
32+
return fmt.Errorf("failed generating %s: %w", file, err)
33+
}
34+
35+
data := struct {
36+
SDKVersion string
37+
OpenAPIVersion string
38+
}{
39+
SDKVersion: sdkVersion,
40+
OpenAPIVersion: apiVersion,
41+
}
42+
43+
if err := t.Execute(f, data); err != nil {
44+
return fmt.Errorf("failed generating %s: %w", file, err)
45+
}
46+
47+
return nil
48+
}

oxide/lib.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ func NewClient(cfg *Config) (*Client, error) {
194194

195195
// defaultUserAgent builds and returns the default user agent string.
196196
func defaultUserAgent() string {
197-
return fmt.Sprintf("oxide.go/%s", version)
197+
return fmt.Sprintf("oxide.go/%s", sdkVersion)
198198
}
199199

200200
// getProfile determines the path of the user's credentials file
@@ -305,6 +305,7 @@ func (c *Client) buildRequest(ctx context.Context, body io.Reader, method, uri s
305305

306306
req.Header.Set("Content-Type", "application/json")
307307
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.token))
308+
req.Header.Set("API-Version", openAPIVersion)
308309

309310
// Add the parameters to the url.
310311
if err := expandURL(req.URL, params); err != nil {

oxide/version.go

Lines changed: 18 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)