Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/release_checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ labels: release
After completing each task put an `x` in the corresponding box,
and paste the link to the relevant PR.
-->
- [ ] 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.
- [ ] Make sure the [VERSION](https://github.com/oxidecomputer/oxide.go/blob/main/VERSION) file has the new version you want to release.
- [ ] Make sure the changelog file in the `.changelog/` directory is set to the new version you want to release.
- [ ] Make sure all examples and docs reference the new version.
- [ ] 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.
- [ ] Release the new version by running `make tag`.
- [ ] Update GitHub release description with release notes generated from `make changelog`.
- [ ] Create a release branch from the commit of the release tag.
- [ ] 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).
- [ ] Bump the version in [VERSION](https://github.com/oxidecomputer/oxide.go/blob/main/VERSION) and run `make generate` to update the generated files.
- [ ] Create a new file for the next release in [.changelog/](https://github.com/oxidecomputer/oxide.go/blob/main/.changelog/).
5 changes: 2 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ $ make all

## Releasing a new SDK version

1. Make sure the following files have the new version you want to release.
- [`VERSION`](./VERSION)
- [`oxide/version.go`](./oxide/version.go)
1. Update the [`VERSION`](./VERSION) file with the new version you want to release.
- The [`oxide/version.go`](./oxide/version.go) file will be automatically updated when you run `make generate`
2. Make sure you have run `make all` and pushed any changes. The release
will fail if running `make all` causes any changes to the generated
code.
Expand Down
31 changes: 31 additions & 0 deletions internal/generate/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ func generateSDK() error {
}
}

sdkVersionFile := "../VERSION"
sdkVersion, err := loadSDKVersionFromFile(sdkVersionFile)
if err != nil {
return err
}

typesFile := "../../oxide/types.go"
if err := generateTypes(typesFile, spec); err != nil {
return err
Expand All @@ -59,9 +65,34 @@ func generateSDK() error {
return err
}

versionFile := "../../oxide/version.go"
if err := generateVersion(versionFile, spec, sdkVersion); err != nil {
return err
}

return nil
}

func loadSDKVersionFromFile(file string) (string, error) {
wd, err := os.Getwd()
if err != nil {
return "", fmt.Errorf("error getting current working directory: %w", err)
}

f := filepath.Join(filepath.Dir(wd), file)
version, err := os.ReadFile(f)
if err != nil {
return "", fmt.Errorf("error retrieving SDK version: %w", err)
}

sdkVersion := strings.TrimSpace(string(version))
if sdkVersion == "" {
return "", fmt.Errorf("sdk version cannot be empty: %s", file)
}

return sdkVersion, nil
}

func loadAPIFromFile(file string) (*openapi3.T, error) {
wd, err := os.Getwd()
if err != nil {
Expand Down
12 changes: 12 additions & 0 deletions internal/generate/templates/version.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// sdkVersion is the Oxide Go SDK sdkVersion. This is used to dynamically
// populate the user agent for [Client]. It is purposefully unexported to
// prevent external users from reading it. The value of this comes from the
// VERSION file in the root of this repository.
const sdkVersion = "{{ .SDKVersion }}"

// openAPIVersion is the OpenAPI specification version the Oxide Go SDK was
// generated from. This is used to dynamically populate the 'API-Version' header
// for [Client]. It is purposefully unexported to prevent external users from
// reading it. The value of this comes from the OpenAPI specification associated
// with the OMICRON_VERSION file in the root of this repository.
const openAPIVersion = "{{ .OpenAPIVersion }}"
48 changes: 48 additions & 0 deletions internal/generate/version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

package main

import (
"fmt"
"text/template"

"github.com/getkin/kin-openapi/openapi3"
)

// generateVersion generates the version.go file with both SDK and API versions.
func generateVersion(file string, spec *openapi3.T, sdkVersion string) error {
f, err := openGeneratedFile(file)
if err != nil {
return err
}
defer f.Close()

apiVersion := ""
if spec.Info != nil && spec.Info.Version != "" {
apiVersion = spec.Info.Version
}
if apiVersion == "" {
return fmt.Errorf("failed generating %s: api version cannnot be empty", file)
}

t, err := template.ParseFiles("./templates/version.tpl")
if err != nil {
return fmt.Errorf("failed generating %s: %w", file, err)
}

data := struct {
SDKVersion string
OpenAPIVersion string
}{
SDKVersion: sdkVersion,
OpenAPIVersion: apiVersion,
}

if err := t.Execute(f, data); err != nil {
return fmt.Errorf("failed generating %s: %w", file, err)
}

return nil
}
3 changes: 2 additions & 1 deletion oxide/lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ func NewClient(cfg *Config) (*Client, error) {

// defaultUserAgent builds and returns the default user agent string.
func defaultUserAgent() string {
return fmt.Sprintf("oxide.go/%s", version)
return fmt.Sprintf("oxide.go/%s", sdkVersion)
}

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

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

// Add the parameters to the url.
if err := expandURL(req.URL, params); err != nil {
Expand Down
23 changes: 18 additions & 5 deletions oxide/version.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.