Re-vendor the Greptile CLI at 3.5.2 (#7) #15
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CLI Check | |
| # The plugin vendors the Greptile CLI at plugins/greptile/scripts/greptile.mjs. | |
| # Vendoring is a manual step, so the two things that can silently go wrong are | |
| # shipping a bundle that is not the release it claims to be, and shipping one | |
| # that is not what npm publishes at all. Both are checked by running the file | |
| # and by comparing it byte-for-byte against the published tarball. | |
| # | |
| # A local rebuild of the CLI is NOT byte-identical to the npm artifact for the | |
| # same version, so the vendored file must always be extracted from `npm pack`, | |
| # never from a local `bun scripts/bundle.ts`. | |
| # | |
| # No secrets. As in mcp-check.yml, repo-controlled values are read from disk | |
| # and never interpolated into shell source with `${{ }}` — a fork pull request | |
| # controls these files. | |
| on: | |
| push: | |
| branches: [main] | |
| paths: | |
| - 'plugins/greptile/scripts/**' | |
| - 'plugins/greptile/commands/**' | |
| - '.github/workflows/cli-check.yml' | |
| pull_request: | |
| paths: | |
| - 'plugins/greptile/scripts/**' | |
| - 'plugins/greptile/commands/**' | |
| - '.github/workflows/cli-check.yml' | |
| schedule: | |
| - cron: '41 8 * * *' | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| check: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | |
| - name: Recorded version is well formed | |
| run: | | |
| set -euo pipefail | |
| version=$(tr -d '[:space:]' < plugins/greptile/scripts/greptile.version) | |
| if ! printf '%s' "$version" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then | |
| echo "::error::plugins/greptile/scripts/greptile.version is not a plain semver string." | |
| exit 1 | |
| fi | |
| printf '%s' "$version" > "$RUNNER_TEMP/version.txt" | |
| echo "Recorded version $version" | |
| - name: Bundle runs and reports the recorded version | |
| run: | | |
| set -euo pipefail | |
| version=$(cat "$RUNNER_TEMP/version.txt") | |
| reported=$(node plugins/greptile/scripts/greptile.mjs --version | tr -d '[:space:]') | |
| if [ "$reported" != "$version" ]; then | |
| echo "::error::Vendored bundle reports $reported but greptile.version records $version." | |
| exit 1 | |
| fi | |
| echo "Bundle reports $reported." | |
| - name: Bundle is byte-identical to the published npm release | |
| run: | | |
| set -euo pipefail | |
| version=$(cat "$RUNNER_TEMP/version.txt") | |
| cd "$RUNNER_TEMP" | |
| npm pack "greptile@$version" >/dev/null | |
| tar -xzf "greptile-$version.tgz" | |
| cd "$GITHUB_WORKSPACE" | |
| published=$(shasum -a 256 "$RUNNER_TEMP/package/dist/greptile.js" | cut -d' ' -f1) | |
| vendored=$(shasum -a 256 plugins/greptile/scripts/greptile.mjs | cut -d' ' -f1) | |
| if [ "$published" != "$vendored" ]; then | |
| echo "::error::Vendored bundle does not match npm greptile@$version. published=$published vendored=$vendored. Re-vendor with: npm pack greptile@$version && tar -xzf greptile-$version.tgz && cp package/dist/greptile.js plugins/greptile/scripts/greptile.mjs" | |
| exit 1 | |
| fi | |
| echo "Vendored bundle matches npm greptile@$version ($vendored)." | |
| - name: Commands invoke the vendored bundle, not a fetched one | |
| run: | | |
| set -euo pipefail | |
| # Assert against the fenced command block only. Matching whole files | |
| # would fail on a prose mention of npx, and — worse — would accept a | |
| # command that dropped GREPTILE_NO_UPDATE_CHECK as long as the | |
| # paragraph explaining it survived. | |
| for f in plugins/greptile/commands/review.md plugins/greptile/commands/login.md; do | |
| block=$(awk '/^```/{fence = !fence; next} fence' "$f") | |
| if [ -z "$block" ]; then | |
| echo "::error::$f has no fenced command block to validate." | |
| exit 1 | |
| fi | |
| if grep -q 'npx' <<<"$block"; then | |
| echo "::error::$f still fetches the CLI with npx. The plugin vendors it; invoke \${CLAUDE_PLUGIN_ROOT}/scripts/greptile.mjs instead." | |
| exit 1 | |
| fi | |
| if ! grep -qF 'node "${CLAUDE_PLUGIN_ROOT}/scripts/greptile.mjs"' <<<"$block"; then | |
| echo "::error::$f does not invoke the vendored bundle at \${CLAUDE_PLUGIN_ROOT}/scripts/greptile.mjs." | |
| exit 1 | |
| fi | |
| if ! grep -qF 'GREPTILE_NO_UPDATE_CHECK=1 node "${CLAUDE_PLUGIN_ROOT}/scripts/greptile.mjs"' <<<"$block"; then | |
| echo "::error::$f invokes the vendored bundle without GREPTILE_NO_UPDATE_CHECK=1. CLI versions that predate plugin-install detection read this path as a standalone install and name an installer that cannot update the plugin's copy. --agent already suppresses the notice, so this is a second line of defence for invocations that drop it." | |
| exit 1 | |
| fi | |
| done | |
| echo "Commands invoke the vendored bundle with the update check disabled." | |
| - name: Review command suppresses the renderer download | |
| run: | | |
| set -euo pipefail | |
| # The CLI fetches the mmdr binary from a third-party GitHub release | |
| # the first time it renders a Mermaid diagram. That is fine in a | |
| # terminal; inside Claude Code there is no TTY to show the image on, | |
| # so it would stall a review to produce a link. README.md documents | |
| # the download and states that this command suppresses it — keep the | |
| # two in step. | |
| block=$(awk '/^```/{fence = !fence; next} fence' plugins/greptile/commands/review.md) | |
| if ! grep -qF 'GREPTILE_NO_AUTO_INSTALL=1 GREPTILE_NO_UPDATE_CHECK=1 node "${CLAUDE_PLUGIN_ROOT}/scripts/greptile.mjs"' <<<"$block"; then | |
| echo "::error::plugins/greptile/commands/review.md must invoke the bundle with GREPTILE_NO_AUTO_INSTALL=1 ahead of GREPTILE_NO_UPDATE_CHECK=1. README.md tells users the plugin never downloads the mmdr renderer; this is what makes that true." | |
| exit 1 | |
| fi | |
| echo "Review command suppresses the renderer download." |