-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add GH
release
workflow and bump-version
action, fix hard-coded c…
…lient version (#66) ## Problem We have a private function which returns a hard-coded version number which is used when we build the user-agent for requests originating from the client. This is difficult to maintain while releasing because Go releases are handled through GitHub and Git tags, and requires us to keep things in sync manually. I also missed updating this for `v1.0.0`, so it needs to be bumped anyways. We're also missing any kind of "official" release process for the Go client, which would be beneficial in standardizing versioning and the process for releasing the client now that we're >v1.0.0. I'd rather we have a GitHub workflow similar to the other clients even if it primarily involves bumping a hard-coded version file, and pushing a tag. ## Solution - Replace the old hard-coded version with a new `internal/version.go` file which packages and holds `internal.Version` to be used within the client. This is the file that CI will manage and commit updates towards as we bump versions. - Add new GitHub action `.github/actions/bump-version` allowing us to easily bump the `currentVersion` using a specific `releaseLevel` (major, minor, patch), `isPrerelease`, and `prereleaseSuffix` if desired. This action was something @jhamon originally added to the [pinecone-python-client](https://github.com/pinecone-io/pinecone-python-client/tree/main/.github/actions/bump-version). I've lifted it here with minor alterations to support just returning a new `version_tag` rather than modifying a file using `fs` which it does in the Python repo. - I would like to work on getting this action shared properly through GitHub so that we can reuse with one source of truth, but that will take some additional work beyond the scope of this fix. I've added a ticket: https://app.asana.com/0/1203260648987893/1208039955828667/f - Add new GitHub workflow `./github/workflows/release.yaml` to facilitate releasing the Go SDK by updating `internal/version.go`, and pushing the new tag. For prerelease, we just push the tag without committing. ## Type of Change - [X] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] This change requires a documentation update - [X] Infrastructure change (CI configs, etc) - [ ] Non-code change (docs, etc) - [ ] None of the above: (explain here) ## Test I'll need to get the CI files into source before I can test the actual release process. My thinking here is I've updated the hard-coded value to the current `v1.0.0`, and I'd like to release a `v1.0.1` to fix the current problem with the user-agent not matching. I think this is reasonable, but let me know if you don't agree. The `bump-version` action itself was lifted directly from @jhamon's work including unit tests, so I think that is mostly safe. I'd spend the bulk of the review looking at my approach in `release.yaml`. --- - To see the specific tasks where the Asana app for GitHub is being used, see below: - https://app.asana.com/0/0/1206945560195919
- Loading branch information
1 parent
aee839b
commit b1754c6
Showing
12 changed files
with
4,171 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
const core = require("./core"); | ||
|
||
function bumpVersion(currentVersion, bumpType, prerelease) { | ||
let newVersion = calculateNewVersion(currentVersion, bumpType); | ||
|
||
if (prerelease) { | ||
newVersion = `${newVersion}.${prerelease}`; | ||
} | ||
core.setOutput("previous_version", currentVersion); | ||
core.setOutput("previous_version_tag", `v${currentVersion}`); | ||
core.setOutput("version", newVersion); | ||
core.setOutput("version_tag", `v${newVersion}`); | ||
} | ||
|
||
function calculateNewVersion(currentVersion, bumpType) { | ||
const [major, minor, patch] = currentVersion.split("."); | ||
let newVersion; | ||
|
||
switch (bumpType) { | ||
case "major": | ||
newVersion = `${parseInt(major) + 1}.0.0`; | ||
break; | ||
case "minor": | ||
newVersion = `${major}.${parseInt(minor) + 1}.0`; | ||
break; | ||
case "patch": | ||
newVersion = `${major}.${minor}.${parseInt(patch) + 1}`; | ||
break; | ||
default: | ||
throw new Error(`Invalid bumpType: ${bumpType}`); | ||
} | ||
|
||
return newVersion; | ||
} | ||
|
||
module.exports = { bumpVersion }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
const action = require("./action"); | ||
const core = require("./core"); | ||
|
||
jest.mock("./core"); | ||
|
||
describe("bump-version", () => { | ||
test("bump major", () => { | ||
action.bumpVersion("1.2.3", "major", ""); | ||
|
||
expect(core.setOutput).toHaveBeenCalledWith("previous_version", "1.2.3"); | ||
expect(core.setOutput).toHaveBeenCalledWith( | ||
"previous_version_tag", | ||
"v1.2.3" | ||
); | ||
expect(core.setOutput).toHaveBeenCalledWith("version", "2.0.0"); | ||
expect(core.setOutput).toHaveBeenCalledWith("version_tag", "v2.0.0"); | ||
}); | ||
|
||
test("bump minor: existing minor and patch", () => { | ||
action.bumpVersion("1.2.3", "minor", ""); | ||
|
||
expect(core.setOutput).toHaveBeenCalledWith("previous_version", "1.2.3"); | ||
expect(core.setOutput).toHaveBeenCalledWith( | ||
"previous_version_tag", | ||
"v1.2.3" | ||
); | ||
expect(core.setOutput).toHaveBeenCalledWith("version", "1.3.0"); | ||
expect(core.setOutput).toHaveBeenCalledWith("version_tag", "v1.3.0"); | ||
}); | ||
|
||
test("bump minor: with no patch", () => { | ||
action.bumpVersion("1.2.0", "minor", ""); | ||
|
||
expect(core.setOutput).toHaveBeenCalledWith("previous_version", "1.2.0"); | ||
expect(core.setOutput).toHaveBeenCalledWith( | ||
"previous_version_tag", | ||
"v1.2.0" | ||
); | ||
expect(core.setOutput).toHaveBeenCalledWith("version", "1.3.0"); | ||
expect(core.setOutput).toHaveBeenCalledWith("version_tag", "v1.3.0"); | ||
}); | ||
|
||
test("bump minor: from existing patch", () => { | ||
action.bumpVersion("2.2.3", "minor", ""); | ||
|
||
expect(core.setOutput).toHaveBeenCalledWith("previous_version", "2.2.3"); | ||
expect(core.setOutput).toHaveBeenCalledWith( | ||
"previous_version_tag", | ||
"v2.2.3" | ||
); | ||
expect(core.setOutput).toHaveBeenCalledWith("version", "2.3.0"); | ||
expect(core.setOutput).toHaveBeenCalledWith("version_tag", "v2.3.0"); | ||
}); | ||
|
||
test("bump patch: existing patch", () => { | ||
action.bumpVersion("1.2.3", "patch", ""); | ||
|
||
expect(core.setOutput).toHaveBeenCalledWith("previous_version", "1.2.3"); | ||
expect(core.setOutput).toHaveBeenCalledWith( | ||
"previous_version_tag", | ||
"v1.2.3" | ||
); | ||
expect(core.setOutput).toHaveBeenCalledWith("version", "1.2.4"); | ||
expect(core.setOutput).toHaveBeenCalledWith("version_tag", "v1.2.4"); | ||
}); | ||
|
||
test("bump patch: minor with no patch", () => { | ||
action.bumpVersion("1.2.0", "patch", ""); | ||
|
||
expect(core.setOutput).toHaveBeenCalledWith("previous_version", "1.2.0"); | ||
expect(core.setOutput).toHaveBeenCalledWith( | ||
"previous_version_tag", | ||
"v1.2.0" | ||
); | ||
expect(core.setOutput).toHaveBeenCalledWith("version", "1.2.1"); | ||
expect(core.setOutput).toHaveBeenCalledWith("version_tag", "v1.2.1"); | ||
}); | ||
|
||
test("bump patch: major with no minor or patch", () => { | ||
action.bumpVersion("1.0.0", "patch", ""); | ||
|
||
expect(core.setOutput).toHaveBeenCalledWith("previous_version", "1.0.0"); | ||
expect(core.setOutput).toHaveBeenCalledWith( | ||
"previous_version_tag", | ||
"v1.0.0" | ||
); | ||
expect(core.setOutput).toHaveBeenCalledWith("version", "1.0.1"); | ||
expect(core.setOutput).toHaveBeenCalledWith("version_tag", "v1.0.1"); | ||
}); | ||
|
||
test("bump patch: major with minor", () => { | ||
action.bumpVersion("1.1.0", "patch", ""); | ||
|
||
expect(core.setOutput).toHaveBeenCalledWith("previous_version", "1.1.0"); | ||
expect(core.setOutput).toHaveBeenCalledWith( | ||
"previous_version_tag", | ||
"v1.1.0" | ||
); | ||
expect(core.setOutput).toHaveBeenCalledWith("version", "1.1.1"); | ||
expect(core.setOutput).toHaveBeenCalledWith("version_tag", "v1.1.1"); | ||
}); | ||
|
||
test("prerelease suffix provided", () => { | ||
action.bumpVersion("1.2.3", "patch", "rc1"); | ||
|
||
expect(core.setOutput).toHaveBeenCalledWith("previous_version", "1.2.3"); | ||
expect(core.setOutput).toHaveBeenCalledWith( | ||
"previous_version_tag", | ||
"v1.2.3" | ||
); | ||
expect(core.setOutput).toHaveBeenCalledWith("version", "1.2.4.rc1"); | ||
expect(core.setOutput).toHaveBeenCalledWith("version_tag", "v1.2.4.rc1"); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
name: 'pinecone-io/bump-version' | ||
|
||
description: 'Bumps a given semantic version number based on a bumpType and prereleaseSuffix' | ||
|
||
inputs: | ||
currentVersion: | ||
description: 'The current version of the client to bump from' | ||
required: true | ||
bumpType: | ||
description: 'The type of version bump (major, minor, patch)' | ||
required: true | ||
prereleaseSuffix: | ||
description: 'Optional prerelease identifier to append to the version number' | ||
required: false | ||
default: '' | ||
|
||
outputs: | ||
version: | ||
description: 'The new version number' | ||
version_tag: | ||
description: 'The new version tag' | ||
previous_version: | ||
description: 'The previous version number' | ||
previous_version_tag: | ||
description: 'The previous version tag' | ||
|
||
runs: | ||
using: 'node20' | ||
main: 'index.js' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
// Copied these commands out of the github actions toolkit | ||
// because actually depending on @actions/core requires me to check | ||
// in node_modules and 34MB of dependencies, which I don't want to do. | ||
|
||
const fs = require("fs"); | ||
const os = require("os"); | ||
|
||
function getInput(name, options) { | ||
const val = | ||
process.env[`INPUT_${name.replace(/ /g, "_").toUpperCase()}`] || ""; | ||
if (options && options.required && !val) { | ||
throw new Error(`Input required and not supplied: ${name}`); | ||
} | ||
|
||
if (options && options.trimWhitespace === false) { | ||
return val; | ||
} | ||
|
||
return val.trim(); | ||
} | ||
|
||
function toCommandValue(input) { | ||
if (input === null || input === undefined) { | ||
return ""; | ||
} else if (typeof input === "string" || input instanceof String) { | ||
return input; | ||
} | ||
return JSON.stringify(input); | ||
} | ||
|
||
function prepareKeyValueMessage(key, value) { | ||
const delimiter = `delimiter_${Math.floor(Math.random() * 100000)}`; | ||
const convertedValue = toCommandValue(value); | ||
|
||
// These should realistically never happen, but just in case someone finds a | ||
// way to exploit uuid generation let's not allow keys or values that contain | ||
// the delimiter. | ||
if (key.includes(delimiter)) { | ||
throw new Error( | ||
`Unexpected input: name should not contain the delimiter "${delimiter}"` | ||
); | ||
} | ||
|
||
if (convertedValue.includes(delimiter)) { | ||
throw new Error( | ||
`Unexpected input: value should not contain the delimiter "${delimiter}"` | ||
); | ||
} | ||
|
||
return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`; | ||
} | ||
|
||
function setOutput(name, value) { | ||
const filePath = process.env["GITHUB_OUTPUT"] || ""; | ||
if (filePath) { | ||
return issueFileCommand("OUTPUT", prepareKeyValueMessage(name, value)); | ||
} | ||
|
||
process.stdout.write(os.EOL); | ||
issueCommand("set-output", { name }, toCommandValue(value)); | ||
} | ||
|
||
function issueFileCommand(command, message) { | ||
const filePath = process.env[`GITHUB_${command}`]; | ||
if (!filePath) { | ||
throw new Error( | ||
`Unable to find environment variable for file command ${command}` | ||
); | ||
} | ||
if (!fs.existsSync(filePath)) { | ||
throw new Error(`Missing file at path: ${filePath}`); | ||
} | ||
|
||
fs.appendFileSync(filePath, `${toCommandValue(message)}${os.EOL}`, { | ||
encoding: "utf8", | ||
}); | ||
} | ||
|
||
module.exports = { getInput, setOutput }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
const action = require("./action"); | ||
const core = require("./core"); | ||
|
||
action.bumpVersion( | ||
core.getInput("currentVersion"), | ||
core.getInput("bumpType"), | ||
core.getInput("prereleaseSuffix") | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"verbose": true | ||
} |
Oops, something went wrong.