Skip to content

Commit 9fff007

Browse files
authored
fix shell parsing in server release workflows (#1941)
Fix the server-v3/v4 release workflows to resolve remote tags without the broken nested heredoc shell pattern, while keeping the no-fallback release guards. <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Fixes the server v3/v4 release workflows by avoiding fragile shell parsing with a Node tag resolver that writes to a temp file. Keeps no-fallback guards and ensures versions advance from the latest remote tag. - **Bug Fixes** - Resolve latest remote tag with git ls-remote in Node (no local tag reliance). - Write resolver output to a temp file instead of stdout to avoid shell parsing bugs. - Block release if no remote tag exists and enforce version > highest remote. - Applies to `@browserbasehq/stagehand-server-v3` and `@browserbasehq/stagehand-server-v4`. <sup>Written for commit 2c3a827. Summary will update on new commits. <a href="https://cubic.dev/pr/browserbase/stagehand/pull/1941">Review in cubic</a></sup> <!-- End of auto-generated description by cubic. -->
1 parent 4b3596d commit 9fff007

2 files changed

Lines changed: 74 additions & 74 deletions

File tree

.github/workflows/stagehand-server-v3-release.yml

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -49,47 +49,47 @@ jobs:
4949
| awk '{sub("refs/tags/", "", $2); print $2}' \
5050
> "${remote_tags}"
5151
52-
latest_tag="$(
53-
REMOTE_TAGS_FILE="${remote_tags}" node <<'NODE'
54-
const fs = require('fs');
55-
56-
const tags = fs
57-
.readFileSync(process.env.REMOTE_TAGS_FILE, 'utf8')
58-
.split('\n')
59-
.map((line) => line.trim())
60-
.filter(Boolean);
61-
62-
const parseTag = (tag) => {
63-
const match = /^stagehand-server-v3\/v(\d+)\.(\d+)\.(\d+)$/.exec(tag);
64-
if (!match) {
65-
return null;
66-
}
67-
return match.slice(1).map((part) => Number(part));
68-
};
69-
70-
const compareVersions = (left, right) => {
71-
for (let i = 0; i < 3; i += 1) {
72-
if (left[i] !== right[i]) {
73-
return left[i] - right[i];
74-
}
75-
}
76-
return 0;
77-
};
52+
latest_tag_file="$(mktemp)"
53+
REMOTE_TAGS_FILE="${remote_tags}" LATEST_TAG_FILE="${latest_tag_file}" node <<'NODE'
54+
const fs = require('fs');
7855
79-
let best = null;
80-
for (const tag of tags) {
81-
const version = parseTag(tag);
82-
if (!version) {
83-
continue;
84-
}
85-
if (best === null || compareVersions(version, best.version) > 0) {
86-
best = { tag, version };
56+
const tags = fs
57+
.readFileSync(process.env.REMOTE_TAGS_FILE, 'utf8')
58+
.split('\n')
59+
.map((line) => line.trim())
60+
.filter(Boolean);
61+
62+
const parseTag = (tag) => {
63+
const match = /^stagehand-server-v3\/v(\d+)\.(\d+)\.(\d+)$/.exec(tag);
64+
if (!match) {
65+
return null;
66+
}
67+
return match.slice(1).map((part) => Number(part));
68+
};
69+
70+
const compareVersions = (left, right) => {
71+
for (let i = 0; i < 3; i += 1) {
72+
if (left[i] !== right[i]) {
73+
return left[i] - right[i];
8774
}
8875
}
76+
return 0;
77+
};
78+
79+
let best = null;
80+
for (const tag of tags) {
81+
const version = parseTag(tag);
82+
if (!version) {
83+
continue;
84+
}
85+
if (best === null || compareVersions(version, best.version) > 0) {
86+
best = { tag, version };
87+
}
88+
}
8989
90-
process.stdout.write(best?.tag ?? '');
91-
NODE
92-
)"
90+
fs.writeFileSync(process.env.LATEST_TAG_FILE, best?.tag ?? '', 'utf8');
91+
NODE
92+
latest_tag="$(cat "${latest_tag_file}")"
9393
9494
changed_files="$(mktemp)"
9595
if [ -n "${latest_tag}" ]; then

.github/workflows/stagehand-server-v4-release.yml

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -49,47 +49,47 @@ jobs:
4949
| awk '{sub("refs/tags/", "", $2); print $2}' \
5050
> "${remote_tags}"
5151
52-
latest_tag="$(
53-
REMOTE_TAGS_FILE="${remote_tags}" node <<'NODE'
54-
const fs = require('fs');
55-
56-
const tags = fs
57-
.readFileSync(process.env.REMOTE_TAGS_FILE, 'utf8')
58-
.split('\n')
59-
.map((line) => line.trim())
60-
.filter(Boolean);
61-
62-
const parseTag = (tag) => {
63-
const match = /^stagehand-server-v4\/v(\d+)\.(\d+)\.(\d+)$/.exec(tag);
64-
if (!match) {
65-
return null;
66-
}
67-
return match.slice(1).map((part) => Number(part));
68-
};
69-
70-
const compareVersions = (left, right) => {
71-
for (let i = 0; i < 3; i += 1) {
72-
if (left[i] !== right[i]) {
73-
return left[i] - right[i];
74-
}
75-
}
76-
return 0;
77-
};
52+
latest_tag_file="$(mktemp)"
53+
REMOTE_TAGS_FILE="${remote_tags}" LATEST_TAG_FILE="${latest_tag_file}" node <<'NODE'
54+
const fs = require('fs');
7855
79-
let best = null;
80-
for (const tag of tags) {
81-
const version = parseTag(tag);
82-
if (!version) {
83-
continue;
84-
}
85-
if (best === null || compareVersions(version, best.version) > 0) {
86-
best = { tag, version };
56+
const tags = fs
57+
.readFileSync(process.env.REMOTE_TAGS_FILE, 'utf8')
58+
.split('\n')
59+
.map((line) => line.trim())
60+
.filter(Boolean);
61+
62+
const parseTag = (tag) => {
63+
const match = /^stagehand-server-v4\/v(\d+)\.(\d+)\.(\d+)$/.exec(tag);
64+
if (!match) {
65+
return null;
66+
}
67+
return match.slice(1).map((part) => Number(part));
68+
};
69+
70+
const compareVersions = (left, right) => {
71+
for (let i = 0; i < 3; i += 1) {
72+
if (left[i] !== right[i]) {
73+
return left[i] - right[i];
8774
}
8875
}
76+
return 0;
77+
};
78+
79+
let best = null;
80+
for (const tag of tags) {
81+
const version = parseTag(tag);
82+
if (!version) {
83+
continue;
84+
}
85+
if (best === null || compareVersions(version, best.version) > 0) {
86+
best = { tag, version };
87+
}
88+
}
8989
90-
process.stdout.write(best?.tag ?? '');
91-
NODE
92-
)"
90+
fs.writeFileSync(process.env.LATEST_TAG_FILE, best?.tag ?? '', 'utf8');
91+
NODE
92+
latest_tag="$(cat "${latest_tag_file}")"
9393
9494
changed_files="$(mktemp)"
9595
if [ -n "${latest_tag}" ]; then

0 commit comments

Comments
 (0)