Skip to content

Test/diff actions ai#40

Draft
yifancong wants to merge 11 commits intomainfrom
test/diff-actions-ai
Draft

Test/diff actions ai#40
yifancong wants to merge 11 commits intomainfrom
test/diff-actions-ai

Conversation

@yifancong
Copy link
Copy Markdown
Contributor

No description provided.

Copilot AI review requested due to automatic review settings March 23, 2026 11:19
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 23, 2026

Rsdoctor Bundle Diff Analysis

Found 2 projects in monorepo, 1 project with changes.

📊 Quick Summary
Project Total Size Change
rsbuild-demo 190.1 KB -231.0 B (-0.1%)
rsbuild-demo2 190.3 KB 0
📋 Detailed Reports (Click to expand)

📁 rsbuild-demo

Path: examples/rsbuild-demo/dist/.rsdoctor/rsdoctor-data.json

📌 Baseline Commit: 2aaf6eac24 | PR: #37

Metric Current Baseline Change
📊 Total Size 190.1 KB 190.4 KB -231.0 B (-0.1%)
📄 JavaScript 188.3 KB 188.5 KB -231.0 B (-0.1%)
🎨 CSS 345.0 B 345.0 B 0
🌐 HTML 374.0 B 374.0 B 0
📁 Other Assets 1.2 KB 1.2 KB 0

📦 Download Diff Report: rsbuild-demo Bundle Diff

🤖 AI Degradation Analysis (Click to expand)

📁 rsbuild-demo

📦 Bundle Size Analysis Report

1. Size Regression Summary

Metric Baseline Current Diff % Change Status
Total Bundle 279.2 KB 279.4 KB +211 B +0.07% ⚠️ Up
Initial JS 278.0 KB 278.2 KB +211 B +0.07% ⚠️ Up
Initial CSS 430 B 430 B 0 B 0% ✅ -
  • Critical Thresholds: No assets exceeded the >10 KB or >5% total bundle increase threshold.
  • Observation: The increase is statistically negligible.

2. Root Cause Analysis

The entire size increase is attributed to a single module change:

  • File: src/App.tsx
  • Change: Parsed size increased by 205 B (+23.48%).
  • Note: Interestingly, the source size decreased slightly (-8 B), but the parsed size increased. This suggests the transpilation process (TypeScript/SWC/Babel) may have generated slightly more verbose output for the new logic, or helper functions were inlined.

3. Risk Assessment

Severity: 🟢 Low

  • Justification: A 211-byte increase on the initial chunk is imperceptible to users and will not impact Load Time, TTI, or Core Web Vitals. It is within the margin of measurement noise for most build tools.

4. Optimization Recommendations

  • ✅ Safe to Merge: No optimization is required for this specific diff.
  • 🔍 Code Review: While performance is not impacted, reviewers should verify the logic changes in src/App.tsx to ensure the increase in parsed size wasn't due to accidental large dependency imports (though package analysis shows no new dependencies).
  • 🔧 Configuration: No changes to Webpack/Rspack configuration are needed.

Generated by Rsdoctor Bundle Analyzer

Analysis by qwen3.5-plus

📁 rsbuild-demo2

📦 Bundle Size Analysis Report

✅ No Significant Regressions Detected

Metric Baseline Current Diff % Change
Total Bundle 279.2 KB 279.4 KB +211 B +0.07%
Initial JS 278.0 KB 278.2 KB +211 B +0.07%
CSS 430 B 430 B 0 B 0%

1. Size Regression Summary

  • Total Increase: Negligible (+211 bytes).
  • Critical Assets: No initial chunks or assets exceeded the >10 KB or >5% significant threshold.
  • New Assets: None added.

2. Root Cause Analysis

  • Module Change: The entire size increase originates from src/App.tsx.
    • Parsed Size: +205 bytes (873 B → 1078 B).
    • Gzip Size: +23 bytes.
    • Reason: Likely minor logic updates or component structure changes within the main app entry. No new dependencies were introduced.

3. Risk Assessment

  • Severity: 🟢 Low
  • Justification: The total bundle size increase is minimal (~0.2 KB) and well within normal build variance. It will have no measurable impact on load times or Core Web Vitals.

4. Optimization Recommendations

  • Action: None required.
  • Note: The change in App.tsx is acceptable. Continue monitoring if future changes to this file introduce heavy libraries or unoptimized renders.

Generated by Rsdoctor Bundle Analyzer

Analysis by qwen3.5-plus

Generated by Rsdoctor GitHub Action

@yifancong yifancong marked this pull request as draft March 23, 2026 11:27
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds optional AI-powered degradation analysis to the Rsdoctor GitHub Action, generating an additional markdown section in PR comments based on an Rsdoctor bundle-diff JSON output.

Changes:

  • Add src/ai-analysis.ts to call Anthropic/OpenAI and produce a markdown analysis from bundle-diff JSON.
  • Extend src/index.ts to generate bundle-diff --json, run AI analysis when AI_TOKEN is set, and append results to the PR comment.
  • Add ai_model input to action.yml; update built artifact in dist/ (and includes a small example app change).

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src/index.ts Generates JSON bundle diff and appends AI analysis to PR comment when enabled.
src/ai-analysis.ts Implements provider detection, prompt building, and API calls to generate markdown analysis.
action.yml Adds ai_model input for configuring the AI model.
examples/rsbuild-demo/src/App.tsx Comments out a duplicate button block in the demo app.
dist/index.js Updates compiled distribution bundle to include new functionality.

Comment thread src/index.ts
Comment on lines +267 to +269
// Generate JSON diff for AI analysis (requires @rsdoctor/cli >= 1.5.6-canary.0)
if (aiToken) {
try {
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

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

This comment says the JSON diff requires @rsdoctor/cli >= 1.5.6-canary.0, but package.json currently pins @rsdoctor/cli to 1.3.3-beta.2. With the pinned version, the --json invocation is likely to fail (and the catch block logs a misleading “CLI not found” message). Either bump the dependency to a version that supports bundle-diff --json or gate the JSON generation by detecting support (and log an accurate error when the command fails).

Copilot uses AI. Check for mistakes.
Comment thread src/index.ts Outdated
}

const resolvedJsonPath = fs.existsSync(diffJsonPath) ? diffJsonPath : defaultDiffJsonPath;
report.aiAnalysis = await analyzeWithAI(resolvedJsonPath, aiToken, aiModel);
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

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

resolvedJsonPath can end up pointing to defaultDiffJsonPath even if neither JSON file was produced (e.g., rsdoctor command failed). analyzeWithAI will then log “not found” and skip, but from this call-site it’s hard to tell whether JSON generation succeeded. Consider explicitly checking existsSync(resolvedJsonPath) after running rsdoctor and only calling analyzeWithAI (or logging a clearer message) when the JSON output was actually created.

Suggested change
report.aiAnalysis = await analyzeWithAI(resolvedJsonPath, aiToken, aiModel);
if (fs.existsSync(resolvedJsonPath)) {
report.aiAnalysis = await analyzeWithAI(resolvedJsonPath, aiToken, aiModel);
} else {
console.warn(
`⚠️ rsdoctor JSON diff file not found for AI analysis. Expected at "${resolvedJsonPath}". ` +
`Skipping AI analysis.`
);
}

Copilot uses AI. Check for mistakes.
Comment thread src/index.ts
Comment on lines +602 to +610
commentBody += '<details>\n<summary><b>🤖 AI Degradation Analysis</b> (Click to expand)</summary>\n\n';
for (const report of reportsWithAI) {
if (!report.aiAnalysis) continue;
if (reportsWithAI.length > 1) {
commentBody += `#### 📁 ${report.projectName}\n\n`;
}
commentBody += report.aiAnalysis.analysis + '\n\n';
commentBody += `<sub>Analysis by ${report.aiAnalysis.model}</sub>\n\n`;
}
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

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

The AI-generated markdown is appended directly into the PR comment body. Since this content comes from an external service and is influenced by repo-controlled input (prompt injection via bundle/module names), it can produce unwanted mentions (@org/@user), links, or very large output that may exceed GitHub’s comment size limits. Consider sanitizing the analysis before posting (e.g., neutralize @ to avoid mentions, optionally strip/limit links/images) and truncating to a safe maximum length with a note when truncated.

Copilot uses AI. Check for mistakes.
Comment thread action.yml Outdated
default: ''
type: string
ai_model:
description: 'AI model to use for degradation analysis (e.g. claude-3-5-haiku-latest, gpt-4o-mini). Provider is auto-detected from the model name prefix.'
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

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

ai_model is configurable, but enabling the feature requires setting AI_TOKEN via environment variables; that requirement isn’t discoverable from action.yml. Consider adding an explicit ai_token input (intended for secrets.*) or at least documenting in the input description that an environment variable is required and that bundle diff JSON will be sent to a third-party AI provider when enabled.

Suggested change
description: 'AI model to use for degradation analysis (e.g. claude-3-5-haiku-latest, gpt-4o-mini). Provider is auto-detected from the model name prefix.'
description: 'AI model to use for degradation analysis (e.g. claude-3-5-haiku-latest, gpt-4o-mini). Provider is auto-detected from the model name prefix. Requires an AI_TOKEN environment variable (typically from secrets.*) for the provider API key, and when enabled the bundle diff JSON will be sent to the selected third-party AI provider.'

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +20
{/* <button onClick={handleClick} className="primary-button">
Click Me!
</button>
<button onClick={() => console.log('Secondary button')} className="secondary-button">
Secondary Action
</button>
</button> */}
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

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

This change comments out an entire button block, but the file already renders the same buttons in the next <div className="button-container">. If this was only for local debugging, it should be removed/reverted to keep the example clean; if it’s intentional, consider deleting the duplicate section rather than leaving commented JSX in the source.

Copilot uses AI. Check for mistakes.
Comment thread src/index.ts
Comment on lines +285 to +287
const shellCmd = `npx @rsdoctor/cli bundle-diff --json --baseline="${baselineJsonPath}" --current="${fullPath}"`;
console.log(`🛠️ Running rsdoctor --json via npx: ${shellCmd}`);
await execFileAsync('sh', ['-c', shellCmd], { cwd: tempOutDir });
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

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

The fallback path uses execFileAsync('sh', ['-c', shellCmd], ...) with a command string that interpolates baselineJsonPath / fullPath. This is shell-injection prone if any path contains quotes or shell metacharacters (paths come from the repo/glob input), and it also makes quoting/escaping brittle across platforms. Prefer invoking npx (or the local node_modules/.bin/rsdoctor) via execFile with an argv array (no shell), e.g. execFileAsync('npx', ['--no-install','@rsdoctor/cli','bundle-diff','--json', ...]) or directly running the resolved bin.

Suggested change
const shellCmd = `npx @rsdoctor/cli bundle-diff --json --baseline="${baselineJsonPath}" --current="${fullPath}"`;
console.log(`🛠️ Running rsdoctor --json via npx: ${shellCmd}`);
await execFileAsync('sh', ['-c', shellCmd], { cwd: tempOutDir });
const npxArgs = [
'@rsdoctor/cli',
'bundle-diff',
'--json',
`--baseline=${baselineJsonPath}`,
`--current=${fullPath}`,
];
console.log(`🛠️ Running rsdoctor --json via npx: npx ${npxArgs.join(' ')}`);
await execFileAsync('npx', npxArgs, { cwd: tempOutDir });

Copilot uses AI. Check for mistakes.
Comment thread src/ai-analysis.ts
Comment on lines +33 to +35
const data = await response.json() as any;
return data.content[0].text as string;
}
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

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

