Skip to content

Added e2e test heatmap and coverage dashboard - #10

Merged
arxdsilva merged 14 commits into
arxdsilva:mainfrom
RaihanSultana:main
Jun 8, 2026
Merged

Added e2e test heatmap and coverage dashboard#10
arxdsilva merged 14 commits into
arxdsilva:mainfrom
RaihanSultana:main

Conversation

@RaihanSultana

@RaihanSultana RaihanSultana commented Jun 5, 2026

Copy link
Copy Markdown
Contributor
  1. Added e2e(frontend) test screen to see run history, failed specs and pass rates
  2. Added e2e test heatmap to view all project and the test status in each environment
  3. Added e2e-upload CLI command for e2e test ingestion.
  4. Added NormalizePlaywrightReport function to normalize playwright report
  5. Unit test for the above changes

Summary by CodeRabbit

  • New Features

    • E2E test run ingestion, storage and pass-rate comparisons vs baseline.
    • New /e2e console UI with run listings, branch/environment/platform filters, failed-spec details, heatmap overlay and auto-refresh.
    • New API endpoints to ingest and query E2E runs and heatmap data.
    • CLI: added an e2e-upload command for uploading Playwright/Appium reports.
  • Tests

    • Added unit tests and fixtures covering report normalization and E2E use cases.

@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8586cc53-cf50-4d87-9e7d-655c5bd3f9d2

📥 Commits

Reviewing files that changed from the base of the PR and between 37d20f7 and f620d20.

📒 Files selected for processing (4)
  • cmd/api/main.go
  • cmd/coveragecli/main.go
  • internal/platform/bootstrap/bootstrap.go
  • migrations/003_e2e_test_runs.sql
🚧 Files skipped from review as they are similar to previous changes (2)
  • migrations/003_e2e_test_runs.sql
  • cmd/coveragecli/main.go

📝 Walkthrough

Walkthrough

This PR implements end-to-end test run management: domain types and migrations, Postgres repositories, application use-cases (ingest/list/compare/get/heatmap), HTTP handlers/routes, CLI upload and Playwright normalization, frontend /e2e console and assets, and wiring in bootstrap/api.

Changes

End-to-End Test Run Management Feature

