Skip to content

release: v0.3.0#230

Merged
jangjos-128 merged 1 commit into
mainfrom
release/v0.3.0
Jul 9, 2026
Merged

release: v0.3.0#230
jangjos-128 merged 1 commit into
mainfrom
release/v0.3.0

Conversation

@jangjos-128

@jangjos-128 jangjos-128 commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

TestSprite CLI v0.3.0

This PR is the release snapshot for v0.3.0, promoting everything merged since v0.2.0 (2026-06-29) — including ~60 community contributions. Full details in CHANGELOG.md under [0.3.0].

Highlights

New commands

  • testsprite doctor — one-command environment diagnostic (Node version, credentials, endpoint reachability, installed skills)
  • test scaffold — generate a starter plan / backend test skeleton
  • test lint — offline validation of plan & steps files before they hit the server
  • test diff <run-a> <run-b> — isolate what changed between two runs
  • test flaky <test-id> — repeat-run flaky-test detector with a stability verdict and CI-gateable exit code
  • agent status — see which TestSprite skills are installed per agent target and whether they're current

CI & environment

  • JUnit XML report export for batch runs (--report junit --report-file <path>)
  • Proxy support (HTTPS_PROXY / HTTP_PROXY / NO_PROXY) and NO_COLOR support
  • New agent install targets: GitHub Copilot, Windsurf, Kiro (experimental)
  • Non-blocking "new version available" notice (24h-cached, silenced in CI/JSON mode)

Behavior changes

  • Node.js 20 is now the minimum supported runtime
  • Graceful shutdown on termination signals; EPIPE-safe piped output
  • Interactive prompts moved to stderr — stdout stays pure for machine consumers

Plus a large batch of fixes across timeouts/polling, batch rerun exit codes, input validation, failure-bundle handling, and two security hardenings (credential INI injection, symlink fail-close in agent install). See the changelog for the complete list.

About this release process

Starting with this release, snapshots land as a regular commit on top of main — no history rewrite. Open PRs are unaffected by the merge itself, though you may need to rebase your branch onto the new main afterward. If your PR was affected by the previous release process, see the maintainer comment on your PR — your work is safe and we'd love to get it re-opened under your name.

After merge

  • v0.3.0 will be published to npm as @testsprite/testsprite-cli@0.3.0
  • A v0.3.0 tag + GitHub Release will follow

Thank you to everyone who contributed to this release!

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features
    • Added testsprite doctor, testsprite usage (credits), and expanded Agent commands (including agent status).
    • Added project credential and project auto-auth, plus testsprite test diff and testsprite test artifact get.
  • Bug Fixes
    • testsprite agent install now defaults when --target resolves to empty (non-TTY).
    • Backend test creation/code-put advisories now display as non-fatal warnings on stderr.
  • Documentation
    • Updated README, reference docs, auth guidance, and contribution/PR gate instructions, including the new 0.3.0 changelog entry.

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The PR adds 0.3.0 CLI functionality, project credential and auto-auth commands, updated test behavior, release documentation, repository automation workflows, contribution policies, and hermetic cross-platform test setup.

Changes

CLI and release behavior

