Skip to content

Test design update#3

Open
ritikrishu wants to merge 3 commits intomainfrom
test/design-update
Open

Test design update#3
ritikrishu wants to merge 3 commits intomainfrom
test/design-update

Conversation

@ritikrishu
Copy link
Contributor

@ritikrishu ritikrishu commented Feb 12, 2026

Persistent test PR for validating the design review action end-to-end.

DO NOT MERGE — this PR exists solely for triggering test workflows.

Summary by CodeRabbit

  • New Features
    • Added a "diff" review mode: reviews can show only changed frames with before/after visuals and per-file diff summaries.
    • Review comments now include per-file diff summaries and better handling of added/modified/renamed/deleted files; artifacts (screenshots) can be uploaded and a summary comment posted.
  • Style
    • Updated the card background color to a refined shade for improved visual consistency.

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/github/files.ts`:
- Around line 145-153: The blob fallback calls octokit.rest.git.getBlob and
unconditionally does blobResp.data.content.replace(...), which will throw if
content is null for very large blobs; update the blob fallback in the same block
(the code that calls octokit.rest.git.getBlob and uses blobResp.data.content) to
first check that blobResp.data.content is a string (e.g., typeof
blobResp.data.content === 'string') before calling .replace; if it's
null/undefined, handle it defensively (for example return an empty string or a
clear sentinel) instead of calling replace to avoid a null dereference.
🧹 Nitpick comments (5)
src/renderers/service.ts (2)

197-253: Unsafe cast of poll result to DiffResponse.

Line 239 casts the raw unknown poll result directly to DiffResponse without any runtime validation. If the service returns a malformed response (or the job type is somehow wrong), downstream code will fail in confusing ways.

Consider adding a minimal guard (e.g., check result.type === 'diff' and result.success !== undefined) before the cast, or use a runtime validation library.

♻️ Proposed minimal guard
     // Poll for completion (reuses existing polling logic)
-    const result = await this.pollForCompletion(submitData.jobId) as DiffResponse;
+    const raw = await this.pollForCompletion(submitData.jobId);
+    const result = raw as DiffResponse;
+    if (!result || result.type !== 'diff' || typeof result.success !== 'boolean') {
+      throw new Error(`Unexpected diff response shape from job ${submitData.jobId}`);
+    }

230-236: Duplicated usage-header logging.

The usage-header block (lines 231–236) is nearly identical to the one in fetchAllFrames (lines 323–330). Consider extracting a small helper like logUsageHeaders(resp: Response) to DRY this up.

src/comment-builder.ts (1)

350-377: Image URLs are injected unsanitized into HTML <img> tags.

Lines 356 and 371–372 embed imageUrl values from the service response directly into markdown image syntax and raw HTML <img src="..."> tags without URL validation. While GitHub's markdown renderer mitigates javascript: scheme attacks, it's worth noting that if these comments were ever rendered outside GitHub (e.g., exported, mirrored), this could become an XSS vector.

A lightweight isHttpUrl(url) guard would harden this.

src/main.ts (2)

222-222: Unsafe cast to ServiceRenderer.

initializeRenderer returns BaseRenderer. The cast relies on the mode guard at line 64 (inputs.renderer === 'service'), but if initializeRenderer ever falls through to the metadata renderer path (e.g., serviceUrl is empty despite passing validation), this cast silently succeeds yet fetchDiff won't exist on the object, causing a runtime crash.

Consider either having initializeRenderer return a discriminated type or adding a runtime check.

♻️ Proposed runtime guard
-  const renderer = await initializeRenderer(inputs) as ServiceRenderer;
+  const renderer = await initializeRenderer(inputs);
+  if (!(renderer instanceof ServiceRenderer)) {
+    throw new Error('Diff mode requires the service renderer but got: ' + renderer.name);
+  }

168-173: artifactUrl is captured but never used.

The destructured artifactUrl on line 172 is assigned but not referenced anywhere (e.g., not included in the comment or outputs). This is dead code.

♻️ Remove unused variable
     if (inputs.uploadArtifacts) {
-      const uploadResult = await uploadScreenshots(inputs.outputDir);
-      artifactUrl = uploadResult.artifactUrl;
+      await uploadScreenshots(inputs.outputDir);
     }

And remove the let artifactUrl declaration on line 169.

Comment on lines +145 to +153
// If content is empty/truncated, fall back to blob API
if (!Array.isArray(data) && 'sha' in data) {
const blobResp = await octokit.rest.git.getBlob({
owner: context.repo.owner,
repo: context.repo.repo,
file_sha: data.sha,
});
return blobResp.data.content.replace(/\n/g, '');
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Potential null dereference in blob fallback.

The GitHub Blob API can return content: null for very large blobs (over ~100 MB). Calling .replace() on null would throw a runtime error.

🛡️ Proposed defensive check
     if (!Array.isArray(data) && 'sha' in data) {
       const blobResp = await octokit.rest.git.getBlob({
         owner: context.repo.owner,
         repo: context.repo.repo,
         file_sha: data.sha,
       });
+      if (!blobResp.data.content) {
+        return null;
+      }
       return blobResp.data.content.replace(/\n/g, '');
     }
📝 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
// If content is empty/truncated, fall back to blob API
if (!Array.isArray(data) && 'sha' in data) {
const blobResp = await octokit.rest.git.getBlob({
owner: context.repo.owner,
repo: context.repo.repo,
file_sha: data.sha,
});
return blobResp.data.content.replace(/\n/g, '');
}
// If content is empty/truncated, fall back to blob API
if (!Array.isArray(data) && 'sha' in data) {
const blobResp = await octokit.rest.git.getBlob({
owner: context.repo.owner,
repo: context.repo.repo,
file_sha: data.sha,
});
if (!blobResp.data.content) {
return null;
}
return blobResp.data.content.replace(/\n/g, '');
}
🤖 Prompt for AI Agents
In `@src/github/files.ts` around lines 145 - 153, The blob fallback calls
octokit.rest.git.getBlob and unconditionally does
blobResp.data.content.replace(...), which will throw if content is null for very
large blobs; update the blob fallback in the same block (the code that calls
octokit.rest.git.getBlob and uses blobResp.data.content) to first check that
blobResp.data.content is a string (e.g., typeof blobResp.data.content ===
'string') before calling .replace; if it's null/undefined, handle it defensively
(for example return an empty string or a clear sentinel) instead of calling
replace to avoid a null dereference.

@RemoteState RemoteState deleted a comment from coderabbitai bot Feb 17, 2026
@RemoteState RemoteState deleted a comment from github-actions bot Feb 17, 2026
@RemoteState RemoteState deleted a comment from github-actions bot Feb 17, 2026
@RemoteState RemoteState deleted a comment from github-actions bot Feb 17, 2026
@RemoteState RemoteState deleted a comment from github-actions bot Feb 17, 2026
@RemoteState RemoteState deleted a comment from github-actions bot Feb 17, 2026
@github-actions
Copy link

github-actions bot commented Feb 17, 2026

🎨 Design Review

📁 1 design file (1 modified)
🖼️ 9 frames detected
9 rendered successfully

📝 test-fixtures/designs/random.pen (modified)

1. Dashboard

Screenshot saved to: .pencil-screenshots/random/1-dashboard-J1VeO.json

2. Interviews

Screenshot saved to: .pencil-screenshots/random/2-interviews-iVES0.json

3. Candidates

Screenshot saved to: .pencil-screenshots/random/3-candidates-x7cUJ.json

4. Questions Bank

Screenshot saved to: .pencil-screenshots/random/4-questions-bank-Mvlj1.json

5. AI Settings

Screenshot saved to: .pencil-screenshots/random/5-ai-settings-lwglP.json

6. Analytics

Screenshot saved to: .pencil-screenshots/random/6-analytics-pdVTW.json

7. Job Positions

Screenshot saved to: .pencil-screenshots/random/7-job-positions-pCH9A.json

8. Settings

Screenshot saved to: .pencil-screenshots/random/8-settings-7b2O7.json

Components

Screenshot saved to: .pencil-screenshots/random/components-0KJfI.json


Generated by Pencil Design Review for commit efde8e1

@github-actions
Copy link

github-actions bot commented Feb 17, 2026

🎨 Design Review

📁 1 design file (1 modified)
🖼️ Frames: 3 modified, 6 unchanged

📝 test-fixtures/designs/random.pen (modified)

✏️ Modified Frames

1. Dashboard · View full screen

BeforeAfter
Before After

6. Analytics · View full screen

BeforeAfter
Before After

8. Settings · View full screen

BeforeAfter
Before After
✅ 6 unchanged frames
    1. Interviews (iVES0)
    1. Candidates (x7cUJ)
    1. Questions Bank (Mvlj1)
    1. AI Settings (lwglP)
    1. Job Positions (pCH9A)
  • Components (0KJfI)

Generated by Pencil Actions for commit b0c94e3

@github-actions
Copy link

github-actions bot commented Feb 17, 2026

🎨 Design Review

📁 1 design file (1 modified)
🖼️ 9 frames detected
9 rendered successfully

📝 test-fixtures/designs/random.pen (modified)

1. Dashboard

1. Dashboard

2. Interviews

2. Interviews

3. Candidates

3. Candidates

4. Questions Bank

4. Questions Bank

5. AI Settings

5. AI Settings

6. Analytics

6. Analytics

7. Job Positions

7. Job Positions

8. Settings

8. Settings

Components

Components

📦 Download all screenshots (9 files)


Generated by Pencil Design Review for commit 36a5c68

@github-actions
Copy link

github-actions bot commented Feb 17, 2026

🎨 Design Review

📁 1 design file (1 modified)
🖼️ Frames: 3 modified, 6 unchanged

📝 test-fixtures/designs/random.pen (modified)

✏️ Modified Frames

1. Dashboard · View full screen

BeforeAfter
Before After

6. Analytics · View full screen

BeforeAfter
Before After

8. Settings · View full screen

BeforeAfter
Before After
✅ 6 unchanged frames
    1. Interviews (iVES0)
    1. Candidates (x7cUJ)
    1. Questions Bank (Mvlj1)
    1. AI Settings (lwglP)
    1. Job Positions (pCH9A)
  • Components (0KJfI)

Generated by Pencil Design Review for commit 36a5c68

@coderabbitai
Copy link

coderabbitai bot commented Feb 17, 2026

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

💤 Files selected but had no reviewable changes (1)
  • test-fixtures/designs/random.pen

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch test/design-update

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

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.

1 participant