Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 76 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,82 @@ jobs:
- name: Decompress Build
run: unzip build.zip
- name: Test JBird
run: swift test
run: swift test --enable-code-coverage
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.

This still gives me dramatically different results for Swift 6.1 vs Swift 6.2 Your filtering is clearly not working.

- name: Generate Coverage Report
run: |
COVERAGE_JSON=$(swift test --show-codecov-path)
echo "Coverage report location: $COVERAGE_JSON"

# Create filtered coverage JSON with only project source files
# This excludes Swift package dependencies from the coverage report
FILTERED_JSON="${COVERAGE_JSON}.filtered"
jq '.data[0].files |= map(select(.filename | contains("/Sources/")))' "$COVERAGE_JSON" > "$FILTERED_JSON"

# Recalculate totals from filtered data
jq '.data[0].totals = {
lines: {
count: ([.data[0].files[].summary.lines.count] | add // 0),
covered: ([.data[0].files[].summary.lines.covered] | add // 0),
percent: (([.data[0].files[].summary.lines.covered] | add // 0) * 100.0 / ([.data[0].files[].summary.lines.count] | add // 1))
},
functions: {
count: ([.data[0].files[].summary.functions.count] | add // 0),
covered: ([.data[0].files[].summary.functions.covered] | add // 0),
percent: (([.data[0].files[].summary.functions.covered] | add // 0) * 100.0 / ([.data[0].files[].summary.functions.count] | add // 1))
},
regions: {
count: ([.data[0].files[].summary.regions.count] | add // 0),
covered: ([.data[0].files[].summary.regions.covered] | add // 0),
percent: (([.data[0].files[].summary.regions.covered] | add // 0) * 100.0 / ([.data[0].files[].summary.regions.count] | add // 1))
}
}' "$FILTERED_JSON" > "${FILTERED_JSON}.tmp" && mv "${FILTERED_JSON}.tmp" "$FILTERED_JSON"

# Extract coverage statistics from filtered data
LINES_PERCENT=$(jq -r '.data[0].totals.lines.percent' "$FILTERED_JSON")
LINES_COVERED=$(jq -r '.data[0].totals.lines.covered' "$FILTERED_JSON")
LINES_TOTAL=$(jq -r '.data[0].totals.lines.count' "$FILTERED_JSON")

FUNCTIONS_PERCENT=$(jq -r '.data[0].totals.functions.percent' "$FILTERED_JSON")
FUNCTIONS_COVERED=$(jq -r '.data[0].totals.functions.covered' "$FILTERED_JSON")
FUNCTIONS_TOTAL=$(jq -r '.data[0].totals.functions.count' "$FILTERED_JSON")

REGIONS_PERCENT=$(jq -r '.data[0].totals.regions.percent' "$FILTERED_JSON")
REGIONS_COVERED=$(jq -r '.data[0].totals.regions.covered' "$FILTERED_JSON")
REGIONS_TOTAL=$(jq -r '.data[0].totals.regions.count' "$FILTERED_JSON")

# Round percentages to 2 decimal places
LINES_PERCENT=$(printf "%.2f" "$LINES_PERCENT")
FUNCTIONS_PERCENT=$(printf "%.2f" "$FUNCTIONS_PERCENT")
REGIONS_PERCENT=$(printf "%.2f" "$REGIONS_PERCENT")

# Create markdown summary
cat >> $GITHUB_STEP_SUMMARY << EOF
## πŸ“Š Code Coverage Report (macOS, Swift ${{ matrix.swift }})

| Metric | Coverage | Covered | Total |
|--------|----------|---------|-------|
| **Lines** | **${LINES_PERCENT}%** | ${LINES_COVERED} | ${LINES_TOTAL} |
| **Functions** | **${FUNCTIONS_PERCENT}%** | ${FUNCTIONS_COVERED} | ${FUNCTIONS_TOTAL} |
| **Regions** | **${REGIONS_PERCENT}%** | ${REGIONS_COVERED} | ${REGIONS_TOTAL} |

✨ Coverage report generated successfully!
EOF

echo "Lines Coverage: ${LINES_PERCENT}%"
echo "Functions Coverage: ${FUNCTIONS_PERCENT}%"
echo "Regions Coverage: ${REGIONS_PERCENT}%"

# Save filtered coverage path for Codecov upload
echo "COVERAGE_JSON=$FILTERED_JSON" >> $GITHUB_ENV
- name: Upload Coverage to Codecov
uses: codecov/codecov-action@v5
with:
files: ${{ env.COVERAGE_JSON }}
flag: swift-${{ matrix.swift }}
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.

This fails because the flag argument doesn't exist

name: macos-swift-${{ matrix.swift }}
fail_ci_if_error: false
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
build-ubuntu-spm:
name: Build JBird (Ubuntu)
strategy:
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,7 @@ Benchmarks/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
*.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
/*.gcno
**/xcshareddata/WorkspaceSettings.xcsettings

# Code Coverage
*.profraw
*.profdata
131 changes: 131 additions & 0 deletions COVERAGE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Code Coverage Documentation

This document describes the code coverage reporting setup for the JBird project.

## Overview

Code coverage is automatically generated and reported for all commits and pull requests for macOS test configurations:
- macOS Swift 6.1 and 6.2

The coverage data is collected using Swift's built-in code coverage support and is visualized in two ways:

1. **GitHub Actions Summary**: A formatted table showing coverage metrics directly in the CI job output for each Swift version
2. **Codecov.io**: Detailed coverage reports, PR comments, and trend tracking with consolidated data from all platforms

## Coverage Metrics

The following metrics are tracked:

- **Lines Coverage**: Percentage of executable lines that were executed during tests
- **Functions Coverage**: Percentage of functions that were called during tests
- **Regions Coverage**: Percentage of code regions that were executed during tests

## Viewing Coverage Reports

### GitHub Actions Summary

After each test run, you can view the coverage summary by:

1. Go to the "Actions" tab in the GitHub repository
2. Select a workflow run
3. Click on "Test JBird (macOS)" for a Swift version
4. Scroll down to view the coverage table in the summary section

The summary shows:
```
## πŸ“Š Code Coverage Report (macOS, Swift 6.2)

| Metric | Coverage | Covered | Total |
|--------|----------|---------|-------|
| **Lines** | **XX.XX%** | XXXX | XXXX |
| **Functions** | **XX.XX%** | XXX | XXX |
| **Regions** | **XX.XX%** | XXXX | XXXX |
```

Each Swift version produces its own coverage report.

### Codecov Integration

Codecov provides additional features by consolidating coverage data from all Swift versions:

- **PR Comments**: Automatic comments on pull requests showing coverage changes
- **Coverage Trends**: Historical tracking of coverage over time
- **File-level Coverage**: Detailed line-by-line coverage for each file
- **Coverage Badge**: Optional badge for the README

Visit https://codecov.io/gh/vsanthanam/JBird to view detailed reports.

## Running Coverage Locally

To generate coverage reports locally:

```bash
# Run tests with coverage enabled
swift test --enable-code-coverage

# View the coverage JSON path
swift test --show-codecov-path

# The coverage data is stored at:
# .build/<platform>/debug/codecov/JBird.json
```

You can then examine the JSON file to see detailed coverage information.

## Coverage Configuration

### CI Configuration

Code coverage is enabled in `.github/workflows/ci.yml` for macOS test jobs:
- macOS Swift 6.1 and 6.2

```yaml
- name: Test JBird
run: swift test --enable-code-coverage
```

The coverage report filters results to only include project source files (those in `/Sources/` directory), excluding Swift package dependencies. This ensures accurate coverage metrics for the project's own code. The filtered JSON is then uploaded to Codecov to ensure consistency across all platforms.

### Codecov Configuration

The Codecov token is stored as a repository secret (`CODECOV_TOKEN`). For public repositories, this token is optional but recommended for better reliability and rate limits.

Coverage data from all Swift versions is uploaded with a single flag per upload:
- `swift-6.1` - macOS with Swift 6.1
- `swift-6.2` - macOS with Swift 6.2

To configure the token:
1. Sign up at https://codecov.io
2. Add the repository
3. Copy the upload token
4. Add it as `CODECOV_TOKEN` in repository secrets

## Future Enhancements

The coverage system supports several potential enhancements:

- **Coverage Thresholds**: Set minimum coverage percentages to fail CI
- **HTML Reports**: Generate browsable HTML coverage reports
- **Coverage Badges**: Add coverage badges to README
- **Differential Coverage**: Show coverage only for changed files

## Troubleshooting

### Coverage data not generated

Ensure you're running tests with `--enable-code-coverage`:
```bash
swift test --enable-code-coverage
```

### Codecov upload fails

- Verify `CODECOV_TOKEN` secret is set (if using private repo)
- Check the codecov action logs for specific errors
- Note: `fail_ci_if_error: false` prevents CI failure on upload errors

### Coverage appears low

- Coverage is only collected from executed test code
- Some generated code (like resource accessors) may not be covered
- Consider adding tests for uncovered code paths
Loading