Skip to content

Conversation

@jonathanpopham
Copy link
Collaborator

@jonathanpopham jonathanpopham commented Jan 7, 2026

Summary

This PR adds intentional dead code to test the dead-code-hunter action on itself.

Added functions that should be detected:

  • unusedHelperFunction
  • formatUnusedData
  • fetchUnusedData
  • unusedProcessor.process

Expected Result

The dead-code-hunter action should:

  1. Run on this PR
  2. Detect the unused functions in src/example-dead-code.ts
  3. Post a comment listing the dead code found

This is a dogfooding test - the action analyzing its own codebase.

Summary by CodeRabbit

  • Tests

    • Added internal dead‑code test fixtures to improve dead‑code detection tooling.
  • Bug Fixes

    • Trimmed and validated API key input with masked key info and warnings for misconfigured keys.
    • Improved error reporting to include API response status and body when available.
    • Enhanced debug output for analysis results and sample findings.
  • Chores

    • CI workflow permissions updated to support repository content access for self‑tests.
  • Documentation

    • Wording, example output, and diagram updates to reflect renamed analysis flow.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 7, 2026

Walkthrough

Adds a dead-code test fixture, tightens API-key parsing/validation and expands runtime debug and API error-response logging; switches graph-generation call to Supermodel, updates README wording, changes CI job permissions, and tweaks PR comment wording. No public API signatures changed.

Changes

Cohort / File(s) Summary
Dead-code test fixture
src/example-dead-code.ts
New file with intentionally unused declarations for dead-code detection: unusedHelperFunction, formatUnusedData, fetchUnusedData, and unusedProcessor.
Runtime logic & logging
src/index.ts
Trim and validate API key (warn if not starting with smsk_); log API key excerpts (length/prefix/suffix); replaced generateCallGraph with generateSupermodelGraph and now reads response.summary; added debug logging for sample function nodes and up to 5 dead-code items (dead-code-json); enhanced error catch to inspect error.response, attempt to read and log response body and status.
PR comment wording
src/dead-code.ts
Minor wording change in PR comment footer: "call graph analysis" → "graph analysis" (no control-flow change).
CI permissions
.github/workflows/ci.yml
Added permissions to the self-test job: contents: read and pull-requests: write.
Docs / README
README.md
Terminology and diagram updates from “Call Graph” → “Graph”; adjusted example PR findings and workflow metadata to reflect CI permission and API naming changes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🧪 A quiet file of functions asleep,
A key trimmed neat, its echoes keep,
Logs pry open answers, line by line,
Graphs now told by Supermodel's design,
Small edits sing — the repo hums fine.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly matches the main objective: adding intentional dead code to test the dead-code-hunter action's self-analysis capability. It's concise, specific, and clearly summarizes the changeset's primary purpose.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b8f3c9f and d9dc9a7.

