Skip to content

GSOC-Week1-Module_A#920

Open
ParthAggarwal16 wants to merge 14 commits into
OWASP:mainfrom
ParthAggarwal16:week_1-2-harvester-validation-and-docs
Open

GSOC-Week1-Module_A#920
ParthAggarwal16 wants to merge 14 commits into
OWASP:mainfrom
ParthAggarwal16:week_1-2-harvester-validation-and-docs

Conversation

@ParthAggarwal16

Copy link
Copy Markdown
Contributor

Summary

This PR adds the initial repository configuration loading and validation layer for the harvester pipeline.

Added

  • YAML-based repository configuration loading
  • Pydantic schema validation for repository configs
  • Semantic repository validation layer
  • Validation fixtures and pytest coverage
  • Sample harvester repository configuration
  • Repository validation utilities and exports
  • Exclude pattern support scaffold

Validation Coverage

Config Loader Validation

  • Missing repository ID
  • Invalid chunk size
  • Invalid YAML syntax
  • Missing config file
  • Empty owner validation
  • Invalid chunking strategy
  • Invalid polling mode

Repository Semantic Validation

  • Duplicate repository IDs
  • Duplicate repositories
  • Duplicate include paths

Test Plan

Executed:

bash python3 -m pytest application/tests/harvester_test -v python3 -m coverage report python3 -m black application/utils/harvester application/tests/harvester_test

All tests passing.

Notes for Reviewers

  • Validation is intentionally split into:

    • schema validation (config_loader.py)
    • semantic/business-rule validation (repos_validator.py)
  • Repository uniqueness checks are case-insensitive.

  • exclude_patterns.txt is currently scaffolded for future integration into harvesting logic.

image

ParthAggarwal16#3 (comment)
this comment has some good coderabbit diagrams if you guys wanna have a look at it

@coderabbitai

coderabbitai Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 16d5ab3b-d9f4-4d1c-b18a-0ab06c21270a

📥 Commits

Reviewing files that changed from the base of the PR and between d4e7731 and f11f869.

📒 Files selected for processing (14)
  • application/tests/harvester_test/config_loader_test.py
  • application/tests/harvester_test/fixtures/duplicate_include_paths.yaml
  • application/tests/harvester_test/fixtures/duplicate_repo_ids.yaml
  • application/tests/harvester_test/fixtures/duplicate_repositories.yaml
  • application/tests/harvester_test/fixtures/empty_include_paths.yaml
  • application/tests/harvester_test/fixtures/empty_owner.yaml
  • application/tests/harvester_test/fixtures/invalid_chunk_size.yaml
  • application/tests/harvester_test/fixtures/invalid_missing_id.yaml
  • application/tests/harvester_test/fixtures/invalid_polling_interval.yaml
  • application/tests/harvester_test/fixtures/invalid_polling_mode.yaml
  • application/tests/harvester_test/fixtures/valid_repos.yaml
  • application/utils/harvester/config_loader.py
  • application/utils/harvester/exclude_patterns.txt
  • application/utils/harvester/schemas.py
✅ Files skipped from review due to trivial changes (7)
  • application/tests/harvester_test/fixtures/invalid_polling_interval.yaml
  • application/tests/harvester_test/fixtures/invalid_chunk_size.yaml
  • application/tests/harvester_test/fixtures/duplicate_include_paths.yaml
  • application/tests/harvester_test/fixtures/valid_repos.yaml
  • application/tests/harvester_test/fixtures/duplicate_repo_ids.yaml
  • application/utils/harvester/exclude_patterns.txt
  • application/tests/harvester_test/fixtures/empty_include_paths.yaml
🚧 Files skipped from review as they are similar to previous changes (5)
  • application/tests/harvester_test/fixtures/duplicate_repositories.yaml
  • application/tests/harvester_test/fixtures/invalid_polling_mode.yaml
  • application/tests/harvester_test/fixtures/invalid_missing_id.yaml
  • application/tests/harvester_test/fixtures/empty_owner.yaml
  • application/tests/harvester_test/config_loader_test.py

Summary by CodeRabbit

  • New Features

    • Added repository harvesting configuration loading with schema validation for chunking, polling, and path rules.
    • Introduced a default repos.yaml plus harvesting exclude patterns.
    • Added semantic validation for duplicate repository IDs, duplicate repositories, and duplicate include globs.
  • Bug Fixes

    • Invalid configurations (malformed YAML, empty include paths, invalid chunk sizes/overlap, and invalid polling settings) now fail fast with clearer error handling.
  • Tests

    • Added unit tests and new YAML fixtures covering valid and negative scenarios (including duplicate and invalid configurations).

Walkthrough

Adds harvester configuration schemas, YAML loading and semantic validation, package exports, repository config examples, ignore patterns, and unit tests with YAML fixtures for valid and invalid repository cases.

Changes

Harvester Configuration System

Layer / File(s) Summary
Schema and data contracts
application/utils/harvester/schemas.py
Adds Pydantic models for path rules, chunking, polling, repository entries, and the root repositories file.
Configuration loading and error handling
application/utils/harvester/config_loader.py, application/tests/harvester_test/config_loader_test.py
Adds YAML loading with schema validation and error mapping, plus tests for valid loading, malformed input, invalid values, and missing files.
Semantic duplicate and constraint validation
application/utils/harvester/repos_validator.py, application/tests/harvester_test/repos_validator_test.py
Adds duplicate repository and include-path validation, plus tests for duplicate and valid configurations.
Public API package exports
application/utils/harvester/__init__.py
Re-exports schema, loading, and validation symbols through an explicit __all__ list.
Example configurations and patterns
application/utils/harvester/repos.yaml, application/utils/harvester/exclude_patterns.txt
Adds repository harvesting configuration and ignore patterns for excluded paths and file types.
Test fixture configurations
application/tests/harvester_test/__init__.py, application/tests/harvester_test/fixtures/*.yaml
Adds YAML fixtures for valid, invalid, duplicate, and malformed repository configurations plus a test package docstring.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested reviewers: Pa04rth

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is too vague to describe the main change and does not convey the harvester validation work. Use a concise title that mentions the added harvester configuration loading and validation layer.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description clearly matches the added harvester configuration loading, validation, fixtures, and tests.
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.
✨ 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.

@ParthAggarwal16

Copy link
Copy Markdown
Contributor Author

ParthAggarwal16#3 (comment)
also this one has the entire HLA for more context

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🧹 Nitpick comments (2)
application/tests/harvester_test/test_config_loader.py (1)

43-45: ⚡ Quick win

Use Path object for consistency.

Line 45 passes a string literal while all other tests use Path objects from FIXTURES_DIR. For consistency and clarity, consider using FIXTURES_DIR / "does_not_exist.yaml" or another Path-based approach.

♻️ Proposed fix for consistency
 def test_missing_config_file():
-    with pytest.raises(FileNotFoundError):
-        load_repo_config("does_not_exist.yaml")
+    config_path = FIXTURES_DIR / "does_not_exist.yaml"
+    with pytest.raises(FileNotFoundError):
+        load_repo_config(config_path)
🤖 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 `@application/tests/harvester_test/test_config_loader.py` around lines 43 - 45,
Replace the string literal path in test_missing_config_file with a Path-based
fixture to match the rest of the tests: call load_repo_config with FIXTURES_DIR
/ "does_not_exist.yaml" instead of "does_not_exist.yaml" so the test uses a Path
object (refer to test_missing_config_file, load_repo_config and FIXTURES_DIR).
application/tests/harvester_test/test_repos_validator.py (1)

14-45: ⚡ Quick win

Consider testing case-insensitive duplicate detection.

The validator uses casefold() for case-insensitive comparison (per the relevant code snippet), but there's no test verifying that repository IDs like "ASVS" and "asvs" are correctly identified as duplicates. Adding such a test would verify this important edge case.

🔤 Proposed case-insensitive duplicate test

Create a fixture duplicate_repo_ids_case_insensitive.yaml:

repositories:
  - id: ASVS
    type: github
    owner: OWASP
    repo: ASVS
    paths:
      include:
        - "**/*.md"
    chunking:
      strategy: markdown
      max_tokens: 1200
    polling:
      mode: incremental
      interval_minutes: 60

  - id: asvs
    type: github
    owner: OWASP
    repo: CheatSheetSeries
    paths:
      include:
        - "**/*.md"
    chunking:
      strategy: markdown
      max_tokens: 1200
    polling:
      mode: incremental
      interval_minutes: 60