Layer / File(s) Summary
Project credential, auto-auth, and validation
src/commands/project.ts, src/commands/project.test.ts
Adds project credential and auto-auth commands, removes update descriptions, and tightens project-name validation.
Test creation and run messaging
src/commands/test.ts, src/commands/test.test.ts
Emits backend warnings to stderr, improves frontend flag validation, and updates unified test-run help semantics.
Agent installation and initialization
src/commands/agent.*, src/commands/init.*
Defaults non-TTY installs to Claude and revises initialization next steps.
Release metadata and documentation
package.json, src/version.ts, CHANGELOG.md, README.md, DOCUMENTATION.md, skills/*, src/commands/usage.ts, src/index.ts
Updates 0.3.0 metadata and documents commands, credentials, diagnostics, exit codes, and dry-run behavior.

Repository automation and contribution policy

Layer / File(s) Summary
Issue-first contribution policy
.github/PULL_REQUEST_TEMPLATE.md, CONTRIBUTING.md
Documents issue assignment and pull request gate requirements alongside scope and security policies.
Pull request issue-link gate
.github/workflows/pr-triage.yml
Resolves linked issues, synchronizes labels and sticky comments, and fails newer unready pull requests.
CI status nudging
.github/workflows/ci-nudge.yml
Tracks workflow checks and creates or updates sticky failure and recovery comments.
Repository maintenance workflows
.github/workflows/issue-triage.yml, .github/workflows/stale.yml, .gitattributes
Migrates App secrets, configures stale processing, and enforces text and binary attributes.

Test infrastructure

Layer / File(s) Summary
Hermetic test environment
test/helpers/hermetic-env.ts, vitest.config.ts
Redirects home directories, preserves Volta resolution, and removes ambient TestSprite variables from Vitest runs.
Cross-platform filesystem tests
src/lib/*test.ts
Normalizes paths, handles Windows permission differences, and strengthens path and line-ending assertions.
CLI subprocess isolation
test/cli.subprocess.test.ts
Controls child-process home paths, skips POSIX-only mode assertions on Windows, and uses in-process cleanup.

Estimated code review effort: 5 (Critical) | ~90 minutes

Sequence Diagram(s)

sequenceDiagram
  participant PR as Pull request
  participant Gate as PR triage workflow
  participant Issues as GitHub Issues
  participant Checks as GitHub checks
  PR->>Gate: pull request event
  Gate->>Issues: resolve linked issues and assignees
  Gate->>PR: update label and sticky comment
  Gate->>Checks: set gate result
Loading

Possibly related PRs

Suggested reviewers: zeshi-du, ruili-testsprite

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 34.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: preparing the v0.3.0 release.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch release/v0.3.0

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🧹 Nitpick comments (3)
src/commands/project.test.ts (1)

949-1167: 📐 Maintainability & Code Quality | 🔵 Trivial

Missing dry-run test coverage for runCredential/runAutoAuth.

None of these suites exercise opts.dryRun. As flagged in project.ts, both handlers read --credential-file/--*-file secrets and skip emitDryRunBanner before the dry-run check — a dry-run test here would have caught it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/commands/project.test.ts` around lines 949 - 1167, Add dry-run coverage
for both runCredential and runAutoAuth so the suites verify opts.dryRun
behavior. Update the tests around runCredential and runAutoAuth to assert that
when dryRun is true, no fetch call is made and the dry-run path is exercised
before any secret-file handling. Use the existing helpers/cases in
runCredential, runAutoAuth, and captureFetch to locate the assertions and add a
dedicated dry-run test for each handler.
.github/workflows/pr-triage.yml (1)

57-62: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Scope the minted App token to least privilege.

create-github-app-token mints a token carrying all of the installation's permissions unless you pass explicit permission-* inputs. This gate only needs to comment and label PRs, so constrain it:

🔒 Proposed scoping
         uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
         with:
           app-id: ${{ secrets.TESTSPRITE_HOB_APP_ID || secrets.ALFHEIM_AGENT_APP_ID }}
           private-key: ${{ secrets.TESTSPRITE_HOB_PRIVATE_KEY || secrets.ALFHEIM_AGENT_PRIVATE_KEY }}
+          permission-issues: write
+          permission-pull-requests: write

As per path instructions "Prefer least-privilege permissions: blocks". Please confirm the permission-* input names for the pinned v3.2.0 action.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/pr-triage.yml around lines 57 - 62, The token minted in
the pr-triage workflow is currently unscoped, so update the
create-github-app-token step to pass explicit permission-* inputs for only what
the job needs, and verify the exact v3.2.0 input names on that action before
changing it. Use the app-token step as the anchor, and constrain the permissions
to PR commenting/labeling only so the minted installation token follows least
privilege.

Sources: Path instructions, Linters/SAST tools

.github/workflows/ci-nudge.yml (1)

88-95: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

FIX keys for matrix jobs must match their expanded check-run names.

The "Unit Tests" and "Build" keys won't match any actual check-runs because those jobs use matrix strategies:

  • Job test has name: Unit Tests (Node ${{ matrix.node-version }}) — expands to "Unit Tests (Node 20)" and "Unit Tests (Node 22)"
  • Job build has name: Build (Node ${{ matrix.node-version }}) — expands to "Build (Node 20)" and "Build (Node 22)"

The lookup at line 110 (FIX[c.name]) will fail for these and silently fall back to "see the logs for details" whenever a matrix variant fails. Update the FIX keys to match the actual check-run names, or consider a pattern-based lookup if all variants should share the same fix instruction.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci-nudge.yml around lines 88 - 95, The FIX lookup in the
CI nudge workflow does not match matrix-expanded check-run names for the `test`
and `build` jobs, so `FIX[c.name]` falls back incorrectly. Update the `FIX` map
in the workflow to use the actual check-run names emitted by `test` and `build`
(for example the Node-specific variants), or switch the lookup logic to handle
matrix prefixes in the same place where `FIX[c.name]` is used.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci-nudge.yml:
- Around line 77-81: The filtering in the check-run handling is too broad
because uses of checks.listForRef and the current ours filter only by app.slug
can include unrelated GitHub Actions runs. Update the logic around the checks,
ours, failing, and pending variables to narrow results to the CI workflow/job
names or the FIX keys used by this nudge script, so only the intended CI check
runs affect pending and failure detection.

In @.github/workflows/issue-triage.yml:
- Around line 42-47: The issue is that the issue-triage workflow’s
`actions/create-github-app-token` step mints a broadly scoped GitHub App token
by relying on default installation permissions. Update the `app-token` step in
`issue-triage.yml` to pass only the explicit `permission-*` inputs needed for
this job’s comment-posting behavior, rather than inheriting all app permissions.
Use the existing `app-token` step and `actions/create-github-app-token` action
as the place to scope these permissions, and keep the workflow aligned with
least-privilege `permissions:` guidance.

In `@CHANGELOG.md`:
- Line 27: Update the release note entry to match the actual runtime floor
enforced by the CLI and documented in package.json/docs. In CHANGELOG.md, adjust
the Node.js support statement so it does not imply all Node 20 versions are
supported; reference the CLI startup check and keep the wording aligned with the
minimum versions (20.19+, 22.13+, 24+).

In `@CONTRIBUTING.md`:
- Around line 59-63: The `agent install` target list in the contributor policy
is out of sync with the released target set. Update the targets mentioned in the
`agent install` section of CONTRIBUTING.md to match the current supported list,
ensuring `copilot` is included and `gemini` is no longer shown as in progress;
keep the maintenance/proposal language aligned with the updated targets.
- Around line 64-68: The outbound network calls policy in CONTRIBUTING.md is out
of sync with the CLI docs around the npm update check. Update the wording near
the version-check exception so it matches the behavior in the CLI docs: the
check should be described as suppressed for interactive-only sessions when
TESTSPRITE_NO_UPDATE_NOTIFIER=1, --dry-run, --output json, or non-TTY stderr are
in effect. Keep the existing scope of the exception intact while aligning the
suppression conditions with the documented behavior.

In `@DOCUMENTATION.md`:
- Around line 610-617: The scope table is missing the new `test scaffold` and
`test lint` write surfaces even though they are marked as `write:tests`
elsewhere. Update the permissions matrix in `DOCUMENTATION.md` so the
`write:tests` entry explicitly includes `test scaffold` and `test lint`, keeping
the scope contract consistent with the test command docs.

In `@package.json`:
- Around line 37-39: The package publishing settings are pointing `npm publish`
for `@testsprite/testsprite-cli` to GitHub Packages with restricted access,
which conflicts with the existing npmjs.org release flow used by `README.md` and
`.github/workflows/release.yaml`. Update the `publishConfig` in package metadata
so it matches the npm release/install path, or otherwise adjust the release
workflow and documentation together; use the `publishConfig` block as the key
symbol to locate the change.

In `@src/commands/project.ts`:
- Around line 491-540: The runAutoAuth flow is still touching the filesystem and
skipping the dry-run banner before the dry-run early return. Update runAutoAuth
so the --password-file, --client-secret-file, and --refresh-token-file reads
happen only after the opts.dryRun branch, and add emitDryRunBanner(stderr) in
that branch before returning the sample. Keep the fix localized around
runAutoAuth, the idempotencyKey logging, and the existing dry-run response path.
- Around line 551-569: `renderAutoAuthText` currently treats every disabled
auto-auth response as a failed trial login, which mislabels explicit `--disable`
requests. Update the note logic so it only prints the “trial login failed”
message when `lastRefreshError` is present (or otherwise explicitly indicates a
failed refresh), and keep the disabled-but-user-requested case as a plain
disabled state. Use the `CliProjectAutoAuthResponse` fields in
`renderAutoAuthText` to distinguish these cases and avoid implying credential
failure when `r.enabled` is false due to an intentional disable.
- Around line 381-409: The dry-run path in the project credential command is
touching the filesystem and missing the standard dry-run banner. Move the
`opts.dryRun` handling in `runCreateCredential` ahead of any credential
resolution so `readFileSync` for `opts.credentialFile` is never reached during
dry-run, and add `emitDryRunBanner(stderr)` in the dry-run branch before
printing the canned `CliProjectCredentialResponse`. Keep the non-dry-run
credential validation and `body` construction unchanged after the early return.

---

Nitpick comments:
In @.github/workflows/ci-nudge.yml:
- Around line 88-95: The FIX lookup in the CI nudge workflow does not match
matrix-expanded check-run names for the `test` and `build` jobs, so
`FIX[c.name]` falls back incorrectly. Update the `FIX` map in the workflow to
use the actual check-run names emitted by `test` and `build` (for example the
Node-specific variants), or switch the lookup logic to handle matrix prefixes in
the same place where `FIX[c.name]` is used.

In @.github/workflows/pr-triage.yml:
- Around line 57-62: The token minted in the pr-triage workflow is currently
unscoped, so update the create-github-app-token step to pass explicit
permission-* inputs for only what the job needs, and verify the exact v3.2.0
input names on that action before changing it. Use the app-token step as the
anchor, and constrain the permissions to PR commenting/labeling only so the
minted installation token follows least privilege.

In `@src/commands/project.test.ts`:
- Around line 949-1167: Add dry-run coverage for both runCredential and
runAutoAuth so the suites verify opts.dryRun behavior. Update the tests around
runCredential and runAutoAuth to assert that when dryRun is true, no fetch call
is made and the dry-run path is exercised before any secret-file handling. Use
the existing helpers/cases in runCredential, runAutoAuth, and captureFetch to
locate the assertions and add a dedicated dry-run test for each handler.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 551d2235-5e94-4d30-970f-e3bb3eb000d8

📥 Commits

Reviewing files that changed from the base of the PR and between 3305dfa and d637ca3.

⛔ Files ignored due to path filters (1)
  • test/__snapshots__/help.snapshot.test.ts.snap is excluded by !**/*.snap, !**/*.snap
📒 Files selected for processing (32)
  • .gitattributes
  • .github/PULL_REQUEST_TEMPLATE.md
  • .github/workflows/ci-nudge.yml
  • .github/workflows/issue-triage.yml
  • .github/workflows/pr-triage.yml
  • .github/workflows/stale.yml
  • CHANGELOG.md
  • CONTRIBUTING.md
  • DOCUMENTATION.md
  • README.md
  • package.json
  • skills/testsprite-onboard.skill.md
  • skills/testsprite-verify.skill.md
  • src/commands/agent.test.ts
  • src/commands/agent.ts
  • src/commands/init.test.ts
  • src/commands/init.ts
  • src/commands/project.test.ts
  • src/commands/project.ts
  • src/commands/test.test.ts
  • src/commands/test.ts
  • src/commands/usage.ts
  • src/index.ts
  • src/lib/agent-targets.test.ts
  • src/lib/bundle.test.ts
  • src/lib/credentials.test.ts
  • src/lib/http.ts
  • src/lib/skill-nudge.test.ts
  • src/version.ts
  • test/cli.subprocess.test.ts
  • test/helpers/hermetic-env.ts
  • vitest.config.ts

Comment thread .github/workflows/ci-nudge.yml Outdated
Comment thread .github/workflows/issue-triage.yml
Comment thread CHANGELOG.md Outdated
Comment thread CONTRIBUTING.md
Comment thread CONTRIBUTING.md Outdated
Comment thread DOCUMENTATION.md
Comment thread package.json Outdated
Comment thread src/commands/project.ts
Comment thread src/commands/project.ts
Comment thread src/commands/project.ts
dukeduke2016
dukeduke2016 previously approved these changes Jul 9, 2026

@dukeduke2016 dukeduke2016 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Private-Snapshot-RevId: d22d9f18f5d9712921097d5829c28d056e3ffd31
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

Test Coverage Report

Metric Coverage
Lines 87.07%
Statements 87.07%
Functions 81.05%
Branches 85.44%

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
.github/workflows/pr-triage.yml (1)

57-62: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Scope the App token to issues only. .github/workflows/pr-triage.yml only creates/updates PR comments and labels through the issues API, so permission-issues: write is sufficient here; permission-pull-requests isn’t needed.

🔒️ Proposed fix
       - id: app-token
         continue-on-error: true
         uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
         with:
           app-id: ${{ secrets.TESTSPRITE_HOB_APP_ID || secrets.ALFHEIM_AGENT_APP_ID }}
           private-key: ${{ secrets.TESTSPRITE_HOB_PRIVATE_KEY || secrets.ALFHEIM_AGENT_PRIVATE_KEY }}
+          permission-issues: write
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/pr-triage.yml around lines 57 - 62, Scope the GitHub App
token in the app-token step to issue permissions only by adding
permission-issues: write and removing any pull-request permission configuration;
keep the existing app-id, private-key, and token usage unchanged.

Sources: Path instructions, Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci-nudge.yml:
- Around line 16-19: Add a top-level concurrency group to the workflow using the
workflow_run commit SHA, specifically ci-nudge-${{
github.event.workflow_run.head_sha }}, so overlapping nudge runs for the same
commit are serialized.
- Around line 37-42: Restrict the token generated by the `app-token` step to
only the required Issues permission by adding `permission-issues: write` in its
`with` configuration; do not grant pull-request or other unnecessary
permissions.

In @.github/workflows/pr-triage.yml:
- Around line 44-51: Align the PR exemption condition in the workflow with the
small-fix exemptions described in CONTRIBUTING.md. Update the condition
surrounding the pull request title check to recognize typo, comment-only, and
other documented small documentation fixes—not only titles starting with
“docs”—or revise the policy text consistently if the narrower behavior is
intended.

---

Nitpick comments:
In @.github/workflows/pr-triage.yml:
- Around line 57-62: Scope the GitHub App token in the app-token step to issue
permissions only by adding permission-issues: write and removing any
pull-request permission configuration; keep the existing app-id, private-key,
and token usage unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 883a8317-6378-4263-9b99-da9e110cd16f

📥 Commits

Reviewing files that changed from the base of the PR and between d637ca3 and 3d65ff5.

⛔ Files ignored due to path filters (1)
  • test/__snapshots__/help.snapshot.test.ts.snap is excluded by !**/*.snap, !**/*.snap
📒 Files selected for processing (32)
  • .gitattributes
  • .github/PULL_REQUEST_TEMPLATE.md
  • .github/workflows/ci-nudge.yml
  • .github/workflows/issue-triage.yml
  • .github/workflows/pr-triage.yml
  • .github/workflows/stale.yml
  • CHANGELOG.md
  • CONTRIBUTING.md
  • DOCUMENTATION.md
  • README.md
  • package.json
  • skills/testsprite-onboard.skill.md
  • skills/testsprite-verify.skill.md
  • src/commands/agent.test.ts
  • src/commands/agent.ts
  • src/commands/init.test.ts
  • src/commands/init.ts
  • src/commands/project.test.ts
  • src/commands/project.ts
  • src/commands/test.test.ts
  • src/commands/test.ts
  • src/commands/usage.ts
  • src/index.ts
  • src/lib/agent-targets.test.ts
  • src/lib/bundle.test.ts
  • src/lib/credentials.test.ts
  • src/lib/http.ts
  • src/lib/skill-nudge.test.ts
  • src/version.ts
  • test/cli.subprocess.test.ts
  • test/helpers/hermetic-env.ts
  • vitest.config.ts
✅ Files skipped from review due to trivial changes (13)
  • src/version.ts
  • .gitattributes
  • .github/PULL_REQUEST_TEMPLATE.md
  • skills/testsprite-verify.skill.md
  • skills/testsprite-onboard.skill.md
  • src/lib/http.ts
  • src/index.ts
  • src/commands/usage.ts
  • CHANGELOG.md
  • package.json
  • src/commands/init.ts
  • README.md
  • DOCUMENTATION.md
🚧 Files skipped from review as they are similar to previous changes (16)
  • src/commands/test.test.ts
  • test/helpers/hermetic-env.ts
  • .github/workflows/stale.yml
  • vitest.config.ts
  • src/lib/agent-targets.test.ts
  • src/commands/agent.ts
  • src/commands/init.test.ts
  • .github/workflows/issue-triage.yml
  • src/lib/bundle.test.ts
  • src/lib/credentials.test.ts
  • test/cli.subprocess.test.ts
  • src/lib/skill-nudge.test.ts
  • src/commands/agent.test.ts
  • src/commands/project.test.ts
  • src/commands/project.ts
  • src/commands/test.ts

Comment on lines +16 to +19
on:
workflow_run:
workflows: ['CI', 'Test Coverage']
types: [completed]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

git ls-files .github/workflows/ci-nudge.yml
echo '---'
ast-grep outline .github/workflows/ci-nudge.yml --view expanded
echo '---'
cat -n .github/workflows/ci-nudge.yml | sed -n '1,220p'

Repository: TestSprite/testsprite-cli

Length of output: 7468


Add a concurrency group to serialize nudge runs.
Both workflow_run triggers can finish close together, and the second run can still see no sticky comment before the first one writes it, creating duplicate nudge comments. Use a per-SHA group like ci-nudge-${{ github.event.workflow_run.head_sha }}.

🧰 Tools
🪛 zizmor (1.26.1)

[error] 16-19: use of fundamentally insecure workflow trigger (dangerous-triggers): workflow_run is almost always used insecurely

(dangerous-triggers)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci-nudge.yml around lines 16 - 19, Add a top-level
concurrency group to the workflow using the workflow_run commit SHA,
specifically ci-nudge-${{ github.event.workflow_run.head_sha }}, so overlapping
nudge runs for the same commit are serialized.

Comment on lines +37 to +42
- id: app-token
continue-on-error: true
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ secrets.TESTSPRITE_HOB_APP_ID || secrets.ALFHEIM_AGENT_APP_ID }}
private-key: ${{ secrets.TESTSPRITE_HOB_PRIVATE_KEY || secrets.ALFHEIM_AGENT_PRIVATE_KEY }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## File list\n'
git ls-files .github/workflows/ci-nudge.yml

printf '\n## Relevant lines from workflow\n'
nl -ba .github/workflows/ci-nudge.yml | sed -n '1,140p'

printf '\n## Search for app-token usage and concurrency in workflow\n'
rg -n "create-github-app-token|concurrency|permission-" .github/workflows/ci-nudge.yml

Repository: TestSprite/testsprite-cli

Length of output: 281


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## Workflow lines\n'
sed -n '1,160p' .github/workflows/ci-nudge.yml | cat -n

printf '\n## Search for concurrency / app-token inputs\n'
rg -n "concurrency|create-github-app-token|permission-" .github/workflows/ci-nudge.yml

Repository: TestSprite/testsprite-cli

Length of output: 7548


🌐 Web query:

actions/create-github-app-token permission-* inputs inherit all installation permissions recommend explicitly list permissions

💡 Result:

When using the actions/create-github-app-token action, the generated installation access token inherits all permissions granted to the GitHub App installation by default [1][2]. To improve security and adhere to the principle of least privilege, it is strongly recommended to explicitly list only the permissions required for your specific use case [1][3]. You can restrict the token's permissions by using inputs with the permission- prefix followed by the permission name (e.g., permission-pull-requests: read) [1][3][4]. Key considerations include: - Purpose of Explicit Listing: By explicitly defining permissions, you limit the scope of the generated token. This follows GitHub's general best practice for controlling permissions in workflows [1][3]. - Mechanism: The action uses these permission-* inputs to communicate with the GitHub API endpoint POST /app/installations/{installation_id}/access_tokens, which accepts a permissions parameter to generate a scoped token [5][2]. - Important Constraints: - You can only grant permissions that have already been granted to the GitHub App installation itself [1][2]. Attempting to request a permission that the installation does not possess will result in an error [1][2]. - If you encounter issues (such as 403 or 422 errors) after defining specific permissions, ensure that all permissions necessary for your workflow tasks are included in your inputs [6]. If a token with default (all) permissions works but a restricted one fails, you may need to incrementally add permissions to identify which specific one is missing [6]. - Best Practice: Start by identifying the minimal set of permissions required for your job's API calls and configure those explicitly [1][6]. Using the permission-* inputs also benefits from the action runner's built-in type intelligence and input validation [1][3].

Citations:


🌐 Web query:

GitHub App issue comments permission issues write pull requests permission required for PR issue comments

💡 Result:

To comment on pull requests (PRs) using a GitHub App, you typically only need the Issues: write permission, not the Pull Requests: write permission [1][2]. This confusion arises because, while every pull request is an issue in the GitHub data model, they are managed under distinct permission scopes [1][3]. Standard comments on the main conversation thread of a pull request are considered "issue comments" and are handled by the Issues API endpoints [4][2][3]. Therefore, the Issues: write permission is sufficient to create, edit, or delete these comments [1][2]. The Pull Requests: write permission is generally reserved for actions that are specific to the pull request lifecycle, such as: - Submitting pull request reviews (inline code comments) [2][5]. - Requesting reviewers [5]. - Updating the pull request branch or managing merge status. If you are receiving a 403 "Resource not accessible by integration" error when posting a comment on a pull request, ensure your GitHub App has been granted Issues: write access [1]. If your app is performing other operations (like submitting reviews), you may need Pull Requests: write, but for general commenting, Issues: write is the correct scope [4][1][2].

Citations:


Scope the App token to issues:write.

create-github-app-token inherits the installation’s full permissions by default. This step only creates/updates PR thread comments via the issues API, so permission-issues: write is enough; permission-pull-requests: write isn’t needed.

Proposed fix
       - id: app-token
         continue-on-error: true
         uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
         with:
           app-id: ${{ secrets.TESTSPRITE_HOB_APP_ID || secrets.ALFHEIM_AGENT_APP_ID }}
           private-key: ${{ secrets.TESTSPRITE_HOB_PRIVATE_KEY || secrets.ALFHEIM_AGENT_PRIVATE_KEY }}
+          permission-issues: write
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- id: app-token
continue-on-error: true
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ secrets.TESTSPRITE_HOB_APP_ID || secrets.ALFHEIM_AGENT_APP_ID }}
private-key: ${{ secrets.TESTSPRITE_HOB_PRIVATE_KEY || secrets.ALFHEIM_AGENT_PRIVATE_KEY }}
- id: app-token
continue-on-error: true
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ secrets.TESTSPRITE_HOB_APP_ID || secrets.ALFHEIM_AGENT_APP_ID }}
private-key: ${{ secrets.TESTSPRITE_HOB_PRIVATE_KEY || secrets.ALFHEIM_AGENT_PRIVATE_KEY }}
permission-issues: write
🧰 Tools
🪛 zizmor (1.26.1)

[error] 39-39: dangerous use of GitHub App tokens (github-app): app token inherits blanket installation permissions

(github-app)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci-nudge.yml around lines 37 - 42, Restrict the token
generated by the `app-token` step to only the required Issues permission by
adding `permission-issues: write` in its `with` configuration; do not grant
pull-request or other unnecessary permissions.

Sources: Path instructions, Linters/SAST tools

Comment on lines +44 to +51
# (dependabot etc.), maintainers, and docs-only changes (CONTRIBUTING
# exempts docs/small fixes from the issue-first ask).
if: >-
github.repository == 'TestSprite/testsprite-cli' &&
github.event.pull_request.state == 'open' &&
github.event.pull_request.user.type != 'Bot' &&
!contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.pull_request.author_association) &&
!startsWith(github.event.pull_request.title, 'docs')

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## pr-triage.yml excerpt\n'
sed -n '1,140p' .github/workflows/pr-triage.yml | cat -n

printf '\n## CONTRIBUTING.md excerpt(s)\n'
rg -n "Docs|small fixes|typos|comment-only|issue-first|docs-only" CONTRIBUTING.md .github/workflows/pr-triage.yml

Repository: TestSprite/testsprite-cli

Length of output: 8911


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## CONTRIBUTING.md full file line count\n'
wc -l CONTRIBUTING.md

printf '\n## CONTRIBUTING.md relevant section\n'
sed -n '1,260p' CONTRIBUTING.md | cat -n

Repository: TestSprite/testsprite-cli

Length of output: 9410


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## pr-triage workflow excerpt around the gate\n'
sed -n '35,60p' .github/workflows/pr-triage.yml | cat -n

Repository: TestSprite/testsprite-cli

Length of output: 1641


Broaden the PR exemption to match CONTRIBUTING.md. .github/workflows/pr-triage.yml:44-51 only skips titles starting with docs, so typo/comment-only PRs like fix: typo in README still get needs-issue even though CONTRIBUTING.md exempts small fixes. Either widen the gate or tighten the policy text so they align.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/pr-triage.yml around lines 44 - 51, Align the PR exemption
condition in the workflow with the small-fix exemptions described in
CONTRIBUTING.md. Update the condition surrounding the pull request title check
to recognize typo, comment-only, and other documented small documentation
fixes—not only titles starting with “docs”—or revise the policy text
consistently if the narrower behavior is intended.

@jangjos-128 jangjos-128 merged commit 60d55e4 into main Jul 9, 2026
9 checks passed
@jangjos-128 jangjos-128 deleted the release/v0.3.0 branch July 9, 2026 23:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants