Skip to content

Commit a380eb1

Browse files
authored
chore(release): version-lock CLI to bundle for v0.2.0-beta.1 (#316)
* chore(release): version-lock CLI to bundle for v0.2.0-beta.1 Prep for the first bundle-versioned release. Aligns the CLI to the bundle version, points the release workflow at the bundle tag, and enforces the versioning scheme from #27. Signed-off-by: Kyle Hounslow <kylhouns@amazon.com>
1 parent 8b43dde commit a380eb1

6 files changed

Lines changed: 92 additions & 9 deletions

File tree

.github/workflows/release-drafter.yml

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: Release Workflow
33
on:
44
push:
55
tags:
6-
- "cli-installer-v*"
6+
- "v*"
77

88
jobs:
99
release-to-npm:
@@ -17,6 +17,52 @@ jobs:
1717
- name: Checkout
1818
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
1919

20+
# Enforces the version scheme from
21+
# https://github.com/opensearch-project/observability-stack/issues/27:
22+
# MAJOR.MINOR.PATCH[-(alpha|beta|rc).N]. The git tag and package.json
23+
# version must agree; the CLI clones the stack at `v<package.json version>`.
24+
- name: Validate release version
25+
id: version
26+
run: |
27+
set -euo pipefail
28+
version=$(jq -r .version aws/cli-installer/package.json)
29+
tag_version="${GITHUB_REF_NAME#v}"
30+
31+
fail() {
32+
echo "::error title=Invalid release version::$1"
33+
{
34+
echo "## ❌ Release rejected"
35+
echo ""
36+
echo "$1"
37+
echo ""
38+
echo "Expected scheme: \`vMAJOR.MINOR.PATCH[-(alpha|beta|rc).N]\`"
39+
echo "Defined in RFC #27: https://github.com/opensearch-project/observability-stack/issues/27"
40+
echo "Examples: \`v0.2.0\`, \`v0.2.0-beta.1\`, \`v1.0.0-rc.2\`"
41+
echo ""
42+
echo "Pushed git tag: \`${GITHUB_REF_NAME}\` · package.json: \`${version}\`"
43+
} >> "$GITHUB_STEP_SUMMARY"
44+
exit 1
45+
}
46+
47+
if [[ "$version" != "$tag_version" ]]; then
48+
fail "Git tag '${GITHUB_REF_NAME}' does not match package.json version '${version}'. Tag and package.json must agree — the CLI clones the stack at v<package.json version>."
49+
fi
50+
51+
stable_re='^[0-9]+\.[0-9]+\.[0-9]+$'
52+
pre_re='^[0-9]+\.[0-9]+\.[0-9]+-(alpha|beta|rc)\.[0-9]+$'
53+
54+
if [[ "$version" =~ $stable_re ]]; then
55+
echo "dist_tag=latest" >> "$GITHUB_OUTPUT"
56+
echo "is_prerelease=false" >> "$GITHUB_OUTPUT"
57+
elif [[ "$version" =~ $pre_re ]]; then
58+
echo "dist_tag=${BASH_REMATCH[1]}" >> "$GITHUB_OUTPUT"
59+
echo "is_prerelease=true" >> "$GITHUB_OUTPUT"
60+
else
61+
fail "Version '${version}' is off-scheme. Only MAJOR.MINOR.PATCH or MAJOR.MINOR.PATCH-(alpha|beta|rc).N are allowed."
62+
fi
63+
64+
echo "✅ Release version '${version}' valid (dist-tag: $(grep '^dist_tag=' "$GITHUB_OUTPUT" | cut -d= -f2))." >> "$GITHUB_STEP_SUMMARY"
65+
2066
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
2167
with:
2268
node-version: '24'
@@ -33,10 +79,11 @@ jobs:
3379

3480
- name: Publish to npm
3581
working-directory: aws/cli-installer
36-
run: npm publish
82+
run: npm publish --tag "${{ steps.version.outputs.dist_tag }}"
3783

3884
- name: Release on Github
3985
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2
4086
with:
4187
draft: false
88+
prerelease: ${{ steps.version.outputs.is_prerelease == 'true' }}
4289
generate_release_notes: true

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*.code-workspace
44
__pycache__
55
.dev
6+
.idea
67
.venv
78
venv
89
node_modules

RELEASING.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Releasing
2+
3+
How maintainers cut a release of observability-stack. Versioning follows the scheme in [RFC #27](https://github.com/opensearch-project/observability-stack/issues/27).
4+
5+
## Versioning
6+
7+
Independent bundle semver: `vMAJOR.MINOR.PATCH[-(alpha|beta|rc).N]`. Upstream component versions (OpenSearch, Data Prepper, OTel Collector, Prometheus) are pinned in `.env` and listed in the release notes, not encoded in the tag.
8+
9+
- Prerelease: `v0.2.0-beta.1`, `v1.0.0-rc.2`. Publishes to an npm dist-tag matching the qualifier (`alpha`/`beta`/`rc`), so bare `npx` stays on the stable `latest`.
10+
- Stable: `v0.2.0`. Publishes to `latest`.
11+
- `v1.0.0` is a deliberate major/GA decision (a breaking change or a GA milestone), not an automatic follow-on to the first stable.
12+
13+
The `release-drafter.yml` workflow rejects any tag that does not match the scheme, or whose version disagrees with `aws/cli-installer/package.json`.
14+
15+
## The CLI ships with the bundle
16+
17+
The CLI (`aws/cli-installer`, published to npm as `@opensearch-project/observability-stack`) is version-locked to the bundle. Its managed deploy clones the stack at the git tag matching its own version (`v${PKG_VERSION}`). So the CLI `package.json` version, the git tag, and the release must all agree. There is no CLI-only release path.
18+
19+
## Cutting a release
20+
21+
1. Open a PR that sets `aws/cli-installer/package.json` to the target version (e.g. `0.2.0-beta.1`). Sign commits for DCO (`git commit -s`). Get a maintainer review and merge to `main`.
22+
2. Tag the merged commit and push it:
23+
```
24+
git tag v0.2.0-beta.1 <sha>
25+
git push upstream v0.2.0-beta.1
26+
```
27+
The tag is the release trigger. Merging alone publishes nothing.
28+
3. The `release-to-npm` job pauses on the `release-approval` environment. A required reviewer, who cannot be the release author, opens the workflow run and approves the deployment.
29+
4. On approval, the workflow validates the version, runs tests, publishes the CLI to the correct npm dist-tag, and drafts the GitHub release. Fill in the release notes with the component-version matrix from `.env`.
30+
31+
## Promoting a prerelease to stable
32+
33+
Once the prerelease is validated and any fixes are merged, repeat the flow with the qualifier dropped: set `package.json` to `0.2.0`, tag `v0.2.0`, approve. It publishes to `latest`.

aws/cli-installer/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@opensearch-project/observability-stack",
3-
"version": "0.1.2",
3+
"version": "0.2.0-beta.1",
44
"description": "CLI for the Observability Stack",
55
"type": "module",
66
"bin": "./bin/cli-installer.mjs",

aws/cli-installer/src/ec2-demo.mjs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@ const { version: PKG_VERSION } = require('../package.json');
2828
const TAG_KEY = 'observability-stack:pipeline-name';
2929
const INSTANCE_TYPE = 't3.xlarge';
3030

31-
// The stack revision the EC2 instance clones. Defaults to the git tag matching
32-
// this CLI release so a pinned CLI deploys a pinned stack (no drift from main
33-
// HEAD at boot time). Override with OBS_STACK_REF for development.
34-
const STACK_REF = process.env.OBS_STACK_REF || `cli-installer-v${PKG_VERSION}`;
31+
// The stack revision the EC2 instance clones. Defaults to the bundle release
32+
// tag matching this CLI version (CLI is version-locked to the bundle), so a
33+
// pinned CLI deploys the matching pinned stack (no drift from main HEAD at boot
34+
// time). Override with OBS_STACK_REF for development.
35+
const STACK_REF = process.env.OBS_STACK_REF || `v${PKG_VERSION}`;
3536

3637
function tags(pipelineName, extra = {}) {
3738
return [

aws/cli-installer/test/unit.test.mjs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,11 @@ describe('EC2 demo buildUserData', () => {
160160
assert.ok(decoded.includes('docker-buildx'));
161161
});
162162

163-
it('pins the stack clone to a ref instead of tracking main HEAD', () => {
163+
it('pins the stack clone to the bundle release tag instead of tracking main HEAD', () => {
164164
const decoded = Buffer.from(_buildUserData(cfg), 'base64').toString();
165165
assert.ok(decoded.includes('--branch "$OBS_STACK_REF"'));
166-
assert.ok(decoded.includes('cli-installer-v'));
166+
// CLI is version-locked to the bundle: clone ref is `v<PKG_VERSION>`.
167+
assert.ok(/OBS_STACK_REF="v\d/.test(decoded));
167168
});
168169

169170
it('clears COMPOSE_PROFILES so local-backend services are pruned in managed mode', () => {

0 commit comments

Comments
 (0)