Then add the test:

def test_duplicate_repository_ids_case_insensitive():
    config_path = FIXTURES_DIR / "duplicate_repo_ids_case_insensitive.yaml"
    config = load_repo_config(config_path)
    
    with pytest.raises(
        RepositoryValidationError,
        match="Duplicate repository id",
    ):
        validate_repositories(config)
🤖 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 `@application/tests/harvester_test/test_repos_validator.py` around lines 14 -
45, Add a case-insensitive duplicate-id test: create the fixture
duplicate_repo_ids_case_insensitive.yaml with two repositories whose ids differ
only by case (e.g., "ASVS" and "asvs"), then add a test function
test_duplicate_repository_ids_case_insensitive() that loads the fixture via
load_repo_config and asserts validate_repositories(config) raises
RepositoryValidationError with a "Duplicate repository id" match; this ensures
the validate_repositories code path that uses casefold() is exercised.
🤖 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 `@application/tests/harvester_test/test_repos_validator.py`:
- Around line 14-45: Add a new success-case test to
application/tests/harvester_test/test_repos_validator.py that ensures
validate_repositories(config) does not raise for a known-good config: create a
test function (e.g., test_validate_valid_repositories) that loads FIXTURES_DIR /
"valid_repos.yaml" via load_repo_config and calls validate_repositories(config)
(no exception assertion needed); reference existing helpers load_repo_config and
the function validate_repositories so the test mirrors the failure tests' style.

In `@application/utils/harvester/__init__.py`:
- Around line 17-27: The __all__ export list is unsorted; reorder the entries
alphabetically so it meets linting standards by sorting the names:
ChunkingConfig, ConfigLoaderError, PathRules, PollingConfig, RepositoryConfig,
RepositoriesValidationError (note actual names below), ReposFile,
load_repo_config, RepositoryValidationError, validate_repositories —
specifically sort the existing symbols ("ChunkingConfig", "ConfigLoaderError",
"PathRules", "PollingConfig", "RepositoryConfig", "ReposFile",
"load_repo_config", "RepositoryValidationError", "validate_repositories") into
ascending alphabetical order and replace the current __all__ definition with
that sorted list.

---

Nitpick comments:
In `@application/tests/harvester_test/test_config_loader.py`:
- Around line 43-45: Replace the string literal path in test_missing_config_file
with a Path-based fixture to match the rest of the tests: call load_repo_config
with FIXTURES_DIR / "does_not_exist.yaml" instead of "does_not_exist.yaml" so
the test uses a Path object (refer to test_missing_config_file, load_repo_config
and FIXTURES_DIR).

In `@application/tests/harvester_test/test_repos_validator.py`:
- Around line 14-45: Add a case-insensitive duplicate-id test: create the
fixture duplicate_repo_ids_case_insensitive.yaml with two repositories whose ids
differ only by case (e.g., "ASVS" and "asvs"), then add a test function
test_duplicate_repository_ids_case_insensitive() that loads the fixture via
load_repo_config and asserts validate_repositories(config) raises
RepositoryValidationError with a "Duplicate repository id" match; this ensures
the validate_repositories code path that uses casefold() is exercised.
🪄 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: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 9f37ad90-960e-469e-bfbe-c6dda95e7b54

📥 Commits

Reviewing files that changed from the base of the PR and between e93ce92 and c7ecbf0.

