Skip to content

Feat/tool integration v2 - #86

Open
Amazing-Stardom wants to merge 20 commits into
masterfrom
feat/tool-integration-v2
Open

Feat/tool integration v2#86
Amazing-Stardom wants to merge 20 commits into
masterfrom
feat/tool-integration-v2

Conversation

@Amazing-Stardom

Copy link
Copy Markdown
Contributor

No description provided.

Comment thread ui/src/pages/Reviews/ReviewDetail.tsx Fixed
@lovestaco
lovestaco marked this pull request as ready for review August 29, 2026 16:13
@LiveReview-Bot

Copy link
Copy Markdown

Implement Third-Party Tool Integration

Overview

This change introduces a new feature enabling third-party static analysis tools to run as Lambda-backed jobs during LiveReview code reviews. It establishes a comprehensive system including new database schemas, API endpoints, UI components, and job orchestration. The system aims to provide detailed tool findings and credit consumption within the review process.

Technical Highlights

  • db/migrations/*, db/schema.sql: Add available_tools, org_tools, org_tool_billing_state, and tool_credit_ledger tables.
  • internal/api/server.go, tools_handler.go: Implement new API endpoints for managing global and organization-specific tools.
  • internal/review_processor/events.go: Introduce SeverityCounts and ToolSummary structs for review event aggregation.
  • docs/tools/tools-integration-beta.md: Defines the tool_invocation River job for orchestrating Lambda-based tool execution.
  • ui/src/components/reviews/ToolAnalysisCard.tsx: New UI component displays detailed tool analysis results with filtering and pagination.
  • ui/src/pages/Reviews/ReviewDetail.tsx: Integrates ToolAnalysisCard and processes tool accounting data for display.
  • internal/api/diff_review.go: Gracefully handles decoding failures for reviews without AI comments.
  • ui/src/components/Dashboard/widgets/ToolsUsageWidget.tsx: Adds a new dashboard widget for tool usage overview.

Impact

  • Functionality: Users can now integrate, configure, and view results from third-party static analysis tools directly within code reviews. Review summaries include detailed tool findings and severity counts.
  • Risk: New database schemas require careful migration and data integrity checks. The hasNoReviewLayerData function in ReviewLayersData.tsx now always returns false, potentially affecting existing dashboard logic. Extensive mock data usage in ReviewDetail.tsx could mask real API issues during development.


1. THE System SHALL provide an `available_tools` table with columns: `id` (bigserial primary key), `name` (text not null unique), `description` (text not null), and `lambda_arn` (text not null).
2. THE System SHALL seed the `available_tools` table with at least two initial rows: one for `ruff` and one for `pylint`, each with a non-empty `description` and a placeholder `lambda_arn`.
3. THE System SHALL manage the `available_tools` schema exclusively through dbmate migration files located in `db/migrations/`, and SHALL NOT apply these migrations directly to any production database.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Severity: critical

The dbmate migrations have not been applied to the production environment. The strategy for updating the schema needs to be clarified.

Suggestions:

  1. Clarify how production database schema updates will be managed if dbmate migrations are not applied directly.
  2. Reconcile this statement with standard dbmate usage for all environments.


1. THE System SHALL provide an `org_tools` table with columns: `org_id` (bigint not null, references `organizations.id`), `tool_id` (bigint not null, references `available_tools.id`), `enabled` (boolean not null default false), `config_json` (jsonb not null default `'{}'`), and a composite primary key on (`org_id`, `tool_id`).
2. THE System SHALL enforce that every row in `org_tools` references a valid `org_id` in the `organizations` table and a valid `tool_id` in the `available_tools` table via foreign key constraints.
3. THE System SHALL manage the `org_tools` schema exclusively through dbmate migration files and SHALL NOT apply these migrations directly to any production database.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Severity: critical

The dbmate migrations have not been applied to the production environment. The strategy for updating the schema needs to be clarified.

Suggestions:

  1. Clarify how production database schema updates will be managed if dbmate migrations are not applied directly.
  2. Reconcile this statement with standard dbmate usage for all environments.

1. WHEN `isCloudMode()` returns `true` AND the authenticated user's role is `owner`, THE Settings Page SHALL render a navigable tab at the hash route `third-party-tools` within `/#/settings`.
2. WHEN `isCloudMode()` returns `false`, THE Settings Page SHALL NOT render the `third-party-tools` tab.
3. WHEN the authenticated user's role is not `owner`, THE Settings Page SHALL NOT render the `third-party-tools` tab as a clickble navigation item.
4. WHEN a non-owner org member navigates directly to `/#/settings#third-party-tools`, THE Settings Page SHALL render a read-only view of the enabled tools without controls to modify them.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Severity: warning

A read-only view should be implemented for non-owners. Ensure that no sensitive configuration information is exposed through this view.

Suggestions:

  1. Verify that the read-only view for non-owners does not expose any sensitive configuration details that should be restricted.
  2. Implement robust data filtering on the backend for read-only access.

id bigserial PRIMARY KEY,
name text NOT NULL UNIQUE,
description text NOT NULL,
lambda_arn text NOT NULL,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Severity: warning

The lambda_arn column is defined as NOT NULL, but the seeding process requires placeholders. This needs to be reconciled with requirement R1.2.

Suggestions:

  1. Clarify how lambda_arn will be handled for initial seeded tools (R1.2) if they are NOT NULL and 'no hardcoded ARNs belong here'.
  2. Consider allowing NULL initially or ensuring a robust placeholder/update mechanism.

name text NOT NULL UNIQUE,
description text NOT NULL,
lambda_arn text NOT NULL,
multiplier numeric(6,2) NOT NULL DEFAULT 1.0,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Severity: warning

A multiplier column has been added. Its purpose is not clear from the schema definition.

Suggestions:

  1. Add a comment or documentation explaining the purpose and usage of the multiplier column.

description text NOT NULL,
lambda_arn text NOT NULL,
multiplier numeric(6,2) NOT NULL DEFAULT 1.0,
use_case text NOT NULL DEFAULT '',

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Severity: warning

A use_case column has been added. Its purpose is not clear from the schema definition.

Suggestions:

  1. Add a comment or documentation explaining the purpose and usage of the use_case column.

created_at timestamptz NOT NULL DEFAULT now()
);

-- Tools are registered via the lr-tools deployer's `register-tools` command,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Severity: critical

This comment conflicts with requirement R1.2, which specifies seeding with placeholder ARNs.

Suggestions:

  1. Reconcile this comment with Requirement 1.2, which states that available_tools should be seeded with placeholder lambda_arns.
  2. Clarify if seeding happens outside of this migration or if placeholders are acceptable here.

@@ -0,0 +1,15 @@
-- migrate:up
CREATE TABLE IF NOT EXISTS public.org_tools (
org_id bigint NOT NULL REFERENCES public.orgs(id) ON DELETE CASCADE,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Severity: warning

The ON DELETE CASCADE option is used for the orgs table. Please confirm that this aligns with the business logic requirements.

Suggestions:

  1. Confirm that cascading deletion of org_tools entries upon orgs deletion aligns with business requirements.
  2. Consider ON DELETE RESTRICT or SET NULL if org_tools data needs to be preserved or handled differently.

-- migrate:up
CREATE TABLE IF NOT EXISTS public.org_tools (
org_id bigint NOT NULL REFERENCES public.orgs(id) ON DELETE CASCADE,
tool_id bigint NOT NULL REFERENCES public.available_tools(id) ON DELETE CASCADE,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Severity: warning

The ON DELETE CASCADE option is used for the available_tools table. Please confirm that this aligns with the business logic requirements.

Suggestions:

  1. Confirm that cascading deletion of org_tools entries upon available_tools deletion aligns with business requirements.
  2. This is generally acceptable, as configurations for a non-existent tool are usually irrelevant.

tool_id bigint NOT NULL REFERENCES public.available_tools(id) ON DELETE CASCADE,
enabled boolean NOT NULL DEFAULT false,
config_json jsonb NOT NULL DEFAULT '{}',
updated_at timestamptz NOT NULL DEFAULT now(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Severity: warning

The updated_at column lacks an ON UPDATE trigger, meaning it is only set upon insertion and not updated thereafter.

Suggestions:

  1. Add an ON UPDATE trigger to automatically update the updated_at timestamp whenever a row in org_tools is modified.
  2. Consider using the org_tool_billing_state_set_updated_at() function if applicable.

Comment thread db/schema.sql
@@ -1,7 +1,7 @@
\restrict dbmate

-- Dumped from database version 15.17 (Debian 15.17-1.pgdg13+1)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Severity: warning

There is a PostgreSQL version bump from 15.17 to 16.14. Please ensure compatibility with existing applications and queries.

Suggestions:

  1. Verify compatibility of all application components and dependencies with PostgreSQL 16.14.
  2. Ensure all environments (dev, staging, prod) are aligned or tested for this version.

Comment thread db/schema.sql
Comment thread db/schema.sql

--
-- Name: scheduled_review_configs scheduled_review_configs_repository_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
-- Name: scheduled_review_configs scheduled_review_configs_org_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

When performing the foreign key swap for scheduled_review_configs, ensure that the migration correctly handles existing rows.

Suggestions:

  1. Verify that all existing repository_id values map correctly to org_id via the new FK.

Comment thread docs/openapi.yaml
operationId: UpdateUser
parameters:
- in: path
name: org_id

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: critical

There is a parameter order mismatch; please check the potential impact on client-side functionality.

Suggestions:

  1. Audit all API clients for breaking changes due to parameter swap.
  2. Verify backend route handler matches new parameter order.

- Procedural sentences contain a maximum of 20 words.
- Descriptive sentences contain a maximum of 25 words.
- All verbs use simple present, simple past, or simple future tenses.
- The text avoids unapproved modal verbs (`should`, `would`, `may`, `might`, `could`).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

The unapproved modal verb 'should' is used here, which violates the STE100 rules.

Suggestions:

  1. Replace 'should' with 'must' or 'will' to comply with Simplified Technical English requirements.

if callErr != nil {
return "", 0, 0, callErr
}
return text, len(input) / 4, len(text) / 4, nil

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

The heuristic token estimation, calculated as len/4, is inaccurate and may lead to billing or quota issues.

Suggestions:

  1. Use a proper tokenizer library (e.g., tiktoken-go) instead of length/4.
  2. Log a warning when falling back to estimation.

} else if len(dbComments) > 0 {
for _, dbC := range dbComments {
var contentMap map[string]interface{}
if err := json.Unmarshal(dbC.Content, &contentMap); err != nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

Unmarshaling comment content inside a loop could become a potential performance bottleneck, especially for large reviews.

Suggestions:

  1. Consider batch processing or pre-fetching if comment volume is high.

dbURL = os.Getenv("DATABASE_URL")
}
if dbURL == "" {
dbURL = "postgres://livereview:livereview_password_123@localhost:5432/livereview?sslmode=disable"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

Database credentials are hardcoded directly within the test, which is not recommended.

Suggestions:

  1. Use environment variables exclusively for test DB configuration.

if err := c.Bind(&req); err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid request body"})
}
if req.Name == "" || req.LambdaARN == "" {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

Validation for empty strings is missing; consider using a validator package or adding explicit checks.

Suggestions:

  1. Implement a struct validation library like go-playground/validator
  2. Add explicit checks for all required fields


for _, tool := range enabledTools {
dispatchJSON := fmt.Sprintf(`{"tool_id": %d, "tool_name": %q, "status": "pending"}`, tool.ID, tool.Name)
if _, execErr := w.db.ExecContext(ctx, `

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

Direct SQL execution within a loop is present, which could lead to a potential performance bottleneck.

Suggestions:

  1. Batch insert review events using a single query
  2. Use a transaction if multiple inserts are required

LambdaARN: tool.LambdaARN,
DiffZipBase64: args.DiffZipBase64,
}
if err := w.jq.QueueToolReviewJob(ctx, toolJobArgs); err != nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

Error handling for failed job queueing is missing, which results in a silent failure.

Suggestions:

  1. Return error to stop processing if critical
  2. Implement retry logic or dead-letter queueing

}

// NewToolReviewWorker creates a new ToolReviewWorker with AWS config loaded from env.
func NewToolReviewWorker(db *sql.DB) *ToolReviewWorker {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

In NewToolReviewWorker, no context is being passed to LoadDefaultConfig.

Suggestions:

  1. Pass the provided context.Context to config.LoadDefaultConfig for proper cancellation and tracing.

accessKey := os.Getenv("AWS_ACCESS_KEY_ID")
secretKey := os.Getenv("AWS_SECRET_ACCESS_KEY")
region := os.Getenv("AWS_REGION")
if region == "" {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

The AWS region is hardcoded; consider making it configurable.

Suggestions:

  1. Make the AWS region configurable via an environment variable or a dedicated configuration struct.
  2. Ensure AWS_REGION is always set in deployment environments.

}
if err != nil {
log.Printf("[WARN] ToolReviewWorker: failed to load AWS config: %v. Creating fallback config.", err)
awsCfg = aws.Config{Region: region}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

The use of a fallback AWS configuration might inadvertently hide critical errors.

Suggestions:

  1. Re-evaluate if a fallback config is truly desired. If config.LoadDefaultConfig fails, it often indicates a critical environment setup issue that should halt the worker.
  2. If fallback is necessary, ensure it's well-documented and its limitations are understood.

_ = eventSink.EmitLogEvent(ctx, args.ReviewID, args.OrgID, "error", fmt.Sprintf("Lambda execution for tool %s failed: %v", args.ToolName, err), "")
// Write synthetic failure event
toolsStore := storagetools.NewToolsStore(w.db)
failJSON := fmt.Sprintf(`{"exit_code": -1, "findings": [], "stderr": %q}`, err.Error())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

The construction of the synthetic failure event JSON carries a potential injection risk.

Suggestions:

  1. Sanitize err.Error() before embedding it directly into a JSON string to prevent malformed JSON or unexpected data.
  2. Consider using json.Marshal for the failJSON object to ensure proper escaping and structure.

}

// Parse findings and classify using deterministic rule map + taxonomy
var altResp struct {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: info

A large anonymous struct is used for the Lambda response; it would be better to define a named struct for clarity and maintainability.

Suggestions:

  1. Extract this anonymous struct into a named type (e.g., LambdaToolResponse) for better readability and reusability.
  2. Consider defining sub-structs for Findings and Start/Extra fields.

} `json:"extra"`
} `json:"findings"`
}
if jsonErr := json.Unmarshal(outBytes, &altResp); jsonErr != nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

An unmarshal error is logged as a WARN, but processing continues, which might lead to unexpected behavior.

Suggestions:

  1. Clarify if this behavior is intended. If malformed JSON from Lambda should prevent classification, then return fmt.Errorf(...) here.
  2. If continuing is desired, document why a partial success (raw stored, classification skipped) is acceptable.

if jsonErr := json.Unmarshal(outBytes, &altResp); jsonErr != nil {
log.Printf("[WARN] ToolReviewWorker: failed to unmarshal Lambda findings output for tool=%s review=%d: %v", args.ToolName, args.ReviewID, jsonErr)
} else if len(altResp.Findings) > 0 {
rawList := make([]toolclassifier.RawToolFinding, len(altResp.Findings))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

The logic for extracting finding fields is complex and appears brittle to future changes.

Suggestions:

  1. Centralize this logic if multiple tools have similar output variations.
  2. Consider a more robust mapping or adapter pattern if tool outputs are highly variable.
  3. Add comments explaining the priority order for field extraction.

rm := reviewprocessor.NewReviewManager(w.db)
stored := 0
for _, c := range classifiedComments {
if c == nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

There is a nil check for a classified comment, but ClassifyToolResult should ideally not return nil elements.

Suggestions:

  1. Review toolclassifier.ClassifyToolResult to ensure it does not return nil elements in the slice.
  2. If nil elements are possible, add a comment explaining why and if they should be filtered earlier.

}

// finalizeIfAllDone checks if all dispatched tools have returned results and marks the review completed.
func (w *ToolReviewWorker) finalizeIfAllDone(ctx context.Context, args ToolReviewJobArgs) error {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: critical

There is a race condition risk because multiple workers can finalize concurrently.

Suggestions:

  1. Implement a distributed lock (e.g., using pg_advisory_lock) around the finalizeIfAllDone logic for a given review_id.
  2. Consider using a transactional approach or a single-threaded finalization mechanism to prevent multiple completion events or status updates.

// finalizeIfAllDone checks if all dispatched tools have returned results and marks the review completed.
func (w *ToolReviewWorker) finalizeIfAllDone(ctx context.Context, args ToolReviewJobArgs) error {
var pendingJobs int
err := w.db.QueryRowContext(ctx, `

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

The SQL query is inefficient due to JSON field extraction being performed within the WHERE or NOT IN clauses.

Suggestions:

  1. Add a GIN index on the data column for review_events to speed up JSON key lookups (e.g., CREATE INDEX idx_review_events_data_tool_name ON public.review_events USING GIN (data jsonb_path_ops);).
  2. Consider restructuring review_events schema to have tool_name as a direct column if this query is frequent, avoiding JSON extraction overhead.


eventSink := reviewprocessor.NewDatabaseEventSink(w.db)
if emitErr := eventSink.EmitCompletionEvent(ctx, args.ReviewID, args.OrgID,
"### Static Analysis Tools Review Only\n\nAI review skipped due to --tools flag.",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

The completion message is hardcoded and may not always be accurate.

Suggestions:

  1. Make the completion message dynamic based on the actual review type or flags.
  2. Pass the appropriate message as an argument to finalizeIfAllDone.

Comment thread internal/license/plans.go

// IsToolsEligible returns true if the plan type is eligible for static analysis tool credit deduction.
func IsToolsEligible(p PlanType) bool {
if p == PlanType("") {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

An empty PlanType currently returns true; please clarify the intended behavior.

Suggestions:

  1. Clarify if an empty PlanType should indeed be eligible for tools. This might allow tool usage without a valid plan.
  2. If not intended, change return true to return false or handle PlanType("") as an invalid state.

return nil, nil
}

var raw map[string]interface{}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

Manual type assertions are used for each field, which makes the code verbose and error-prone.

Suggestions:

  1. Consider using a library like mapstructure for safer, more concise mapping from map[string]interface{} to ToolRuleConfig.
  2. Extract field parsing logic into smaller helper functions for enabled, category, include, exclude.

results[toolName] = &ToolRuleConfig{Enabled: &bVal}
case map[string]interface{}:
cfg := &ToolRuleConfig{}
if enabledRaw, exists := v["enabled"]; exists && enabledRaw != nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: info

The repeated exists && enabledRaw != nil checks appear redundant.

Suggestions:

  1. Simplify: if enabledVal, ok := v["enabled"].(bool); ok { cfg.Enabled = &enabledVal }. If key doesn't exist or is nil, ok will be false.

}
}
if incRaw, exists := v["include"]; exists && incRaw != nil {
if incSlice, ok := incRaw.([]interface{}); ok {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

Non-string items in the include slice are silently skipped, which could lead to potential configuration misinterpretation.

Suggestions:

  1. Add logging for non-string items in include or exclude to alert users to malformed configuration.
  2. Consider returning an error if unexpected types are found, making configuration stricter.

}
}
}
if excRaw, exists := v["exclude"]; exists && excRaw != nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

Non-string items in the exclude slice are silently skipped, which could lead to potential configuration misinterpretation.

Suggestions:

  1. Add logging for non-string items in include or exclude to alert users to malformed configuration.
  2. Consider returning an error if unexpected types are found, making configuration stricter.

return true
}

var includeMatcher *gitignore.GitIgnore

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

The gitignore matcher creation logic is duplicated in both ShouldRunToolRuleForDiff and FilterLocalCodeDiffsForTool.

Suggestions:

  1. Extract createGitIgnoreMatchers(cfg *ToolRuleConfig) helper function to return (includeMatcher, excludeMatcher *gitignore.GitIgnore).
  2. Call this helper once at the start of both functions.

}

matchingFilesCount := 0
for _, d := range diffs {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

The path extraction logic is duplicated in both ShouldRunToolRuleForDiff and FilterLocalCodeDiffsForTool.

Suggestions:

  1. Extract getDiffPath(d lib.LocalCodeDiff) helper function.
  2. Call this helper within the loop in both functions.

return diffs
}

var includeMatcher *gitignore.GitIgnore

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

The gitignore matcher creation logic is duplicated in both ShouldRunToolRuleForDiff and FilterLocalCodeDiffsForTool.

Suggestions:

  1. Extract createGitIgnoreMatchers(cfg *ToolRuleConfig) helper function to return (includeMatcher, excludeMatcher *gitignore.GitIgnore).
  2. Call this helper once at the start of both functions.


var filtered []lib.LocalCodeDiff
for _, d := range diffs {
path := d.NewPath

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

The path extraction logic is duplicated in both ShouldRunToolRuleForDiff and FilterLocalCodeDiffsForTool.

Suggestions:

  1. Extract getDiffPath(d lib.LocalCodeDiff) helper function.
  2. Call this helper within the loop in both functions.


b.WriteString(fmt.Sprintf("diff --git a/%s b/%s\n", oldPath, newPath))
if d.OldPath == "/dev/null" || d.OldPath == "" {
b.WriteString("new file mode 100644\n")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Severity: warning

The file mode 100644 is hardcoded and may not be accurate for all file types, such as executables.

Suggestions:

  1. If lib.LocalCodeDiff contains file mode information, use that instead.
  2. If not, consider if 100644 is always acceptable or if a default is sufficient for current use cases.

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.

5 participants