callAnthropicAPI assumes data.content[0].text exists. If the API returns an error shape (or content is empty), this will throw a confusing runtime error later. Consider validating the response JSON structure and throwing a clearer error when expected fields are missing (similar for OpenAI response parsing).

Copilot uses AI. Check for mistakes.
Comment thread src/ai-analysis.ts
Comment on lines +56 to +58
const data = await response.json() as any;
return data.choices[0].message.content as string;
}
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

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

callOpenAIAPI assumes data.choices[0].message.content exists. If the response is missing choices (rate limit, validation error, etc.), this will throw a non-actionable exception. Add minimal shape checks (e.g., ensure choices is an array and the content is a string) and include provider/model context in the thrown error to aid debugging.

Copilot uses AI. Check for mistakes.
Comment thread src/ai-analysis.ts
Comment on lines +98 to +106
export async function analyzeWithAI(
diffJsonPath: string,
token: string,
model = 'claude-3-5-haiku-latest',
): Promise<AIAnalysisResult | null> {
if (!token) {
console.log('ℹ️ No AI token provided, skipping AI analysis');
return null;
}
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

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

New AI analysis functionality is introduced here, but there are no tests covering the new module. The repo already uses @rstest/core with mocks (see src/__tests__). Please add unit tests for analyzeWithAI covering: no token, missing JSON file, provider detection from model name, and successful/failed API calls (mock fetch responses).

Copilot uses AI. Check for mistakes.
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