📒 Files selected for processing (21)
  • application/tests/harvester_test/__init__.py
  • application/tests/harvester_test/fixtures/duplicate_include_paths.yaml
  • application/tests/harvester_test/fixtures/duplicate_repo_ids.yaml
  • application/tests/harvester_test/fixtures/duplicate_repositories.yaml
  • application/tests/harvester_test/fixtures/empty_include_paths.yaml
  • application/tests/harvester_test/fixtures/empty_owner.yaml
  • application/tests/harvester_test/fixtures/invalid_chunk_size.yaml
  • application/tests/harvester_test/fixtures/invalid_chunking_strategy.yaml
  • application/tests/harvester_test/fixtures/invalid_missing_id.yaml
  • application/tests/harvester_test/fixtures/invalid_polling_interval.yaml
  • application/tests/harvester_test/fixtures/invalid_polling_mode.yaml
  • application/tests/harvester_test/fixtures/invalid_yaml.yaml
  • application/tests/harvester_test/fixtures/valid_repos.yaml
  • application/tests/harvester_test/test_config_loader.py
  • application/tests/harvester_test/test_repos_validator.py
  • application/utils/harvester/__init__.py
  • application/utils/harvester/config_loader.py
  • application/utils/harvester/exclude_patterns.txt
  • application/utils/harvester/repos.yaml
  • application/utils/harvester/repos_validator.py
  • application/utils/harvester/schemas.py

Comment thread application/tests/harvester_test/test_repos_validator.py Outdated
Comment thread application/utils/harvester/__init__.py
@ParthAggarwal16

Copy link
Copy Markdown
Contributor Author

@coderabbitai
0be6df8
this commit should address it

@coderabbitai

coderabbitai Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
gh api repos/OWASP/OpenCRE/commits/0be6df87c7642908c76dc915c48b54c30227acff --jq '.commit.message + "\n---\n" + (.files // [] | map("  " + .filename + " [+" + (.additions|tostring) + "/-" + (.deletions|tostring) + "]\n  patch: " + (.patch // "")) | join("\n"))'

Length of output: 1054



@ParthAggarwal16 Confirmed — commit 0be6df8 addresses both concerns:

  1. Missing happy-path test: test_validate_valid_repositories() now covers the success case for validate_repositories(), loading valid_repos.yaml and asserting no exception is raised.
  2. __all__ ordering: RepositoryValidationError is now in correct alphabetical position in application/utils/harvester/__init__.py.

Both look good. Thanks for the fix!

(^‿^)🐇


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

@northdpole northdpole left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Great job on the W1 config layer — the schema vs semantic validation split (config_loader.py / repos_validator.py) is clean, the Pydantic models are well-structured, and the fixture matrix covers the important failure modes. This is ready to merge once the items below are addressed to match repo conventions.

Requested changes

1. Make tests discoverable by make test (blocker)

CI runs:

python -m unittest discover -s application/tests -p "*_test.py"

Your tests are named test_config_loader.py / test_repos_validator.py and use pytest — they never run in CI today.

Fix:

  • Rename to config_loader_test.py and repos_validator_test.py (under application/tests/harvester_test/).
  • Convert to unittest (mirror application/tests/noise_filter/config_loader_test.py): unittest.TestCase classes, self.assertRaises / self.assertEqual, no pytest.raises.
  • Run locally: make test and confirm both modules are executed (not just flask routes).

2. Cover the remaining fixtures

You already have fixtures without tests:

  • invalid_polling_interval.yaml (interval_minutes: 0) — add a test expecting ConfigLoaderError (Pydantic gt=0 on interval_minutes).
  • empty_include_paths.yaml (include: []) — add a test expecting ConfigLoaderError (min_length=1 on paths.include).

3. Rebase onto main

The branch is ~33 commits behind main. Please rebase and push so CI runs fresh on current main.

Note for upcoming weeks (not blocking W1)

