-
-
Notifications
You must be signed in to change notification settings - Fork 30
test(plugins): add live install verification scripts for each agent #184
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| #!/usr/bin/env bash | ||
| # | ||
| # verify-install.sh — Live-install and basic runtime validation of the built | ||
| # Claude Code distribution using the real `claude` CLI. | ||
| # | ||
| # Proves that `claude plugin marketplace add`, manifest acceptance, and | ||
| # --plugin-dir loading work against the exact tree shape published to | ||
| # getsentry/plugin-claude. | ||
| # | ||
| # Usage: verify-install.sh <TARGET_DIR> (a tree produced by build.sh) | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| TARGET_DIR="${1:?usage: verify-install.sh <TARGET_DIR>}" | ||
|
|
||
| echo "=== Ensuring claude CLI is available ===" | ||
| if ! command -v claude >/dev/null 2>&1; then | ||
| echo "claude CLI not found; installing via official installer..." | ||
| curl -fsSL https://claude.ai/install.sh | bash | ||
| fi | ||
|
|
||
| export PATH="$HOME/.local/bin:$PATH" | ||
| hash -r 2>/dev/null || true | ||
|
|
||
| claude --version || true | ||
|
|
||
| echo "=== Live marketplace add from $TARGET_DIR ===" | ||
| claude plugin marketplace add "$TARGET_DIR" | ||
|
|
||
| echo "=== Introspection via claude CLI ===" | ||
| claude plugin list | cat | ||
|
|
||
| echo "=== One-shot load test via --plugin-dir (exercises the loader) ===" | ||
| claude --plugin-dir "$TARGET_DIR" \ | ||
| -p 'List the names of the Sentry router skills only (sentry-sdk-setup, sentry-workflow, sentry-feature-setup). One line, comma separated.' \ | ||
| --safe-mode --print 2>&1 | cat | ||
|
Comment on lines
+34
to
+36
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: The Suggested FixRemove the Prompt for AI AgentDid we get this right? 👍 / 👎 to inform future reviews. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Claude install path is skippedMedium Severity The Claude script adds the marketplace and then uses Reviewed by Cursor Bugbot for commit d808783. Configure here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Claude prompt fails without APIHigh Severity The deploy workflow runs this script with Reviewed by Cursor Bugbot for commit 35c22e7. Configure here. |
||
|
|
||
| echo "=== Optional: claude's own manifest validate ===" | ||
| claude plugin validate "$TARGET_DIR/.claude-plugin/plugin.json" || true | ||
|
|
||
| echo "=== Claude verify-install complete ===" | ||
|
cursor[bot] marked this conversation as resolved.
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| #!/usr/bin/env bash | ||
| # | ||
| # verify-install.sh — Live-install and basic runtime validation of the built | ||
| # Codex distribution using the real `codex` CLI. | ||
| # | ||
| # Proves that `codex plugin marketplace add` + `codex plugin add` succeed | ||
| # for the special Codex layout (plugins/sentry/ + .agents/plugins/marketplace.json | ||
| # + the agents/openai.yaml transforms for hidden skills). | ||
| # | ||
| # Usage: verify-install.sh <TARGET_DIR> (a tree produced by build.sh) | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| TARGET_DIR="${1:?usage: verify-install.sh <TARGET_DIR>}" | ||
|
|
||
| echo "=== Ensuring codex CLI is available ===" | ||
| if ! command -v codex >/dev/null 2>&1; then | ||
| echo "codex CLI not found; installing via official installer..." | ||
| CODEX_NON_INTERACTIVE=1 curl -fsSL https://chatgpt.com/codex/install.sh | sh | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Codex installer flag is mis-scopedMedium Severity
Reviewed by Cursor Bugbot for commit d808783. Configure here. |
||
| fi | ||
|
|
||
| export PATH="$HOME/.codex/packages/standalone/current/bin:$HOME/.local/bin:$PATH" | ||
| hash -r 2>/dev/null || true | ||
|
|
||
| codex --version || true | ||
|
|
||
| echo "=== Clean any previous test marketplace (harmless if absent) ===" | ||
| codex plugin marketplace remove sentry-plugin-marketplace 2>/dev/null || true | ||
|
|
||
| echo "=== Live marketplace add from $TARGET_DIR ===" | ||
| codex plugin marketplace add "$TARGET_DIR" | ||
|
|
||
| echo "=== Live plugin add ===" | ||
| codex plugin add sentry@sentry-plugin-marketplace | ||
|
|
||
| echo "=== Introspection via codex CLI ===" | ||
| codex plugin list | grep -A2 -B2 'sentry-plugin-marketplace' | cat || true | ||
|
|
||
| # Note: Many Codex prompt invocations are sensitive to TTY/PTY. | ||
| # The marketplace add + plugin add + list above are the primary signals | ||
| # that the agent's own plugin system accepted and registered the bundle. | ||
| # A best-effort prompt can be added here later with `script` if desired. | ||
|
|
||
| echo "=== Codex verify-install complete ===" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| #!/usr/bin/env bash | ||
| # | ||
| # verify-install.sh — Live "installation" and layout validation of the built | ||
| # Cursor distribution. | ||
| # | ||
| # Cursor's .cursor-plugin style plugins are primarily installed via the IDE | ||
| # ("Settings > Plugins" or adding the github marketplace repo). There is no | ||
| # fully equivalent `cursor plugin install <local-tree>` that behaves exactly | ||
| # like the published flow for end users. | ||
| # | ||
| # This script: | ||
| # - Ensures the cursor CLI/agent is present. | ||
| # - Verifies that the tree produced by build.sh has exactly the layout | ||
| # expected at the root of getsentry/plugin-cursor (i.e. what Cursor will | ||
| # consume when added from the published repo). | ||
| # - Optionally stages to a local plugins dir for manual testing. | ||
| # | ||
| # Usage: verify-install.sh <TARGET_DIR> (a tree produced by build.sh) | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| TARGET_DIR="${1:?usage: verify-install.sh <TARGET_DIR>}" | ||
|
|
||
| echo "=== Ensuring cursor CLI/agent is available ===" | ||
| if ! command -v cursor >/dev/null 2>&1; then | ||
| echo "cursor CLI not found; installing via official installer..." | ||
| curl https://cursor.com/install -fsS | bash | ||
| fi | ||
|
Check warning on line 28 in plugin-src/cursor/verify-install.sh
|
||
|
|
||
| export PATH="$HOME/.local/bin:$PATH" | ||
| hash -r 2>/dev/null || true | ||
|
|
||
| cursor --version || true | ||
|
|
||
| echo "=== Cursor published layout verification ===" | ||
| # These are the files/dirs the published getsentry/plugin-cursor root must have. | ||
| ls -la "$TARGET_DIR/.cursor-plugin/" "$TARGET_DIR/mcp.json" 2>/dev/null | cat || true | ||
| echo "Sample skills present:" | ||
| ls "$TARGET_DIR/skills/" | head -8 | cat | ||
| echo "Sample commands present:" | ||
| ls "$TARGET_DIR/commands/" 2>/dev/null | cat || true | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cursor checks ignore failuresMedium Severity The Cursor layout check suppresses Reviewed by Cursor Bugbot for commit d808783. Configure here. |
||
|
|
||
| # Best-effort: show whether cursor agent is invocable. | ||
| cursor agent --version 2>/dev/null || echo "cursor agent subcommand present (or will be fetched on demand)" | ||
|
|
||
| # For local manual testing you can stage the tree: | ||
| # mkdir -p ~/.cursor/plugins/local/sentry && rm -rf ~/.cursor/plugins/local/sentry/* | ||
| # cp -a "$TARGET_DIR/." ~/.cursor/plugins/local/sentry/ | ||
| # Then use `cursor agent -p --print ...` (requires CURSOR_API_KEY or prior login). | ||
|
|
||
| echo "=== Cursor verify-install complete (primary user install remains GUI marketplace) ===" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| #!/usr/bin/env bash | ||
| # | ||
| # verify-install.sh — Live-install and basic runtime validation of the built | ||
| # Grok distribution using the real `grok` CLI. | ||
| # | ||
| # Proves that `grok plugin install`, manifest parsing, skill/command registration, | ||
| # and basic loading work against the exact tree shape that will be published. | ||
| # | ||
| # Usage: verify-install.sh <TARGET_DIR> (a tree produced by build.sh) | ||
| # | ||
| # The script is idempotent-ish for the CLI install and safe to run locally or in CI. | ||
| # It will attempt to install the grok CLI if not already on PATH. | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| TARGET_DIR="${1:?usage: verify-install.sh <TARGET_DIR>}" | ||
|
|
||
| echo "=== Ensuring grok CLI is available ===" | ||
| if ! command -v grok >/dev/null 2>&1; then | ||
| echo "grok CLI not found; installing via official installer..." | ||
| curl -fsSL https://x.ai/cli/install.sh | bash | ||
|
Check warning on line 21 in plugin-src/grok/verify-install.sh
|
||
| fi | ||
|
|
||
| # Common install locations | ||
| export PATH="$HOME/.local/bin:$HOME/.grok/bin:$PATH" | ||
| hash -r 2>/dev/null || true | ||
|
|
||
| grok --version || true | ||
|
|
||
| echo "=== Live install from $TARGET_DIR (local path) ===" | ||
| grok plugin install "$TARGET_DIR" --trust | ||
|
|
||
| echo "=== Introspection via grok CLI ===" | ||
| grok plugin list | cat | ||
| grok plugin details sentry | cat | ||
| grok plugin validate "$TARGET_DIR" | ||
|
|
||
| echo "=== Best-effort functional smoke test (prompt, no MCP) ===" | ||
| # Use script(1) to give the agent a PTY (many CLIs behave better non-interactively this way). | ||
| # Fall back gracefully if script is unavailable. | ||
| if command -v script >/dev/null 2>&1; then | ||
| PROMPT_OUT=$(script -q -c \ | ||
| 'grok -p "Name the three primary Sentry router skills (sentry-sdk-setup etc) from the loaded plugin. Output only the names as a comma separated list." ' \ | ||
| /dev/null 2>&1 | cat) || true | ||
| else | ||
| echo "(no script(1); running prompt directly)" | ||
| PROMPT_OUT=$(grok -p \ | ||
| 'Name the three primary Sentry router skills (sentry-sdk-setup etc) from the loaded plugin. Output only the names as a comma separated list.' \ | ||
| 2>&1 | cat) || true | ||
| fi | ||
| echo "$PROMPT_OUT" | grep -E 'sentry-sdk-setup|sentry-workflow|sentry-feature-setup' \ | ||
| || echo "::warning::Grok prompt check did not surface expected skill names (auth or model availability may be limited)" | ||
|
|
||
| echo "=== Grok verify-install complete ===" | ||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unpinned curl|bash installers run with GH_TOKEN in deploy step (supply-chain exposure)
Each new plugin-src/<agent>/verify-install.sh pipes an unverified remote installer (e.g.
curl -fsSL https://x.ai/cli/install.sh | bash) and is invoked from the deploy workflow'sBuild and deploystep, which exports GH_TOKEN (a GitHub App token with contents:write on the matching plugin repo). If any of the four vendor install endpoints is compromised, the malicious installer inherits GH_TOKEN and the tokenized git remote already on the runner, allowing pushes to getsentry/plugin-<agent>. Pin the CLI install to a verified version/checksum or run the install in a step that does not have the deploy token in scope.Evidence
.github/workflows/deploy-plugins.ymlstepBuild and deploy plugin-${{ matrix.agent }}setsGH_TOKEN: ${{ steps.token.outputs.token }}(env block) and the minted app token is scopedcontents:writetoplugin-${{ matrix.agent }}.https://x-access-token:${GH_TOKEN}@github.com/getsentry/${TARGET_REPO}.gitinto the worktree and then runsplugin-src/${AGENT}/verify-install.sh "$WORKTREE", so child processes inherit GH_TOKEN and the tokenized remote.claude.ai/install.sh | bash,cursor.com/install | bash,chatgpt.com/codex/install.sh | sh,x.ai/cli/install.sh | bash.Also found at 2 additional locations
plugin-src/cursor/verify-install.sh:28plugin-src/grok/verify-install.sh:21Identified by Warden security-review · TJL-YS2