Skip to content

Conversation

@josefinalliende
Copy link
Contributor

@josefinalliende josefinalliende commented Aug 19, 2025

Description

In #464 I added a script to check diff coverage. This script checked the coverage of changed files that followed a pattern name (starting only for providers).

🐛 CI was failing in master due to new step that checked diff coverage.

🤔 This error helped me realize that there were multiple errors in this check and that it was only working OK when a provider file was changed. These are my conclusions

  • It doesn't make sense to run it in master, just makes sense to run it in PRs cause in master diff will always be empty,
  • The script wasn't working properly when no files changed matched the pattern (a provider pattern or provider test)
  • The script wasn't working as expected when only tests files were modified (you could have deleted a provider test file and coverage check wasn't warning)

💡 So this PR:

  • Adds a condition in CI steps related to coverage, so that they are only run on pull requests, not in pushes to master
  • Fixed checK-diff_coverage script to work without changes in provider files, with changes just in providers tests and removal of providers tests

Case 1: No files changed match pattern

Change Result
Screenshot 2025-08-19 at 11 35 48 AM no-match

Case 2: Provider test is removed

Change Result
Screenshot 2025-08-19 at 11 32 06 AM Screenshot 2025-08-19 at 1 24 05 PM

Case 3: Provider test without min coverage is modified

Change Result
test-change test-change-result

Case 4: Provider test with min coverage is modified

Change Result
change Screenshot 2025-08-19 at 1 37 23 PM

Case 5: Provider without min coverage is modified

Change Result
change result

Case 6: Provider with min coverage is modified

Change Result
change result

Type of Change

  • 🛠️ Bug fix : fixes check diff coverage script

Checklist

  • Run just precommit to ensure that formatting and linting are correct
  • Run just check-flutter-coverage to ensure that flutter coverage rules are passing
  • Updated the CHANGELOG.md file with your changes (if they affect the user experience)

Summary by CodeRabbit

  • New Features
    • Smarter diff coverage: links changed tests to their corresponding source files, improving accuracy.
  • Tests
    • Coverage runs automatically on pull requests with clearer reporting and early exit when no relevant Dart changes.
  • Chores
    • CI now separates push vs pull request behavior: standard tests on pushes; coverage steps on pull requests.
    • Installs coverage tools only for pull requests to speed up other runs.
    • Adds prerequisite checks and improved messaging for easier troubleshooting.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 19, 2025

Walkthrough

The CI workflow splits test execution: standard tests on push, coverage on pull_request. The diff-coverage script is refactored to compute files to check from both lib changes and mapped tests, adds prerequisites and coverage file checks, updates logging, and replaces old change-detection logic.

Changes

Cohort / File(s) Summary
CI workflow gating
.github/workflows/ci.yml
Split test steps by event: push runs flutter tests; pull_request runs flutter tests with coverage, installs lcov, and checks coverage. Prior unconditional steps now gated via if: github.event_name filters.
Diff coverage script refactor
scripts/check_diff_coverage.sh
Introduced helpers (debug_print, prerequisites/coverage checks, file mapping and combination). Replaced get_changed_files with get_files_to_check that merges lib changes and lib-from-test mappings. Updated calculate_coverage and check_diff_coverage, adjusted messaging to stderr, and added early exits.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Dev as Developer
  participant GH as GitHub Actions
  participant Job as CI Job

  Dev->>GH: Push
  GH->>Job: Trigger workflow (event=push)
  Job->>Job: Run Flutter tests
  Note over Job: No coverage steps on push

  Dev->>GH: Open/Update PR
  GH->>Job: Trigger workflow (event=pull_request)
  Job->>Job: Run Flutter tests with --coverage
  Job->>Job: Install lcov
  Job->>Job: Check coverage (lcov/info)