Module B’s ChangeRecord contract (merged in #913) expects:

  • source.repo as a combined slug, e.g. "OWASP/ASVS" (not separate owner + repo fields in the emitted record).
  • Chunk sizing in characters (max_chars, default 4000 in the labeled-dataset builder), while this config uses max_tokens.

Fine for W1 config-only work — please align chunking units and emission shape in A-W3 so harvest output matches the B contract without a surprise refactor.

Production

No concerns — this is additive and nothing is wired into web/worker/import yet.

Ping when the test/convention fixes are in and rebased; happy to approve and merge then.

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (1)
application/tests/harvester_test/config_loader_test.py (1)

12-59: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing tests for "empty owner", "invalid chunking strategy", "invalid polling mode" fixtures.

The PR description explicitly lists "Empty owner validation," "Invalid chunking strategy," and "Invalid polling mode" as covered validation cases, and corresponding fixtures (empty_owner.yaml, invalid_chunking_strategy.yaml, invalid_polling_mode.yaml) exist in the fixtures directory, but no test methods in this file exercise them. This leaves those fixtures unused and the claimed coverage unverified.

✅ Suggested additions
     def test_empty_include_paths(self):
         config_path = FIXTURES_DIR / "empty_include_paths.yaml"

         with self.assertRaises(ConfigLoaderError):
             load_repo_config(config_path)

+    def test_empty_owner(self):
+        config_path = FIXTURES_DIR / "empty_owner.yaml"
+
+        with self.assertRaises(ConfigLoaderError):
+            load_repo_config(config_path)
+
+    def test_invalid_chunking_strategy(self):
+        config_path = FIXTURES_DIR / "invalid_chunking_strategy.yaml"
+
+        with self.assertRaises(ConfigLoaderError):
+            load_repo_config(config_path)
+
+    def test_invalid_polling_mode(self):
+        config_path = FIXTURES_DIR / "invalid_polling_mode.yaml"
+
+        with self.assertRaises(ConfigLoaderError):
+            load_repo_config(config_path)
+
🤖 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 `@application/tests/harvester_test/config_loader_test.py` around lines 12 - 59,
Add missing coverage in ConfigLoaderTests for the unused fixtures
empty_owner.yaml, invalid_chunking_strategy.yaml, and invalid_polling_mode.yaml
by creating focused test methods that call load_repo_config and assert
ConfigLoaderError is raised. Use the existing test pattern from
test_missing_repository_id, test_invalid_chunk_size, and
test_invalid_polling_interval so the new cases are consistent and the validation
paths in load_repo_config are exercised.
🤖 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.

Nitpick comments:
In `@application/tests/harvester_test/config_loader_test.py`:
- Around line 12-59: Add missing coverage in ConfigLoaderTests for the unused
fixtures empty_owner.yaml, invalid_chunking_strategy.yaml, and
invalid_polling_mode.yaml by creating focused test methods that call
load_repo_config and assert ConfigLoaderError is raised. Use the existing test
pattern from test_missing_repository_id, test_invalid_chunk_size, and
test_invalid_polling_interval so the new cases are consistent and the validation
paths in load_repo_config are exercised.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 528a6b53-0a7f-464e-b990-c3f189002cc1

📥 Commits

Reviewing files that changed from the base of the PR and between 0be6df8 and c728fed.

📒 Files selected for processing (2)
  • application/tests/harvester_test/config_loader_test.py
  • application/tests/harvester_test/repos_validator_test.py

@ParthAggarwal16

Copy link
Copy Markdown
Contributor Author

yo @northdpole , sorry it took a bit longer than enxpected, but i think it should be good to go now, let me know if anything else is neccesery or i missed
image

Comment thread application/utils/harvester/exclude_patterns.txt
@ParthAggarwal16

Copy link
Copy Markdown
Contributor Author

yeah mb, forgot about that one, should be done now

Comment thread application/utils/harvester/config_loader.py Outdated
Comment thread application/utils/harvester/exclude_patterns.txt
Comment thread application/utils/harvester/schemas.py Outdated
Comment thread application/utils/harvester/schemas.py Outdated
@ParthAggarwal16

Copy link
Copy Markdown
Contributor Author

f11f869

@Pa04rth this one should address all the concerns

@Pa04rth

Pa04rth commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

@ParthAggarwal16 Good work , let @northdpole approve the PR , then we can merge

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