Layer / File(s) Summary
Domain model and DB schema
internal/domain/e2e.go, migrations/003_e2e_test_runs.sql
Adds E2E run/spec enums and structs and migrations to create e2e_test_runs and e2e_test_spec_results with constraints and indexes.
Application ports & repositories
internal/application/ports.go, internal/adapters/postgres/*
Introduces TestHeatmapRow, E2E repository interfaces and Postgres implementations for runs and spec results (create, get, list, heatmap), and updates integration repo to use TestHeatmapRow.
Application use-cases
internal/application/e2e_usecase.go
Implements ingest, list, latest comparison, single-run retrieval, and heatmap use-cases with validation, entity construction, transaction persistence, comparison deltas, and grouping.
Use-case tests & stubs
internal/application/e2e_usecase_test.go, internal/application/mock_application.go
Adds comprehensive tests for use-cases and in-memory stub repositories for controlled test scenarios and error injection.
HTTP handlers & routes
internal/adapters/http/handlers.go, internal/adapters/http/router.go
Adds HTTP handlers and v1 routes for E2E run ingestion, listing, latest comparison, run retrieval, and heatmap endpoints.
CLI e2e-upload & normalization
cmd/coveragecli/main.go, cmd/coveragecli/main_test.go, cmd/coveragecli/testdata/*
Adds e2e-upload command, Playwright normalization (recursive suite traversal, duration/state/failure extraction), ANSI stripping, Appium stub, response parsing, and tests/fixtures.
Backend wiring
internal/platform/bootstrap/bootstrap.go, cmd/api/main.go
Creates E2E repositories and use-cases in bootstrap and wires them into the HTTP handler in the API main.
Frontend E2E console
cmd/frontend/web/e2eTest.html, cmd/frontend/web/assets/e2e.js, cmd/frontend/main.go, cmd/frontend/web/index.html
Adds /e2e page and assets with project/branch/status/environment filters, run list/chain, failed-spec details, auto-refresh, heatmap overlay, and sidebar navigation.

Sequence Diagram(s)

sequenceDiagram
  participant Client as Client
  participant IngestUC as IngestE2ERunUseCase
  participant ProjectRepo as ProjectRepository
  participant RunRepo as E2ETestRunRepository
  participant SpecRepo as E2ESpecResultRepository
  participant TX as TransactionManager

  Client->>IngestUC: Execute(input)
  IngestUC->>IngestUC: Validate input
  IngestUC->>ProjectRepo: Get or Create project
  ProjectRepo-->>IngestUC: project
  IngestUC->>IngestUC: Build E2ETestRun & E2ESpecResult entities
  IngestUC->>TX: Begin transaction
  IngestUC->>RunRepo: Create E2ETestRun
  RunRepo-->>IngestUC: run (with ID)
  IngestUC->>SpecRepo: CreateBatch specs
  SpecRepo-->>IngestUC: success
  IngestUC->>TX: Commit
  IngestUC->>RunRepo: Get baseline (latest on default branch)
  RunRepo-->>IngestUC: baseline
  IngestUC->>SpecRepo: List failed specs for comparison
  SpecRepo-->>IngestUC: failed specs
  IngestUC->>IngestUC: Compute deltas & pass rates
  IngestUC-->>Client: IngestE2ERunOutput
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Poem

🐰 A rabbit scurries through test-run light,
Playwright traces mapped from day to night,
CLI uploads, DB stores, UI in bloom,
Heatmaps glow and failed specs find room —
Hops of green checkmarks keep the codebase bright.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.18% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Added e2e test heatmap and coverage dashboard' accurately summarizes the main changes: introduction of E2E test functionality including a heatmap feature and UI dashboard.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🧹 Nitpick comments (6)
internal/adapters/postgres/e2e_test_run_repository.go (1)

74-83: 💤 Low value

Redundant type cast on platform field.

The platform column is already TEXT in the schema, so COALESCE(platform::text, '') can be simplified to COALESCE(platform, ''). The same pattern appears on lines 123 and 170.

♻️ Optional simplification
-		COALESCE(framework_version, ''), COALESCE(test_framework, ''), COALESCE(platform::text, ''), suite_description, suite_path, total_specs, passed_specs,
+		COALESCE(framework_version, ''), COALESCE(test_framework, ''), COALESCE(platform, ''), suite_description, suite_path, total_specs, passed_specs,

Apply the same change on lines 123 and 170.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/adapters/postgres/e2e_test_run_repository.go` around lines 74 - 83,
The SQL queries in e2e_test_run_repository (the QueryRow and other query blocks
that select platform) use a redundant platform::text cast; replace
COALESCE(platform::text, '') with COALESCE(platform, '') in the query inside the
function that calls q.QueryRow(...) (the e2e test run select), and apply the
same change to the other two occurrences found later in the file (the other
SELECTs around the blocks referenced at lines ~123 and ~170) so the platform
column is coalesced without the unnecessary ::text cast.
internal/adapters/postgres/e2e_spec_result_repository.go (1)

19-49: ⚖️ Poor tradeoff

Prefer batch INSERT over loop of individual INSERTs.

The current implementation executes N individual INSERT statements. A single multi-row INSERT (or pgx CopyFrom) would be more efficient and reduce round-trips.

Example batch insert pattern
func (r *E2ESpecResultRepository) CreateBatch(ctx context.Context, specs []domain.E2ESpecResult) error {
	if len(specs) == 0 {
		return nil
	}

	q := getQuerier(ctx, r.pool)
	
	// Build multi-row INSERT
	values := make([]string, 0, len(specs))
	args := make([]any, 0, len(specs)*9)
	for i, spec := range specs {
		offset := i * 9
		values = append(values, fmt.Sprintf("($%d, $%d, $%d, $%d, $%d, $%d, $%d, $%d, $%d)",
			offset+1, offset+2, offset+3, offset+4, offset+5, offset+6, offset+7, offset+8, offset+9))
		args = append(args,
			spec.ID, spec.E2ETestRunID, spec.SpecPath, spec.LeafNodeText,
			spec.State, spec.DurationMS, spec.FailureMessage,
			spec.FailureLocationFile, spec.FailureLocationLine,
		)
	}

	sql := fmt.Sprintf(`
		INSERT INTO e2e_test_spec_results (
			id, e2e_run_id, spec_path, leaf_node_text, state, duration_ms,
			failure_message, failure_location_file, failure_location_line
		) VALUES %s
	`, strings.Join(values, ", "))

	if _, err := q.Exec(ctx, sql, args...); err != nil {
		return fmt.Errorf("insert e2e spec results: %w", err)
	}
	return nil
}

Alternatively, consider pgx.CopyFrom for even better performance with large batches.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/adapters/postgres/e2e_spec_result_repository.go` around lines 19 -
49, The CreateBatch method on E2ESpecResultRepository currently issues one
INSERT per spec causing N round-trips; replace the loop in CreateBatch (which
uses getQuerier and q.Exec) with a single multi-row INSERT or use pgx.CopyFrom:
build a values slice of "(...)" placeholders for each spec, construct an args
[]any containing spec fields in the correct order (ID, E2ETestRunID, SpecPath,
LeafNodeText, State, DurationMS, FailureMessage, FailureLocationFile,
FailureLocationLine), join values into the SQL VALUES clause, then call
q.Exec(ctx, sql, args...) and wrap/return any error (update the error message to
"insert e2e spec results: %w"); alternatively implement pgx.CopyFrom for large
batches for better perf.
migrations/003_e2e_test_runs.sql (1)

51-52: ⚡ Quick win

Consider a composite index on (e2e_run_id, state).

The standalone index on state has low selectivity (only 5 possible values) and may not be effective. Queries typically filter specs by state within a specific run, so a composite index (e2e_run_id, state) would better support that pattern and could replace both existing indexes.

♻️ Proposed refactor for more efficient indexing
-CREATE INDEX IF NOT EXISTS e2e_test_spec_results_run_id_idx ON e2e_test_spec_results(e2e_run_id);
-CREATE INDEX IF NOT EXISTS e2e_test_spec_results_state_idx ON e2e_test_spec_results(state);
+CREATE INDEX IF NOT EXISTS e2e_test_spec_results_run_state_idx 
+  ON e2e_test_spec_results(e2e_run_id, state);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@migrations/003_e2e_test_runs.sql` around lines 51 - 52, Replace the
low-selectivity single-column state index with a composite index that matches
common query patterns: create an index e2e_test_spec_results_run_id_state_idx on
e2e_test_spec_results(e2e_run_id, state) and remove the standalone state index
e2e_test_spec_results_state_idx (you can keep the run_id index
e2e_test_spec_results_run_id_idx only if other queries need it); this ensures
queries filtering by e2e_run_id and state use the composite index for better
selectivity and performance.
cmd/coveragecli/main.go (3)

571-571: ⚡ Quick win

Use camelCase for local variables.

The variable framework_version uses snake_case. Go convention prefers camelCase for local variables.

♻️ Proposed fix
 func normalizePlaywrightReport(raw map[string]any) map[string]any {
 	var suiteDescription string
 	var suitePath string
-	var framework_version string
+	var frameworkVersion string
 
 	result := make(map[string]any)
 	testFramework := "playwright"
 
 	config := firstMap(raw, "config")
 	suites := firstSlice(raw, "suites")
 	if config != nil {
 		suitePath = firstString(config, "rootDir")
-		framework_version = firstString(config, "version")
+		frameworkVersion = firstString(config, "version")
 	}
 	if len(suites) > 0 {
 		if first, ok := suites[0].(map[string]any); ok {
 			suiteDescription = firstString(first, "title")
 		}
 	}
 	result["suiteDescription"] = suiteDescription
 	result["suitePath"] = suitePath
 	result["reportType"] = &testFramework
 	result["testFramework"] = &testFramework
-	result["frameworkVersion"] = framework_version
+	result["frameworkVersion"] = frameworkVersion
 	result["platformType"] = "web"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/coveragecli/main.go` at line 571, The local variable framework_version
uses snake_case instead of Go's camelCase convention; rename the identifier to
frameworkVersion everywhere it's declared and referenced (look for the variable
symbol framework_version in main.go, e.g., within the function scope where it is
declared) and update all usages to the new name to maintain consistency and
compile-time correctness.

592-592: ⚡ Quick win

Remove redundant platformType assignment.

Line 592 hardcodes platformType to "web", but line 486 overwrites it with the --platform-type flag value. The hardcoded assignment is redundant and could cause confusion during maintenance.

♻️ Proposed fix
 	result["suiteDescription"] = suiteDescription
 	result["suitePath"] = suitePath
 	result["reportType"] = &testFramework
 	result["testFramework"] = &testFramework
 	result["frameworkVersion"] = frameworkVersion
-	result["platformType"] = "web"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/coveragecli/main.go` at line 592, Remove the redundant hardcoded
assignment result["platformType"] = "web" — the platformType is already set from
the --platform-type flag (the platformType variable or earlier assignment around
where result is populated), so delete that line in main (or the function that
builds the result map) to avoid confusion and rely on the existing flag-derived
value.

477-477: ⚡ Quick win

Rename variable for clarity.

The variable normalizeReport holds a map result, not a function. Consider renaming to normalizedReport to avoid confusion with the normalization functions below.

♻️ Proposed fix
-	var normalizeReport map[string]any
+	var normalizedReport map[string]any
 	switch *reportType {
 	case "playwright":
-		normalizeReport = normalizePlaywrightReport(report)
+		normalizedReport = normalizePlaywrightReport(report)
 	case "appium":
-		normalizeReport = normalizeAppiumReport(report)
+		normalizedReport = normalizeAppiumReport(report)
 	default:
 		exitErr("validate input", fmt.Errorf("unsupported report type: %s", *reportType))
 	}
-	normalizeReport["platformType"] = *platformType
+	normalizedReport["platformType"] = *platformType
 
 	payload := e2ePayload{
 		ProjectKey:    *projectKey,
 		ProjectName:   *projectName,
 		ProjectGroup:  group,
 		DefaultBranch: *defaultBranch,
 		Branch:        *branch,
 		CommitSHA:     *commitSHA,
 		Author:        *author,
 		TriggerType:   *triggerType,
 		RunTimestamp:  *runTimestamp,
 		Environment:   env,
-		TestReport:    normalizeReport,
+		TestReport:    normalizedReport,
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/coveragecli/main.go` at line 477, The local variable named
normalizeReport is misleading because it suggests a function; rename it to
normalizedReport everywhere it's declared and used in main.go (the variable
declared as "var normalizeReport map[string]any") and update all references to
match, ensuring you don't collide with any normalization function names (e.g.,
any functions named normalizeReport or normalize*). Adjust any subsequent code
that reads/writes this map to use normalizedReport so identifiers remain clear
and unambiguous.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmd/frontend/web/assets/e2e.js`:
- Around line 638-646: The current UI computes pass rate as (passedRuns /
failedRuns) * 100 which produces misleading values (e.g., 900%); update the
logic around passedRuns, failedRuns, and e2ePassRate so you compute total =
passedRuns + failedRuns, return '-' if total === 0, otherwise set
e2ePassRate.textContent = `${((passedRuns / total) * 100).toFixed(2)}%` (this
makes 18 passed + 2 failed = 90.00%), and remove the special-case that outputs
'∞%' when failedRuns === 0; locate the calculation block referencing passedRuns,
failedRuns and e2ePassRate to implement this change.
- Around line 620-621: The platform query parameter being set in e2e.js is not
supported by the backend ListE2ERunsInput struct in
internal/application/e2e_usecase.go, causing the platform filter dropdown to be
ignored. To fix this, add a Platform field to the ListE2ERunsInput struct to
accept the platform parameter from the query string, update the repository query
method to filter by this platform field when it is provided, and ensure the
platform value flows through the entire chain from the HTTP handler through the
use case to the repository layer where the actual filtering logic is applied.

In `@internal/adapters/http/handlers.go`:
- Around line 177-181: Remove the premature slog.Info call that logs the
zero-value variable `in` (the slog.Info call with "name":"ingest_e2e_run" and
"stage":"decoding_input"); either delete that log line or move it to immediately
after the request body is decoded into `in` (e.g., after the call that decodes
into `in` succeeds) so that you only log the populated `in` and handle/avoid
logging on decode errors.

In `@internal/application/e2e_usecase_test.go`:
- Around line 1056-1084: In TestGetE2EHeatmapExecute remove the leftover debug
print by deleting the fmt.Println(out.Groups) statement inside the test; if you
need to record output for diagnostics use t.Logf or t.Log instead, but do not
leave fmt.Println in the TestGetE2EHeatmapExecute function (which constructs
NewGetE2EHeatmapUseCase and calls uc.Execute).

In `@internal/application/e2e_usecase.go`:
- Around line 501-520: The environment validation in ListE2ERunsUseCase.Execute
currently rejects "none" but the repository (e2e_test_run_repository.go) treats
"none" as a valid special filter for NULL environments; update the validation in
ListE2ERunsUseCase.Execute to accept "none" in addition to "test", "stage", and
"prod" and adjust the NewInvalidArgument message to reflect the allowed values
(e.g., "one of: test, stage, prod, none") so callers can filter for runs with no
environment set.

In `@migrations/003_e2e_test_runs.sql`:
- Line 45: Add a CHECK constraint on the spec result column duration_ms to
prevent negative values by altering the CREATE TABLE (or adding an ALTER TABLE)
in migrations/003_e2e_test_runs.sql so that the duration_ms BIGINT column
includes a non-negative check (e.g., ensure duration_ms >= 0) and give the
constraint a clear name (e.g., chk_spec_result_duration_ms_nonnegative) so it is
enforceable and identifiable.
- Around line 54-58: The rollback (Down) block contains duplicate DROP
statements for the tables e2e_test_spec_results and e2e_test_runs; remove the
redundant lines so each table is dropped only once (keep a single "DROP TABLE IF
EXISTS e2e_test_spec_results;" and a single "DROP TABLE IF EXISTS
e2e_test_runs;" in the Down section) to clean up the migration and avoid
copy-paste duplication.
- Line 24: Add a CHECK constraint to ensure duration_ms is non-negative: update
the migration that creates the e2e_test_runs table (column duration_ms) to
include a CHECK constraint such as CHECK (duration_ms >= 0) either inline on the
duration_ms column or as a table-level constraint; reference the duration_ms
column in the e2e_test_runs creation statement and add the constraint so
negative duration values cannot be inserted.
- Line 13: Add a CHECK constraint enforcing platform IN ('web','android','ios')
on the platform column (platform) of the e2e_test_runs table: update the column
definition in the migration (or add an ALTER TABLE ... ADD CONSTRAINT) to
include a CHECK that only allows 'web', 'android', or 'ios' values so invalid
platform strings are rejected at the DB level.
- Around line 16-21: Add SQL CHECK constraints to enforce non-negative values
and consistency: ensure total_specs, passed_specs, failed_specs, skipped_specs,
flaked_specs, and pending_specs are >= 0 and add a CHECK that passed_specs +
failed_specs + skipped_specs + flaked_specs + pending_specs = total_specs.
Modify the CREATE TABLE statement (or add an ALTER TABLE) to include checks like
CHECK (total_specs >= 0) and CHECK (passed_specs >= 0) ... for each column and a
single CHECK (passed_specs + failed_specs + skipped_specs + flaked_specs +
pending_specs = total_specs) referencing the existing column names total_specs,
passed_specs, failed_specs, skipped_specs, flaked_specs, pending_specs.

---

Nitpick comments:
In `@cmd/coveragecli/main.go`:
- Line 571: The local variable framework_version uses snake_case instead of Go's
camelCase convention; rename the identifier to frameworkVersion everywhere it's
declared and referenced (look for the variable symbol framework_version in
main.go, e.g., within the function scope where it is declared) and update all
usages to the new name to maintain consistency and compile-time correctness.
- Line 592: Remove the redundant hardcoded assignment result["platformType"] =
"web" — the platformType is already set from the --platform-type flag (the
platformType variable or earlier assignment around where result is populated),
so delete that line in main (or the function that builds the result map) to
avoid confusion and rely on the existing flag-derived value.
- Line 477: The local variable named normalizeReport is misleading because it
suggests a function; rename it to normalizedReport everywhere it's declared and
used in main.go (the variable declared as "var normalizeReport map[string]any")
and update all references to match, ensuring you don't collide with any
normalization function names (e.g., any functions named normalizeReport or
normalize*). Adjust any subsequent code that reads/writes this map to use
normalizedReport so identifiers remain clear and unambiguous.

In `@internal/adapters/postgres/e2e_spec_result_repository.go`:
- Around line 19-49: The CreateBatch method on E2ESpecResultRepository currently
issues one INSERT per spec causing N round-trips; replace the loop in
CreateBatch (which uses getQuerier and q.Exec) with a single multi-row INSERT or
use pgx.CopyFrom: build a values slice of "(...)" placeholders for each spec,
construct an args []any containing spec fields in the correct order (ID,
E2ETestRunID, SpecPath, LeafNodeText, State, DurationMS, FailureMessage,
FailureLocationFile, FailureLocationLine), join values into the SQL VALUES
clause, then call q.Exec(ctx, sql, args...) and wrap/return any error (update
the error message to "insert e2e spec results: %w"); alternatively implement
pgx.CopyFrom for large batches for better perf.

In `@internal/adapters/postgres/e2e_test_run_repository.go`:
- Around line 74-83: The SQL queries in e2e_test_run_repository (the QueryRow
and other query blocks that select platform) use a redundant platform::text
cast; replace COALESCE(platform::text, '') with COALESCE(platform, '') in the
query inside the function that calls q.QueryRow(...) (the e2e test run select),
and apply the same change to the other two occurrences found later in the file
(the other SELECTs around the blocks referenced at lines ~123 and ~170) so the
platform column is coalesced without the unnecessary ::text cast.

In `@migrations/003_e2e_test_runs.sql`:
- Around line 51-52: Replace the low-selectivity single-column state index with
a composite index that matches common query patterns: create an index
e2e_test_spec_results_run_id_state_idx on e2e_test_spec_results(e2e_run_id,
state) and remove the standalone state index e2e_test_spec_results_state_idx
(you can keep the run_id index e2e_test_spec_results_run_id_idx only if other
queries need it); this ensures queries filtering by e2e_run_id and state use the
composite index for better selectivity and performance.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bdd96296-2a7d-4b04-bd10-3d06fff09d94

📥 Commits

Reviewing files that changed from the base of the PR and between 20d303f and 37d20f7.

📒 Files selected for processing (20)
  • cmd/api/main.go
  • cmd/coveragecli/main.go
  • cmd/coveragecli/main_test.go
  • cmd/coveragecli/testdata/playwright-report-fail-dummy.json
  • cmd/coveragecli/testdata/playwright-report-pass-dummy.json
  • cmd/frontend/main.go
  • cmd/frontend/web/assets/e2e.js
  • cmd/frontend/web/e2eTest.html
  • cmd/frontend/web/index.html
  • internal/adapters/http/handlers.go
  • internal/adapters/http/router.go
  • internal/adapters/postgres/e2e_spec_result_repository.go
  • internal/adapters/postgres/e2e_test_run_repository.go
  • internal/adapters/postgres/integration_test_run_repository.go
  • internal/application/e2e_usecase.go
  • internal/application/e2e_usecase_test.go
  • internal/application/mock_application.go
  • internal/application/ports.go
  • internal/domain/e2e.go
  • migrations/003_e2e_test_runs.sql

Comment thread cmd/frontend/web/assets/e2e.js
Comment thread cmd/frontend/web/assets/e2e.js
Comment thread internal/adapters/http/handlers.go
Comment thread internal/application/e2e_usecase_test.go
Comment thread internal/application/e2e_usecase.go
Comment thread migrations/003_e2e_test_runs.sql Outdated
Comment thread migrations/003_e2e_test_runs.sql
Comment thread migrations/003_e2e_test_runs.sql
Comment thread migrations/003_e2e_test_runs.sql
Comment thread migrations/003_e2e_test_runs.sql
Comment thread cmd/coveragecli/main.go Outdated
Comment thread cmd/coveragecli/main.go Outdated
Comment thread cmd/coveragecli/main.go Outdated
Comment thread migrations/003_e2e_test_runs.sql Outdated

@arxdsilva arxdsilva left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

thanks @RaihanSultana for the contribution, lets just fix these small things and I'll merge it

@RaihanSultana

Copy link
Copy Markdown
Contributor Author

Hey @arxdsilva, resolved the above pr commented. Replaced the print statements with log/slog and added constraints for platform field in the e2e migration file. Thanks!

@RaihanSultana
RaihanSultana requested a review from arxdsilva June 8, 2026 19:19

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/platform/bootstrap/bootstrap.go`:
- Around line 41-54: Wrap returned errors with context using fmt.Errorf to
indicate which startup step failed: when migrations.Up(ctx, cfg.DatabaseURL,
cfg.MigrationsDir) returns err, replace the bare return with returning
fmt.Errorf("migrations up failed: %w", err) (and still close pool before
returning); when pool.Ping(ctx) returns err, return fmt.Errorf("database ping
failed: %w", err); also add fmt to the imports. Ensure all returns that
previously returned err directly now wrap the error with a descriptive message
referencing the failing operation (e.g., "migrations up failed" and "database
ping failed").
- Around line 40-54: The DB startup code uses raw ctx for pgxpool.New,
migrations.Up and pool.Ping which can hang; wrap each DB operation in a context
with a sensible timeout (e.g. context.WithTimeout(ctx, <reasonable duration>))
and ensure defer cancel() is called, then pass the timeoutted context into
pgxpool.New, migrations.Up(cfg.DatabaseURL, cfg.MigrationsDir, ...) and
pool.Ping; if any operation times out or errors, close the pool (use
pool.Close()) and return the error. Ensure symbols referenced are pgxpool.New,
migrations.Up, pool.Ping, runMigrations, cfg.DatabaseURL, cfg.MigrationsDir and
pool.Close.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8586cc53-cf50-4d87-9e7d-655c5bd3f9d2

📥 Commits

Reviewing files that changed from the base of the PR and between 37d20f7 and f620d20.

📒 Files selected for processing (4)
  • cmd/api/main.go
  • cmd/coveragecli/main.go
  • internal/platform/bootstrap/bootstrap.go
  • migrations/003_e2e_test_runs.sql
🚧 Files skipped from review as they are similar to previous changes (2)
  • migrations/003_e2e_test_runs.sql
  • cmd/coveragecli/main.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/platform/bootstrap/bootstrap.go`:
- Around line 41-54: Wrap returned errors with context using fmt.Errorf to
indicate which startup step failed: when migrations.Up(ctx, cfg.DatabaseURL,
cfg.MigrationsDir) returns err, replace the bare return with returning
fmt.Errorf("migrations up failed: %w", err) (and still close pool before
returning); when pool.Ping(ctx) returns err, return fmt.Errorf("database ping
failed: %w", err); also add fmt to the imports. Ensure all returns that
previously returned err directly now wrap the error with a descriptive message
referencing the failing operation (e.g., "migrations up failed" and "database
ping failed").
- Around line 40-54: The DB startup code uses raw ctx for pgxpool.New,
migrations.Up and pool.Ping which can hang; wrap each DB operation in a context
with a sensible timeout (e.g. context.WithTimeout(ctx, <reasonable duration>))
and ensure defer cancel() is called, then pass the timeoutted context into
pgxpool.New, migrations.Up(cfg.DatabaseURL, cfg.MigrationsDir, ...) and
pool.Ping; if any operation times out or errors, close the pool (use
pool.Close()) and return the error. Ensure symbols referenced are pgxpool.New,
migrations.Up, pool.Ping, runMigrations, cfg.DatabaseURL, cfg.MigrationsDir and
pool.Close.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8586cc53-cf50-4d87-9e7d-655c5bd3f9d2

📥 Commits

Reviewing files that changed from the base of the PR and between 37d20f7 and f620d20.

📒 Files selected for processing (4)
  • cmd/api/main.go
  • cmd/coveragecli/main.go
  • internal/platform/bootstrap/bootstrap.go
  • migrations/003_e2e_test_runs.sql
🚧 Files skipped from review as they are similar to previous changes (2)
  • migrations/003_e2e_test_runs.sql
  • cmd/coveragecli/main.go
🛑 Comments failed to post (2)
internal/platform/bootstrap/bootstrap.go (2)

40-54: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add timeouts for database operations during startup.

The database connection and ping operations use the raw context without a timeout. If the database is slow or unresponsive, the application startup could hang indefinitely. As per coding guidelines, sensible timeouts should be added for DB operations.

⏱️ Proposed fix to add startup timeouts
 func New(ctx context.Context, cfg config.Config, runMigrations bool) (*App, error) {
+	connCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
+	defer cancel()
+	
-	pool, err := pgxpool.New(ctx, cfg.DatabaseURL)
+	pool, err := pgxpool.New(connCtx, cfg.DatabaseURL)
 	if err != nil {
 		return nil, err
 	}
 
 	if runMigrations {
 		if err := migrations.Up(ctx, cfg.DatabaseURL, cfg.MigrationsDir); err != nil {
 			pool.Close()
 			return nil, err
 		}
 	}
 
-	if err := pool.Ping(ctx); err != nil {
+	pingCtx, pingCancel := context.WithTimeout(ctx, 5*time.Second)
+	defer pingCancel()
+	if err := pool.Ping(pingCtx); err != nil {
 		pool.Close()
 		return nil, err
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/platform/bootstrap/bootstrap.go` around lines 40 - 54, The DB
startup code uses raw ctx for pgxpool.New, migrations.Up and pool.Ping which can
hang; wrap each DB operation in a context with a sensible timeout (e.g.
context.WithTimeout(ctx, <reasonable duration>)) and ensure defer cancel() is
called, then pass the timeoutted context into pgxpool.New,
migrations.Up(cfg.DatabaseURL, cfg.MigrationsDir, ...) and pool.Ping; if any
operation times out or errors, close the pool (use pool.Close()) and return the
error. Ensure symbols referenced are pgxpool.New, migrations.Up, pool.Ping,
runMigrations, cfg.DatabaseURL, cfg.MigrationsDir and pool.Close.

Source: Coding guidelines


41-54: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Wrap errors with context to aid debugging.

The function returns bare errors without context. When startup fails, operators cannot easily identify which step failed. As per coding guidelines, wrap errors with context using fmt.Errorf("...: %w", err).

🔧 Proposed fix to add error context
 	pool, err := pgxpool.New(ctx, cfg.DatabaseURL)
 	if err != nil {
-		return nil, err
+		return nil, fmt.Errorf("failed to create connection pool: %w", err)
 	}
 
 	if runMigrations {
 		if err := migrations.Up(ctx, cfg.DatabaseURL, cfg.MigrationsDir); err != nil {
 			pool.Close()
-			return nil, err
+			return nil, fmt.Errorf("failed to run migrations: %w", err)
 		}
 	}
 
 	if err := pool.Ping(ctx); err != nil {
 		pool.Close()
-		return nil, err
+		return nil, fmt.Errorf("failed to ping database: %w", err)
 	}

Note: You'll need to add "fmt" to the imports.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/platform/bootstrap/bootstrap.go` around lines 41 - 54, Wrap returned
errors with context using fmt.Errorf to indicate which startup step failed: when
migrations.Up(ctx, cfg.DatabaseURL, cfg.MigrationsDir) returns err, replace the
bare return with returning fmt.Errorf("migrations up failed: %w", err) (and
still close pool before returning); when pool.Ping(ctx) returns err, return
fmt.Errorf("database ping failed: %w", err); also add fmt to the imports. Ensure
all returns that previously returned err directly now wrap the error with a
descriptive message referencing the failing operation (e.g., "migrations up
failed" and "database ping failed").

Source: Coding guidelines

@arxdsilva
arxdsilva merged commit ff76824 into arxdsilva:main Jun 8, 2026
2 checks passed
This was referenced Jun 16, 2026
@coderabbitai coderabbitai Bot mentioned this pull request Jun 24, 2026
@coderabbitai coderabbitai Bot mentioned this pull request Jul 2, 2026
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.

3 participants