testronaut 1.3.4 → 1.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
name: Prepare Package Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
release_type:
|
|
7
|
+
description: Semver increment to prepare
|
|
8
|
+
required: true
|
|
9
|
+
type: choice
|
|
10
|
+
default: patch
|
|
11
|
+
options:
|
|
12
|
+
- patch
|
|
13
|
+
- minor
|
|
14
|
+
- major
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
|
|
19
|
+
concurrency:
|
|
20
|
+
group: prepare-package-release
|
|
21
|
+
cancel-in-progress: false
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
authorize-release:
|
|
25
|
+
name: Authorize Release
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
steps:
|
|
28
|
+
- name: Require main branch
|
|
29
|
+
run: |
|
|
30
|
+
if [ "${GITHUB_REF_NAME}" != "main" ]; then
|
|
31
|
+
echo "Manual release preparation is only allowed from main."
|
|
32
|
+
exit 1
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
- name: Require repository admin permission
|
|
36
|
+
uses: actions/github-script@v7
|
|
37
|
+
with:
|
|
38
|
+
script: |
|
|
39
|
+
const owner = context.repo.owner;
|
|
40
|
+
const repo = context.repo.repo;
|
|
41
|
+
const actor = context.actor;
|
|
42
|
+
|
|
43
|
+
if (owner.toLowerCase() === actor.toLowerCase()) {
|
|
44
|
+
core.info(`Actor ${actor} matches the repository owner and is treated as admin.`);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const response = await github.rest.repos.getCollaboratorPermissionLevel({
|
|
49
|
+
owner,
|
|
50
|
+
repo,
|
|
51
|
+
username: actor,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const { permission, role_name: roleName } = response.data;
|
|
55
|
+
core.info(`Actor ${actor} permission=${permission}, role_name=${roleName}`);
|
|
56
|
+
|
|
57
|
+
if (permission !== "admin" && roleName !== "admin") {
|
|
58
|
+
core.setFailed(`Only repository admins can prepare package releases. ${actor} has ${roleName || permission}.`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
prepare-release:
|
|
62
|
+
name: Prepare Release Pull Request
|
|
63
|
+
needs: authorize-release
|
|
64
|
+
runs-on: ubuntu-latest
|
|
65
|
+
permissions:
|
|
66
|
+
# Required because this workflow pushes a release branch and opens a PR.
|
|
67
|
+
contents: write
|
|
68
|
+
pull-requests: write
|
|
69
|
+
steps:
|
|
70
|
+
- name: Checkout
|
|
71
|
+
uses: actions/checkout@v4
|
|
72
|
+
with:
|
|
73
|
+
fetch-depth: 0
|
|
74
|
+
|
|
75
|
+
- name: Setup Node
|
|
76
|
+
uses: actions/setup-node@v4
|
|
77
|
+
with:
|
|
78
|
+
node-version: 24
|
|
79
|
+
cache: npm
|
|
80
|
+
|
|
81
|
+
- name: Install dependencies
|
|
82
|
+
run: npm ci
|
|
83
|
+
|
|
84
|
+
- name: Run automated test suite
|
|
85
|
+
run: npm test
|
|
86
|
+
|
|
87
|
+
- name: Bump package version
|
|
88
|
+
run: npm version "${{ inputs.release_type }}" --no-git-tag-version
|
|
89
|
+
|
|
90
|
+
- name: Read new version
|
|
91
|
+
id: version
|
|
92
|
+
run: |
|
|
93
|
+
VERSION="$(node -e 'process.stdout.write(require("./package.json").version)')"
|
|
94
|
+
echo "value=${VERSION}" >> "$GITHUB_OUTPUT"
|
|
95
|
+
echo "branch=release/v${VERSION}" >> "$GITHUB_OUTPUT"
|
|
96
|
+
|
|
97
|
+
- name: Ensure release branch is not already open
|
|
98
|
+
env:
|
|
99
|
+
RELEASE_BRANCH: ${{ steps.version.outputs.branch }}
|
|
100
|
+
run: |
|
|
101
|
+
if git ls-remote --exit-code --heads origin "${RELEASE_BRANCH}" >/dev/null 2>&1; then
|
|
102
|
+
echo "Release branch ${RELEASE_BRANCH} already exists on origin."
|
|
103
|
+
exit 1
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
- name: Create release branch
|
|
107
|
+
env:
|
|
108
|
+
RELEASE_BRANCH: ${{ steps.version.outputs.branch }}
|
|
109
|
+
run: git switch -c "${RELEASE_BRANCH}"
|
|
110
|
+
|
|
111
|
+
- name: Configure git author
|
|
112
|
+
run: |
|
|
113
|
+
git config user.name "github-actions[bot]"
|
|
114
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
115
|
+
|
|
116
|
+
- name: Commit release version
|
|
117
|
+
env:
|
|
118
|
+
VERSION: ${{ steps.version.outputs.value }}
|
|
119
|
+
run: |
|
|
120
|
+
git add package.json package-lock.json
|
|
121
|
+
git commit -m "chore(release): v${VERSION}"
|
|
122
|
+
|
|
123
|
+
- name: Push release branch
|
|
124
|
+
env:
|
|
125
|
+
RELEASE_BRANCH: ${{ steps.version.outputs.branch }}
|
|
126
|
+
run: git push --set-upstream origin "${RELEASE_BRANCH}"
|
|
127
|
+
|
|
128
|
+
- name: Open release pull request
|
|
129
|
+
id: pull-request
|
|
130
|
+
uses: actions/github-script@v7
|
|
131
|
+
env:
|
|
132
|
+
RELEASE_BRANCH: ${{ steps.version.outputs.branch }}
|
|
133
|
+
VERSION: ${{ steps.version.outputs.value }}
|
|
134
|
+
with:
|
|
135
|
+
script: |
|
|
136
|
+
const owner = context.repo.owner;
|
|
137
|
+
const repo = context.repo.repo;
|
|
138
|
+
const head = process.env.RELEASE_BRANCH;
|
|
139
|
+
const version = process.env.VERSION;
|
|
140
|
+
|
|
141
|
+
const pr = await github.rest.pulls.create({
|
|
142
|
+
owner,
|
|
143
|
+
repo,
|
|
144
|
+
title: `chore(release): v${version}`,
|
|
145
|
+
head,
|
|
146
|
+
base: "main",
|
|
147
|
+
body: [
|
|
148
|
+
`Prepares \`v${version}\` for npm publication.`,
|
|
149
|
+
"",
|
|
150
|
+
"After this pull request merges into `main`, the publish workflow will release the package to npm.",
|
|
151
|
+
].join("\n"),
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
core.setOutput("url", pr.data.html_url);
|
|
155
|
+
|
|
156
|
+
- name: Write job summary
|
|
157
|
+
env:
|
|
158
|
+
VERSION: ${{ steps.version.outputs.value }}
|
|
159
|
+
RELEASE_BRANCH: ${{ steps.version.outputs.branch }}
|
|
160
|
+
PR_URL: ${{ steps.pull-request.outputs.url }}
|
|
161
|
+
run: |
|
|
162
|
+
{
|
|
163
|
+
echo "## Release PR created"
|
|
164
|
+
echo
|
|
165
|
+
echo "- Version: \`${VERSION}\`"
|
|
166
|
+
echo "- Release branch: \`${RELEASE_BRANCH}\`"
|
|
167
|
+
echo "- Pull request: ${PR_URL}"
|
|
168
|
+
} >> "$GITHUB_STEP_SUMMARY"
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
name: Publish Package
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
paths:
|
|
8
|
+
- package.json
|
|
9
|
+
- package-lock.json
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: write
|
|
14
|
+
id-token: write
|
|
15
|
+
|
|
16
|
+
concurrency:
|
|
17
|
+
group: publish-package
|
|
18
|
+
cancel-in-progress: false
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
publish-package:
|
|
22
|
+
name: Publish Package
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
environment:
|
|
25
|
+
# Use the same environment name in npm trusted publisher settings if you
|
|
26
|
+
# want npm to bind publishing to this protected environment.
|
|
27
|
+
name: package-publish
|
|
28
|
+
steps:
|
|
29
|
+
- name: Checkout
|
|
30
|
+
uses: actions/checkout@v4
|
|
31
|
+
with:
|
|
32
|
+
fetch-depth: 0
|
|
33
|
+
|
|
34
|
+
- name: Detect release version
|
|
35
|
+
id: release
|
|
36
|
+
env:
|
|
37
|
+
BEFORE_SHA: ${{ github.event.before }}
|
|
38
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
39
|
+
REF_NAME: ${{ github.ref_name }}
|
|
40
|
+
run: |
|
|
41
|
+
VERSION="$(node -e 'process.stdout.write(require("./package.json").version)')"
|
|
42
|
+
PACKAGE_NAME="$(node -e 'process.stdout.write(require("./package.json").name)')"
|
|
43
|
+
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
|
44
|
+
echo "package_name=${PACKAGE_NAME}" >> "$GITHUB_OUTPUT"
|
|
45
|
+
|
|
46
|
+
if [ "${EVENT_NAME}" = "workflow_dispatch" ]; then
|
|
47
|
+
if [ "${REF_NAME}" != "main" ]; then
|
|
48
|
+
echo "Manual publishing is only allowed from main."
|
|
49
|
+
exit 1
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
echo "should_publish=true" >> "$GITHUB_OUTPUT"
|
|
53
|
+
exit 0
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
if [ -z "${BEFORE_SHA}" ] || [ "${BEFORE_SHA}" = "0000000000000000000000000000000000000000" ]; then
|
|
57
|
+
echo "should_publish=true" >> "$GITHUB_OUTPUT"
|
|
58
|
+
exit 0
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
PREVIOUS_VERSION="$(git show "${BEFORE_SHA}:package.json" | node -e 'let data=""; process.stdin.on("data", chunk => data += chunk); process.stdin.on("end", () => process.stdout.write(JSON.parse(data).version));')"
|
|
62
|
+
|
|
63
|
+
if [ "${PREVIOUS_VERSION}" = "${VERSION}" ]; then
|
|
64
|
+
echo "Version is unchanged at ${VERSION}; skipping publish."
|
|
65
|
+
echo "should_publish=false" >> "$GITHUB_OUTPUT"
|
|
66
|
+
else
|
|
67
|
+
echo "Version changed from ${PREVIOUS_VERSION} to ${VERSION}."
|
|
68
|
+
echo "should_publish=true" >> "$GITHUB_OUTPUT"
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
- name: Setup Node
|
|
72
|
+
if: steps.release.outputs.should_publish == 'true'
|
|
73
|
+
uses: actions/setup-node@v4
|
|
74
|
+
with:
|
|
75
|
+
node-version: 24
|
|
76
|
+
cache: npm
|
|
77
|
+
registry-url: https://registry.npmjs.org
|
|
78
|
+
|
|
79
|
+
- name: Install dependencies
|
|
80
|
+
if: steps.release.outputs.should_publish == 'true'
|
|
81
|
+
run: npm ci
|
|
82
|
+
|
|
83
|
+
- name: Run automated test suite
|
|
84
|
+
if: steps.release.outputs.should_publish == 'true'
|
|
85
|
+
run: npm test
|
|
86
|
+
|
|
87
|
+
- name: Check whether version already exists on npm
|
|
88
|
+
if: steps.release.outputs.should_publish == 'true'
|
|
89
|
+
id: npm-check
|
|
90
|
+
env:
|
|
91
|
+
PACKAGE_NAME: ${{ steps.release.outputs.package_name }}
|
|
92
|
+
VERSION: ${{ steps.release.outputs.version }}
|
|
93
|
+
run: |
|
|
94
|
+
if npm view "${PACKAGE_NAME}@${VERSION}" version >/dev/null 2>&1; then
|
|
95
|
+
echo "should_publish=false" >> "$GITHUB_OUTPUT"
|
|
96
|
+
echo "Version ${VERSION} is already published to npm."
|
|
97
|
+
else
|
|
98
|
+
echo "should_publish=true" >> "$GITHUB_OUTPUT"
|
|
99
|
+
echo "Version ${VERSION} is not yet published to npm."
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
- name: Publish to npm with trusted publishing
|
|
103
|
+
if: steps.release.outputs.should_publish == 'true' && steps.npm-check.outputs.should_publish == 'true'
|
|
104
|
+
run: npm publish --provenance --access public
|
|
105
|
+
|
|
106
|
+
- name: Tag published version
|
|
107
|
+
if: steps.release.outputs.should_publish == 'true' && steps.npm-check.outputs.should_publish == 'true'
|
|
108
|
+
env:
|
|
109
|
+
VERSION: ${{ steps.release.outputs.version }}
|
|
110
|
+
run: |
|
|
111
|
+
if git rev-parse "v${VERSION}" >/dev/null 2>&1; then
|
|
112
|
+
echo "Tag v${VERSION} already exists locally."
|
|
113
|
+
exit 0
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
git config user.name "github-actions[bot]"
|
|
117
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
118
|
+
git tag "v${VERSION}"
|
|
119
|
+
git push origin "refs/tags/v${VERSION}"
|
|
120
|
+
|
|
121
|
+
- name: Write job summary
|
|
122
|
+
env:
|
|
123
|
+
VERSION: ${{ steps.release.outputs.version }}
|
|
124
|
+
SHOULD_PUBLISH: ${{ steps.release.outputs.should_publish }}
|
|
125
|
+
NPM_PUBLISH: ${{ steps.npm-check.outputs.should_publish }}
|
|
126
|
+
run: |
|
|
127
|
+
{
|
|
128
|
+
echo "## Publish summary"
|
|
129
|
+
echo
|
|
130
|
+
echo "- Version: \`${VERSION}\`"
|
|
131
|
+
echo "- Trigger requested publish: \`${SHOULD_PUBLISH:-false}\`"
|
|
132
|
+
echo "- npm publish executed: \`${NPM_PUBLISH:-false}\`"
|
|
133
|
+
} >> "$GITHUB_STEP_SUMMARY"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "testronaut",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.5",
|
|
4
4
|
"main": "./runner/testronaut.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"testronaut": "bin/cli.js"
|
|
@@ -19,6 +19,10 @@
|
|
|
19
19
|
"author": "",
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"description": "",
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/mission-testronaut/testronaut-cli"
|
|
25
|
+
},
|
|
22
26
|
"dependencies": {
|
|
23
27
|
"@dqbd/tiktoken": "^1.0.21",
|
|
24
28
|
"@google/generative-ai": "^0.24.1",
|
|
@@ -35,8 +35,8 @@ export function generateHtmlReport(report, outputPath) {
|
|
|
35
35
|
// Escaping helpers for text and HTML attributes
|
|
36
36
|
const esc = (s) => String(s ?? '')
|
|
37
37
|
.replace(/&/g, '&').replace(/</g, '<')
|
|
38
|
-
.replace(/>/g, '>')
|
|
39
|
-
|
|
38
|
+
.replace(/>/g, '>')
|
|
39
|
+
.replace(/"/g, '"');
|
|
40
40
|
const badge = (status) =>
|
|
41
41
|
status === 'passed' ? '✅ Passed' :
|
|
42
42
|
status === 'failed' ? '❌ Failed' : (status || '—');
|
|
@@ -70,7 +70,7 @@ export function generateHtmlReport(report, outputPath) {
|
|
|
70
70
|
? step.summary.trim()
|
|
71
71
|
: '';
|
|
72
72
|
const planSpan = plan
|
|
73
|
-
? `<span class="plan" title="${
|
|
73
|
+
? `<span class="plan" title="${esc(plan)}">${esc(plan)}</span>`
|
|
74
74
|
: '';
|
|
75
75
|
|
|
76
76
|
return `
|
|
@@ -78,7 +78,7 @@ export function generateHtmlReport(report, outputPath) {
|
|
|
78
78
|
<summary>
|
|
79
79
|
<span class="turn">Turn ${esc((step.turn ?? idx) + 1)}${esc(attemptLabel)}</span>
|
|
80
80
|
${planSpan}
|
|
81
|
-
<span class="step-result ${ok ? 'ok' : 'bad'}" ${resultTooltip ? `title="${
|
|
81
|
+
<span class="step-result ${ok ? 'ok' : 'bad'}" ${resultTooltip ? `title="${esc(resultTooltip)}"` : ''}>${esc(resultRaw)}</span>
|
|
82
82
|
<span class="tokens">tokens: ${esc(step.tokensUsed ?? '—')} / total: ${esc(step.totalTokensUsed ?? '—')}</span>
|
|
83
83
|
</summary>
|
|
84
84
|
<pre class="events">${esc(events.join('\n')) || '(no events)'}</pre>
|