ci: add CodeCov integration for code coverage reporting - #20
Conversation
Adding impelmentation of leader election for Azure Blob Storage, Consul, FileSystem, InMemory, PostgreSQL, Redis, SqlServer and ZooKeeper. Adding tests. Adding Github Action for build and running tests. Adding MinVer versioning. Adding .eidtorconfig file, .gitattributes and .gitignore. Fixes #1
…s workflow Replace docker-compose with docker compose in Github Actions workflow since Github Action runners no longer have the docker-compose command installed by default. Fixes #1
Adding health checks in docker-compose.yml file, renaming container names, added timeouts for running tests in the Github Action workflow Fixes #1
Ensure the directorypath exists in the tests, and create it if it does not exist Fixes #1
Resolving possible race condition in the FileSystem provider, consecutive await using statements could cause disposal problems and could cause hangs Fixes #1
…topAsync is called before disposal IHost instance is not being properly disposed when StopAsync is called before disposal, leaving background services running and causing tests to hang. Changed the entire approach in the IsZooKeeperAvailableAsync() method to create an instance of the ZooKeeperLeaderElectionProvider class and calling the health check method to check whether ZooKeeper is available. Fixes #1
…ed when StopAsync is called before disposal Similar to the issue for ZooKeeper. IHost instance is not being properly disposed when StopAsync is called before disposal, leaving background services running and causing tests to hang. Changed the entire approach in the IsPostgreSqlAvailableAsync() and IsSqlServerAvailableAsync() methods to create an instance of the LeaderElextion provider classes and calling the health check method to check whether PostgreSQL and SqlServer are available. Fixes #1
…nto the tests Changed a GetAwaiter().GetResult() call that had snuck into the tests, and created a version of the WaitForConditionAsync method which takes a Func<Task<bool>> instead of just Func<bool> to properly handle async conditions without blocking. Removed properties not used in Is*AvailableAsync() methods Fixes #1
Correct Github Action workflow permissions: - added contents:read for the workflow to read repository contents - added checks:write for the workflow to create check runs (required by dorny/test-reporter) - added pull-requests:write for the workflow to comment on pull requests with test results Fixes #1
Collections were still being modified by background tasks(s) when test assertions were enumerating the collection, causing trouble. A total of four tests were fixed. Fixes #3
…fied Even after awaiting eventTask the collection could still be modified, correcting this by taking a thread-safe snapshot of the collection before making assertions Fixes #3
Apply thread-safe snapshot pattern to all tests that access the shared events collection to prevent "Collection was modified; enumeration operation may not execute" errors in Github Actions. Changes: - Take array snapshot of events collection while holding lock before making assertions in 6 tests: Where_ShouldFilterEvents, Take_ShouldLimitNumberOfEvents, Skip_ShouldSkipEvents, DistinctUntilChanged_ShouldFilterConsecutiveDuplicates, Throttle_ShouldLimitEventRate, and Debounce_ShouldDelayEvents - Reorder cleanup and assertions to ensure background tasks complete before accessing the collection - Use .Length property instead of .Count for array assertions - Add explanatory comments for exception handling during cleanup This ensures complete thread-safety by creating immutable snapshots of the collection while holding the lock, eliminating any possibility of race conditions during enumeration. All 16 tests now pass reliably in both local and GitHub Actions environments. Fixes #3
Implemented IAsyncDisposable to prevent ObjectDisposedException when timer callbacks execute during disposal. Added active callback tracking with atomic operations and wait mechanism to ensure safe shutdown. Includes 8 new tests covering concurrent disposal scenarios.
Add centralized parameter validation to prevent invalid inputs across all provider implementations and service extensions. Changes: - Created ParameterValidation helper class with validation methods for election groups, participant IDs, metadata, and lock timeouts - Added validation to all 8 provider implementations (PostgreSQL, SQL Server, Redis, FileSystem, InMemory, Consul, ZooKeeper, Azure Blob Storage) - Added null checks to LeaderElectionServiceExtensions methods - Updated ILeaderElectionProvider XML documentation with validation requirements and exception details - Added 108 comprehensive validation tests covering all scenarios Validation enforces: - Non-null, non-empty, non-whitespace identifiers - Alphanumeric characters, underscores, hyphens, and periods only - Maximum length limits (255 chars for identifiers, 4000 for metadata values) - Positive lock timeouts not exceeding 1 day - Metadata entry limits (max 100 entries)
Improve disposal patterns across all provider implementations to ensure consistent, safe, and non-blocking resource cleanup. Changes: - Implemented IAsyncDisposable for Consul and ZooKeeper providers to properly handle async cleanup operations without blocking threads - Standardized disposal pattern across all 8 providers to use early return pattern for consistency - Added 11 comprehensive disposal tests covering basic disposal, double disposal safety, and ObjectDisposedException after disposal - Added detailed XML documentation for DisposeAsync() and Dispose() methods in providers with async cleanup Providers modified: - ConsulLeaderElectionProvider: Added IAsyncDisposable, replaced blocking .Wait() with proper async disposal of Consul sessions - ZooKeeperLeaderElectionProvider: Added IAsyncDisposable, replaced blocking .Wait() with proper async disposal of ZooKeeper connection - SqlServerLeaderElectionProvider: Standardized disposal pattern - RedisLeaderElectionProvider: Standardized disposal pattern Test coverage: - All providers now have disposal tests ensuring idempotent disposal - All providers verify methods throw ObjectDisposedException after disposal - Async-disposable providers have dedicated DisposeAsync() tests - Total: 217 tests
…y descriptions Add comprehensive concurrent scenario tests validating thread-safety and race condition handling across multiple participants. - Add ConcurrentScenarioTests.cs with tests for: - Multiple participants competing for leadership - Rapid acquire/release cycles - Concurrent heartbeat updates - Leader failover scenarios - Update README.md: - Rename all "LeaderElection.Net" references to "MultiLock" - Add "Concurrency and Thread-Safety" documentation section - Update package names, namespaces, and project paths - Enhance disposal patterns in provider tests
…Drafter Implement comprehensive CI/CD infrastructure for automated NuGet package publishing and release management to prepare MultiLock for production deployment. ### NuGet Publishing Workflow - Add automated NuGet publishing workflow with manual and tag-based triggers - Configure package validation using dotnet-validate tool - Implement selective publishing to exclude core MultiLock package (embedded in providers) - Add dry-run mode for testing without actual publication - Include symbol package (.snupkg) publishing for debugging support - Integrate with Release Drafter for automatic changelog updates ### Package Configuration & Standardization - Centralize package metadata in Directory.Build.props - Implement MinVer for semantic versioning from Git tags (v-prefix, 1.0 minimum) - Enable SourceLink for source code debugging support - Configure deterministic builds for reproducibility - Add XML documentation generation for all packages - Standardize package metadata (authors, license, repository, tags) - Optimize package logo to NuGet standards (128x128px, 27.65 KB) ### Release Automation - Add Release Drafter for PR-based automatic changelog generation - Configure 9 changelog categories (Breaking Changes, Features, Bug Fixes, etc.) - Implement auto-labeling based on files, branches, and PR titles - Create comprehensive label definitions (215 labels across all categories) - Add PR template to guide contributors on proper labeling ### Project Structure Improvements - Clean up all .csproj files by removing redundant properties - Standardize provider package configuration across all 8 providers - Update .gitignore to exclude build artifacts and temporary files ### Documentation - Add comprehensive Release Drafter usage guide - Document GitHub Actions workflows and their purposes - Create label setup automation script This implementation provides a production-ready CI/CD pipeline that ensures consistent versioning, automated changelog generation, and reliable package publishing to NuGet.org for all 8 MultiLock provider packages.
Adding CONTRIBUTING.ms and CODE_OF_CONDUCT.md file, correcting minor issue in the setup-labels.ps1 powershell file
Fixes validation error when updating draft releases. The pull_request_target event provides valid commit references instead of PR merge refs.
Correcting minor language issue in the CODE_OF_CONDUCT.md file, and correcting sample code in the CONTRIBUTING.md file
Setting up Dependabot for version updates
…oft.Extensions.Logging.Abstractions Bumps Microsoft.Extensions.DependencyInjection.Abstractions from 8.0.0 to 9.0.10 Bumps Microsoft.Extensions.Logging.Abstractions from 8.0.0 to 9.0.10 --- updated-dependencies: - dependency-name: Microsoft.Extensions.DependencyInjection.Abstractions dependency-version: 9.0.10 dependency-type: direct:production update-type: version-update:semver-major - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-version: 9.0.10 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
Refactor the multi-provider demo sample to align with the MultiLock naming convention: - Rename project from LeaderElection.MultiProvider to MultiLock.MultiProvider - Extract DemoBackgroundService into separate file - Update project references to use MultiLock namespace (MultiLock.csproj, MultiLock.InMemory, MultiLock.FileSystem) - Update using statements to match new namespace structure - Update console output and temp path to use MultiLock branding - Add project to solution file - Apply modern C# syntax improvements (var to explicit types, simplified method calls)
- Add code coverage collection to build-and-test workflow - Add code coverage collection to publish-nuget workflow - Upload coverage reports to CodeCov in both workflows - Create codecov.yml to configure coverage targets and exclusions - Add CodeCov badge to README.md Coverage is collected using coverlet's XPlat Code Coverage and uploaded to CodeCov for tracking and PR comments. Test and sample projects are excluded from coverage calculations.
There was a problem hiding this comment.
Pull Request Overview
This PR integrates CodeCov for code coverage reporting into the MultiLock project. It adds configuration for coverage tracking, updates CI workflows to collect and upload coverage data, and adds a coverage badge to the README.
- Adds codecov.yml configuration file with coverage thresholds and ignore patterns
- Updates both CI workflows (build-and-test.yml and publish-nuget.yml) to collect code coverage using XPlat Code Coverage and upload results to CodeCov
- Adds CodeCov badge to README.md
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| codecov.yml | Configuration file defining coverage requirements, ignore patterns, and reporting behavior |
| README.md | Adds CodeCov badge linking to coverage reports |
| .github/workflows/build-and-test.yml | Adds code coverage collection and CodeCov upload step |
| .github/workflows/publish-nuget.yml | Adds code coverage collection and CodeCov upload step |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| with: | ||
| files: '**/coverage.cobertura.xml' | ||
| fail_ci_if_error: false | ||
| verbose: true |
There was a problem hiding this comment.
The codecov-action@v4 requires a token for authentication. Add the 'token' parameter with a reference to a CODECOV_TOKEN secret: token: ${{ secrets.CODECOV_TOKEN }}. Without this token, uploads may fail or have limited functionality.
| verbose: true | |
| verbose: true | |
| token: ${{ secrets.CODECOV_TOKEN }} |
| with: | ||
| files: '**/coverage.cobertura.xml' | ||
| fail_ci_if_error: false | ||
| verbose: true |
There was a problem hiding this comment.
The codecov-action@v4 requires a token for authentication. Add the 'token' parameter with a reference to a CODECOV_TOKEN secret: token: ${{ secrets.CODECOV_TOKEN }}. Without this token, uploads may fail or have limited functionality.
| verbose: true | |
| verbose: true | |
| token: ${{ secrets.CODECOV_TOKEN }} |
Description
Add CodeCov integration for code coverage reporting to this repo
Type of Change
Related Issue
Changes Made
Coverage is collected using coverlet's XPlat Code Coverage and uploaded to CodeCov for tracking and PR comments. Test and sample projects are excluded from coverage calculations.
Testing
Checklist
Labels
Additional Notes