Loading
sequenceDiagram
  autonumber
  participant Script as check_diff_coverage.sh
  participant Git as git
  participant Lcov as lcov

  Script->>Script: check_prerequisites()
  Script->>Script: check_coverage_file_presence()
  Script->>Git: Determine merge base
  Script->>Script: get_files_to_check(merge_base, pattern)
  Note over Script: Split changes: lib/*.dart and test/*.dart
  Script->>Script: Map tests -> lib files
  Script->>Script: Combine & de-duplicate file set
  alt No files to check
    Script-->>Script: Exit success early
  else Files to check
    Script->>Lcov: --extract lcov.info for files_to_check
    Script-->>Script: calculate_coverage()
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

I thump my paws at CI’s new divide,
Push runs swift, while PRs count coverage with pride.
I nibble logs where mappings now align,
Tests to libs—carrots in a tidy line.
With lcov flakes like snow in night’s cool air,
Our burrow builds with careful, rabbit care. 🥕

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/check-diff-coverage

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@josefinalliende josefinalliende force-pushed the fix/check-diff-coverage branch from ac51db9 to c5abe67 Compare August 19, 2025 10:26
@josefinalliende josefinalliende marked this pull request as ready for review August 19, 2025 10:41
Copy link
Contributor

@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: 3

🧹 Nitpick comments (6)
scripts/check_diff_coverage.sh (4)

123-129: Scope locals to avoid leakage; also keep grep fallback robust.

lib_diff_files, test_diff_files, and lib_files_from_test_diff_files are currently global in this function. Scope them as local to avoid side effects.

Apply this diff:

-    local diff_files
+    local diff_files
     diff_files=$(
-        git diff --name-only "$merge_base" HEAD | grep "${file_pattern}"
+        git diff --name-only "$merge_base" HEAD | grep "${file_pattern}" || true
     )
-    lib_diff_files=$(echo "$diff_files" | grep '^lib/.*\.dart$' || true)
-    test_diff_files=$(echo "$diff_files" | grep '^test/.*\.dart$' || true)
-    lib_files_from_test_diff_files=$(get_lib_files_from_test_files "$test_diff_files")
-    local files_to_check
+    local lib_diff_files test_diff_files lib_files_from_test_diff_files
+    lib_diff_files=$(echo "$diff_files" | grep '^lib/.*\.dart$' || true)
+    test_diff_files=$(echo "$diff_files" | grep '^test/.*\.dart$' || true)
+    lib_files_from_test_diff_files=$(get_lib_files_from_test_files "$test_diff_files")
+    local files_to_check

148-151: Guard against non-existent files before lcov extract.

If the mapped lib file from a test doesn’t exist, lcov --extract may complain. Filter to existing files.

Apply this diff:

-    while IFS= read -r file; do
-        files_array+=("$file")
-    done <<< "$files_to_check"
+    while IFS= read -r file; do
+        [[ -f "$file" ]] && files_array+=("$file")
+    done <<< "$files_to_check"

131-135: Avoid exiting from utility function; let the caller decide.

get_files_to_check currently exits the whole script when empty. This makes the helper impure and duplicates exit handling in the caller. Prefer returning empty and keeping the early-exit in check_diff_coverage.

Apply this diff:

-    if [ -z "$files_to_check" ]; then
-       print_success "No lib/ or test/ Dart files matching '${file_pattern}' changed. Skipping coverage check."
-       exit 0
-    fi
+    if [ -z "$files_to_check" ]; then
+       print_success "No lib/ or test/ Dart files matching '${file_pattern}' changed. Skipping coverage check."
+    fi

The caller already handles the empty case (Lines 243–251).


8-10: Unused debug_print helper.

debug_print is defined but not used. Either wire it into key branches (e.g., before/after git operations) or remove it to reduce noise.

If you intend to keep it, consider a VERBOSE flag to toggle debug verbosity.

.github/workflows/ci.yml (2)

78-78: Trim trailing whitespace to satisfy linters.

YAMLlint flags trailing spaces on Line 78.

Apply this diff:

-      
+

79-82: Make apt-get more reliable on GitHub runners.

Add update and auto-confirm to avoid intermittent failures.

Apply this diff:

-    - name: Install lcov
+    - name: Install lcov
       if: github.event_name == 'pull_request'
-      run: sudo apt-get install lcov
+      run: sudo apt-get update && sudo apt-get install -y lcov
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 92d12fd and c5abe67.

📒 Files selected for processing (2)
  • .github/workflows/ci.yml (1 hunks)
  • scripts/check_diff_coverage.sh (3 hunks)
🧰 Additional context used
🪛 YAMLlint (1.37.1)
.github/workflows/ci.yml

[error] 78-78: trailing spaces

(trailing-spaces)

🪛 Shellcheck (0.10.0)
scripts/check_diff_coverage.sh

[warning] 247-247: Use single quotes, otherwise this expands now rather than when signalled.

(SC2064)

🔇 Additional comments (2)
scripts/check_diff_coverage.sh (1)

236-251: Happy path looks solid after bug fixes.

Once the early grep failure and trap quoting are fixed, the flow (preflight → fetch → merge-base → file set → lcov extract → threshold check) is coherent and robust. Nice job handling “no relevant diffs” and mapping test-only changes to lib targets.

.github/workflows/ci.yml (1)

72-77: Good gating: coverage only on PRs, plain tests on pushes.

This addresses the original failure mode on master and keeps coverage checks scoped to diffs in PRs.

Also applies to: 80-85

Comment on lines +74 to +82
get_lib_file_from_test_file() {
local test_file
test_file=$1
local lib_file
lib_file=${test_file/test\//lib\/}
lib_file=${lib_file%_test.dart}
lib_file=${lib_file}.dart
echo "$lib_file"
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Bug: Incorrect test→lib path mapping due to escaped slashes.

Using backslashes in parameter expansion results in literal backslashes and the substitution doesn’t occur, producing paths like test/... instead of lib/... . This breaks mapping for test-only changes and deletions.

Apply this diff:

 get_lib_file_from_test_file() {
     local test_file
     test_file=$1
     local lib_file
-    lib_file=${test_file/test\//lib\/}
-    lib_file=${lib_file%_test.dart}
-    lib_file=${lib_file}.dart
+    # Map "test/…_test.dart" -> "lib/….dart"
+    lib_file="${test_file/#test\//lib/}"
+    lib_file="${lib_file%_test.dart}.dart"
     echo "$lib_file"
 }

Optional hardening (if your tests aren’t always 1:1 with lib files): validate the file exists before including it downstream. I’ve proposed a guard below in calculate_coverage.

📝 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
get_lib_file_from_test_file() {
local test_file
test_file=$1
local lib_file
lib_file=${test_file/test\//lib\/}
lib_file=${lib_file%_test.dart}
lib_file=${lib_file}.dart
echo "$lib_file"
}
get_lib_file_from_test_file() {
local test_file
test_file=$1
local lib_file
# Map "test/…_test.dart" -> "lib/….dart"
lib_file="${test_file/#test\//lib/}"
lib_file="${lib_file%_test.dart}.dart"
echo "$lib_file"
}
🤖 Prompt for AI Agents
In scripts/check_diff_coverage.sh around lines 74 to 82, the test→lib path
mapping uses escaped slashes in the parameter expansion which leaves literal
backslashes and prevents substitution (producing paths like test/... instead of
lib/...), so change the substitution to use unescaped slashes (e.g.
lib_file=${test_file/test//lib/} or better lib_file=${test_file#test/};
lib_file=lib/${lib_file%_test.dart}.dart) so the replacement actually converts
the test path to the lib path; optionally add a guard after computing lib_file
to check [ -f "$lib_file" ] and skip or warn if the target file does not exist
before including it downstream.

Comment on lines +124 to 134
diff_files=$(git diff --name-only "$merge_base" HEAD | grep "${file_pattern}")
lib_diff_files=$(echo "$diff_files" | grep '^lib/.*\.dart$' || true)
test_diff_files=$(echo "$diff_files" | grep '^test/.*\.dart$' || true)
lib_files_from_test_diff_files=$(get_lib_files_from_test_files "$test_diff_files")
local files_to_check
files_to_check=$(combine_changed_files "$lib_diff_files" "$lib_files_from_test_diff_files")

if [ -z "$files_to_check" ]; then
print_success "No lib/ or test/ Dart files matching '${file_pattern}' changed. Skipping coverage check."
exit 0
fi
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix: grep will exit non-zero under set -e when no matches (breaking the “no diffs” path).

With set -euo pipefail, grep returning 1 aborts the script before your empty-set handling. Add a fallback to avoid premature exit.

Apply this diff:

-    diff_files=$(git diff --name-only "$merge_base" HEAD | grep "${file_pattern}")
+    diff_files=$(git diff --name-only "$merge_base" HEAD | grep "${file_pattern}" || true)
📝 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
diff_files=$(git diff --name-only "$merge_base" HEAD | grep "${file_pattern}")
lib_diff_files=$(echo "$diff_files" | grep '^lib/.*\.dart$' || true)
test_diff_files=$(echo "$diff_files" | grep '^test/.*\.dart$' || true)
lib_files_from_test_diff_files=$(get_lib_files_from_test_files "$test_diff_files")
local files_to_check
files_to_check=$(combine_changed_files "$lib_diff_files" "$lib_files_from_test_diff_files")
if [ -z "$files_to_check" ]; then
print_success "No lib/ or test/ Dart files matching '${file_pattern}' changed. Skipping coverage check."
exit 0
fi
diff_files=$(git diff --name-only "$merge_base" HEAD | grep "${file_pattern}" || true)
lib_diff_files=$(echo "$diff_files" | grep '^lib/.*\.dart$' || true)
test_diff_files=$(echo "$diff_files" | grep '^test/.*\.dart$' || true)
lib_files_from_test_diff_files=$(get_lib_files_from_test_files "$test_diff_files")
local files_to_check
files_to_check=$(combine_changed_files "$lib_diff_files" "$lib_files_from_test_diff_files")
if [ -z "$files_to_check" ]; then
print_success "No lib/ or test/ Dart files matching '${file_pattern}' changed. Skipping coverage check."
exit 0
fi
🤖 Prompt for AI Agents
In scripts/check_diff_coverage.sh around lines 124 to 134, the pipeline
assigning diff_files uses git diff | grep "${file_pattern}" which will cause
grep to return exit status 1 under set -e when there are no matches and abort
the script; update that assignment to tolerate no matches by adding a fallback
(e.g., append "|| true" to the grep pipeline) so diff_files becomes empty
instead of causing the script to exit, keeping the subsequent empty-set handling
intact.

exit 0
else
temp_file=$(make_temp_file)
trap "rm -f $temp_file" EXIT
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

ShellCheck SC2064: Quote trap handler to avoid early expansion.

The trap string expands $temp_file immediately. Use single quotes and quote the variable inside the handler.

Apply this diff:

-        trap "rm -f $temp_file" EXIT
+        trap 'rm -f "$temp_file"' EXIT
📝 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
trap "rm -f $temp_file" EXIT
trap 'rm -f "$temp_file"' EXIT
🧰 Tools
🪛 Shellcheck (0.10.0)

[warning] 247-247: Use single quotes, otherwise this expands now rather than when signalled.

(SC2064)

🤖 Prompt for AI Agents
In scripts/check_diff_coverage.sh around line 247 the trap handler currently
uses double quotes causing $temp_file to expand immediately; change it to use
single quotes and quote the variable inside the handler so the expansion happens
at trap execution (e.g. trap 'rm -f "$temp_file"' EXIT) to avoid early expansion
per ShellCheck SC2064.

@josefinalliende
Copy link
Contributor Author

I'm addressing code rabbit's comments but in a separate PR, so that I'm no longer blocking other open PRs because of this

@josefinalliende
Copy link
Contributor Author

josefinalliende commented Aug 19, 2025

Unless of course if you think that some of those comments should block the merge

@josefinalliende josefinalliende merged commit 9620d81 into master Aug 19, 2025
2 checks passed
@josefinalliende josefinalliende deleted the fix/check-diff-coverage branch August 19, 2025 12:26
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.

Coverage diff step fails when there is no diff relevant for coverage

3 participants