⛔ Files ignored due to path filters (1)
  • dist/index.js is excluded by !**/dist/**
📒 Files selected for processing (2)
  • README.md
  • src/dead-code.ts
🔇 Additional comments (7)
src/dead-code.ts (1)

159-159: LGTM! Clean terminology update.

The wording change from "call graph analysis" to "graph analysis" is consistent with the broader terminology shift in this PR. The attribution line in the PR comment will now match the updated branding.

README.md (6)

3-11: Nice clarity improvement!

The updated intro is more direct. Instead of mentioning "call graphs" specifically, you're now just saying it "finds unreachable functions" which is what users actually care about. The "graph API" terminology is cleaner too.


23-25: Good addition - these permissions are essential!

Without the pull-requests: write permission, your action won't be able to post the dead code findings as a comment. And contents: read is needed to access the repo. Smart to include this in the example so users don't hit permission errors.


62-68: Example looks good, but quick question about the test fixture.

The example now shows the actual functions from your test file (unusedHelperFunction, formatUnusedData, fetchUnusedData), which is way better than hypothetical examples.

One thing: your PR objectives mention 4 unused items including unusedProcessor.process, but the example shows 3. Is the .process method intentionally excluded from this example (maybe because it's a method vs. a standalone function)? Just want to make sure the example accurately reflects what the action will actually detect.


71-71: Consistent branding update.

This matches the footer change in src/dead-code.ts, so the example shows exactly what users will see in their PRs.


94-94: Cleaner wording!

"Supermodel supports analysis for:" is more concise than the old "call graph analysis" phrasing. Gets the same point across with fewer words.


107-110: Diagram terminology updated to match.

The flow diagram now uses "Graph" instead of "Call Graph" and shows the updated API path (/v1/graphs/supermodel). Everything's consistent with the terminology changes throughout the PR.


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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/example-dead-code.ts (1)

1-24: Nice test fixture! Consider adding more patterns to make it comprehensive.

This file does exactly what it says on the tin - provides intentional dead code for testing. The four different patterns you've included (simple function, array formatter, async function, and object method) are solid starting points.

If you want to level up this test fixture, here are some additional patterns that might be worth throwing in:

  1. Exported but unused - to verify the tool distinguishes between "exported" and "actually used elsewhere"

    export function exportedButUnused() { return 42; }
  2. Class with unused methods - another common pattern

    class UnusedClass {
      unusedMethod() { return 'hello'; }
    }
  3. Mixed scenario - some used code alongside unused code, to test that the tool doesn't flag false positives

    function usedHelper() { return 1; }
    function unusedHelper() { return 2; }
    usedHelper(); // This one is called

These would make your dogfooding test more thorough, but what you have now absolutely works for a first pass.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 33eddb6 and b6a348d.

📒 Files selected for processing (1)
  • src/example-dead-code.ts

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @src/index.ts:
- Around line 44-49: The current logging exposes a substring of the secret API
key via core.info; update the code that references apiKey so it never logs any
part of the key (remove apiKey.substring usage). Keep a non-secret diagnostic
such as key length or a boolean result of apiKey.startsWith('smsk_') via
core.info/core.warning, or replace the info call with something like
core.info(`API key configured (${apiKey.length} chars)`) or only log
presence/validation results; ensure no code paths log apiKey or any substring of
it.
🧹 Nitpick comments (1)
src/index.ts (1)

127-127: Prefer unknown over any for better type safety.

Using error: any disables type checking entirely. The modern TypeScript pattern is to use error: unknown, which forces you to narrow the type before using it (you're already doing this with the error instanceof Error check later).

This is a small change but helps catch bugs at compile time. For example, if you accidentally tried to access error.someProperty without checking the type first, TypeScript would catch it with unknown but not with any.

♻️ Proposed refactor
-  } catch (error: any) {
+  } catch (error: unknown) {
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b6a348d and 36ec948.

⛔ Files ignored due to path filters (3)
  • dist/example-dead-code.d.ts is excluded by !**/dist/**
  • dist/example-dead-code.d.ts.map is excluded by !**/dist/**, !**/*.map
  • dist/index.js is excluded by !**/dist/**
📒 Files selected for processing (1)
  • src/index.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-29T23:52:24.392Z
Learnt from: jonathanpopham
Repo: Arch-Gen-App/Supermodel PR: 520
File: api-server/node/src/services/ai-file-domain-suggester.service.ts:135-141
Timestamp: 2025-09-29T23:52:24.392Z
Learning: In api-server/node/src/services/ai-file-domain-suggester.service.ts, the team prefers to enforce data validation via structured output schema constraints rather than post-processing cleanup steps. The existing JSON schema with strict: true should handle type enforcement, and any additional validation should be added to the schema itself (e.g., minLength, pattern) rather than manual type-checking after LLM response.

Applied to files:

  • src/index.ts
🔇 Additional comments (1)
src/index.ts (1)

127-137: Confirm the SDK's error response structure by checking the actual library.

The code assumes error.response exists with a .text() method that returns a Promise and a .status property. While this matches the standard fetch Response API pattern used by most modern HTTP clients, the @supermodeltools/sdk package isn't publicly available on npm, so we can't verify this from public docs.

To fix this, either:

  • Check the SDK's source or type definitions (if you have access) to confirm the error shape
  • Look at any examples in the SDK's internal documentation
  • Test the error path locally with a bad API key to see what actually gets thrown

The nested try-catch inside your catch block is defensive and reasonable, but ideally you'd know exactly what you're catching before relying on it in production.

src/index.ts Outdated
Comment on lines 44 to 49

// Validate API key format
if (!apiKey.startsWith('smsk_')) {
core.warning('API key does not start with expected prefix "smsk_"');
}
core.info(`API key configured (${apiKey.length} chars, starts with: ${apiKey.substring(0, 10)}...)`);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Remove API key prefix from logs (security risk).

Logging the first 10 characters of the API key exposes a partial secret in GitHub Actions logs, which can be publicly visible (especially in public repos) and may get exported to external logging systems.

Even partial key exposure is a security risk. For example, if someone knows the first 10 chars are smsk_abc12 they've reduced the search space for brute-forcing the rest of the key.

🔒 Proposed fix to remove key prefix logging
 // Validate API key format
 if (!apiKey.startsWith('smsk_')) {
   core.warning('API key does not start with expected prefix "smsk_"');
 }
-core.info(`API key configured (${apiKey.length} chars, starts with: ${apiKey.substring(0, 10)}...)`);
+core.info(`API key configured (${apiKey.length} characters)`);
📝 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
// Validate API key format
if (!apiKey.startsWith('smsk_')) {
core.warning('API key does not start with expected prefix "smsk_"');
}
core.info(`API key configured (${apiKey.length} chars, starts with: ${apiKey.substring(0, 10)}...)`);
// Validate API key format
if (!apiKey.startsWith('smsk_')) {
core.warning('API key does not start with expected prefix "smsk_"');
}
core.info(`API key configured (${apiKey.length} characters)`);
🤖 Prompt for AI Agents
In @src/index.ts around lines 44 - 49, The current logging exposes a substring
of the secret API key via core.info; update the code that references apiKey so
it never logs any part of the key (remove apiKey.substring usage). Keep a
non-secret diagnostic such as key length or a boolean result of
apiKey.startsWith('smsk_') via core.info/core.warning, or replace the info call
with something like core.info(`API key configured (${apiKey.length} chars)`) or
only log presence/validation results; ensure no code paths log apiKey or any
substring of it.

@github-actions
Copy link

github-actions bot commented Jan 7, 2026

Dead Code Hunter

Found 2 potentially unused functions:

Function File Line
anonymous
anonymous

Powered by Supermodel call graph analysis

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @src/index.ts:
- Around line 43-50: The code is exposing parts of the secret by logging
substrings of apiKey; update the core.info call that currently prints
apiKey.substring(...) so it only logs non-secret diagnostics (e.g., the
apiKey.length and whether it starts with 'smsk_' or validation result) and
remove any printing of prefix/suffix characters; keep the
core.getInput('supermodel-api-key') trim and the prefix check using
apiKey.startsWith('smsk_') but ensure no substring of apiKey is ever included in
logs.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 36ec948 and d336244.

⛔ Files ignored due to path filters (1)
  • dist/index.js is excluded by !**/dist/**
📒 Files selected for processing (1)
  • src/index.ts
🧰 Additional context used
🧬 Code graph analysis (1)
src/index.ts (1)
dist/index.js (1)
  • core (32461-32461)
🔇 Additional comments (1)
src/index.ts (1)

128-139: Nice enhancement for debugging API failures.

This error handling improvement is solid. Here's what you're doing right:

  1. Type annotation (error: any) - Good call, since catch blocks can catch literally anything (not just Error objects)
  2. Checking error.response exists - Smart, because not all errors come from API calls
  3. Nested try-catch - Nice defensive coding! If reading response.text() fails for some reason, you still log the status
  4. Falls through - Preserves the existing error handling for regular Error instances

Concrete example: If the API returns a 500 error with a message like {"error": "Database connection failed"}, you'll now see both the status code (500) and that JSON body in your logs, which makes debugging way easier than just seeing "An error occurred."

src/index.ts Outdated
Comment on lines 43 to 50
const apiKey = core.getInput('supermodel-api-key', { required: true }).trim();

// Validate API key format
if (!apiKey.startsWith('smsk_')) {
core.warning('API key does not start with expected prefix "smsk_"');
}
// Log key details for debugging (safe - only shows prefix/suffix)
core.info(`API key configured (${apiKey.length} chars, starts: ${apiKey.substring(0, 12)}..., ends: ...${apiKey.substring(apiKey.length - 4)})`);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Still logging parts of the secret API key (now even more of it) - security risk.

Hey, so I see you're trimming the key now (nice!) and validating the prefix (also nice!), but there's still a security problem on line 50. A previous review flagged logging the first 10 characters of the API key as a security risk. Now the code logs the first 12 characters and the last 4 characters - that's 16 total characters of the secret exposed in logs.

Here's why this matters:

  • GitHub Actions logs can be publicly visible (especially in public repos)
  • If someone knows smsk_abc1234 (12 chars) and xyz9 (last 4), they've learned 16 characters of your secret
  • This dramatically reduces the brute-force search space
  • Logs might get exported to external systems, persisted, etc.

Concrete example: If your API key is smsk_abc123456789_secret_xyz9 and you log smsk_abc1234 and xyz9, an attacker now only needs to guess the middle part.

The safe approach: just log the length or a boolean validation result, but never log any part of the actual key value.

🔒 Proposed fix to remove key substring logging
 // Validate API key format
 if (!apiKey.startsWith('smsk_')) {
   core.warning('API key does not start with expected prefix "smsk_"');
 }
-// Log key details for debugging (safe - only shows prefix/suffix)
-core.info(`API key configured (${apiKey.length} chars, starts: ${apiKey.substring(0, 12)}..., ends: ...${apiKey.substring(apiKey.length - 4)})`);
+core.info(`API key configured (${apiKey.length} characters, valid prefix: ${apiKey.startsWith('smsk_')})`);

This way you still get useful debug info (how long is the key? does it have the right prefix?) without exposing any part of the secret itself.

📝 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
const apiKey = core.getInput('supermodel-api-key', { required: true }).trim();
// Validate API key format
if (!apiKey.startsWith('smsk_')) {
core.warning('API key does not start with expected prefix "smsk_"');
}
// Log key details for debugging (safe - only shows prefix/suffix)
core.info(`API key configured (${apiKey.length} chars, starts: ${apiKey.substring(0, 12)}..., ends: ...${apiKey.substring(apiKey.length - 4)})`);
const apiKey = core.getInput('supermodel-api-key', { required: true }).trim();
// Validate API key format
if (!apiKey.startsWith('smsk_')) {
core.warning('API key does not start with expected prefix "smsk_"');
}
core.info(`API key configured (${apiKey.length} characters, valid prefix: ${apiKey.startsWith('smsk_')})`);
🤖 Prompt for AI Agents
In @src/index.ts around lines 43 - 50, The code is exposing parts of the secret
by logging substrings of apiKey; update the core.info call that currently prints
apiKey.substring(...) so it only logs non-secret diagnostics (e.g., the
apiKey.length and whether it starts with 'smsk_' or validation result) and
remove any printing of prefix/suffix characters; keep the
core.getInput('supermodel-api-key') trim and the prefix check using
apiKey.startsWith('smsk_') but ensure no substring of apiKey is ever included in
logs.

@github-actions
Copy link

github-actions bot commented Jan 7, 2026

Dead Code Hunter

Found 2 potentially unused functions:

Function File Line
anonymous
anonymous

Powered by Supermodel call graph analysis

@github-actions
Copy link

github-actions bot commented Jan 7, 2026

Dead Code Hunter

Found 5 potentially unused functions:

Function File Line
unusedHelperFunction src/example-dead-code.ts#L7 L7
formatUnusedData src/example-dead-code.ts#L12 L12
formatPrComment src/dead-code.ts#L129 L129
fetchUnusedData src/example-dead-code.ts#L17 L17
findDeadCode src/dead-code.ts#L69 L69

Powered by Supermodel call graph analysis

@github-actions
Copy link

github-actions bot commented Jan 7, 2026

Dead Code Hunter

Found 5 potentially unused functions:

Function File Line
unusedHelperFunction src/example-dead-code.ts#L7 L7
formatPrComment src/dead-code.ts#L129 L129
findDeadCode src/dead-code.ts#L69 L69
fetchUnusedData src/example-dead-code.ts#L17 L17
formatUnusedData src/example-dead-code.ts#L12 L12

Powered by Supermodel call graph analysis

@github-actions
Copy link

github-actions bot commented Jan 7, 2026

Dead Code Hunter

Found 5 potentially unused functions:

Function File Line
findDeadCode src/dead-code.ts#L69 L69
formatUnusedData src/example-dead-code.ts#L12 L12
unusedHelperFunction src/example-dead-code.ts#L7 L7
formatPrComment src/dead-code.ts#L129 L129
fetchUnusedData src/example-dead-code.ts#L17 L17

Powered by Supermodel graph analysis

- Remove debug logging and test dead code file
- Clean up action output messages
- Point users to dashboard.supermodeltools.com for API keys
- Improve error messages for invalid API keys
@jonathanpopham jonathanpopham merged commit ca74d5b into main Jan 7, 2026
@jonathanpopham jonathanpopham deleted the test-self-analysis branch January 7, 2026 19:36
@github-actions
Copy link

github-actions bot commented Jan 7, 2026

Dead Code Hunter

Found 2 potentially unused functions:

Function File Line
formatPrComment src/dead-code.ts#L129 L129
findDeadCode src/dead-code.ts#L69 L69

Powered by Supermodel graph analysis

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.

2 participants