Skip to content

Commit 26f986d

Browse files
MishaKavclaude
andauthored
Migrate codebase from JavaScript to TypeScript (#255)
* Migrate codebase from JavaScript to TypeScript - Convert all 7 source files (utils, parse, parseXml, junitXml, multiFiles, index, cli) to TypeScript - Add shared type definitions in src/types.d.ts - Add 91 unit tests using Vitest with V8 coverage (~91% statement coverage) - Add CI workflow for format, lint, build, test and coverage badge - Configure TypeScript, ESLint, Vitest, Prettier for TypeScript - Bump version to 1.6.0 - Update dev dependencies to latest compatible versions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Address code review findings from Copilot, Cubic, and CodeRabbit - Fix env var restoration in test (delete when originally undefined) - Fix vacuous test assertions (parseXml skip-covered, parse branch coverage) - Log xml2js parse errors instead of silently ignoring them - Add testsuites structure guard to prevent crash on malformed XML - Add permissions block to CI workflow - Fix package.json main field to point to dist/index.js - Fix onlyChnaged typo in parse.ts - Remove redundant noImplicitAny from tsconfig (covered by strict) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 25a4660 commit 26f986d

26 files changed

Lines changed: 5567 additions & 2096 deletions
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
name: Update Coverage in README
2+
on:
3+
push:
4+
paths-ignore:
5+
- '**/*.md'
6+
- '**/*.yml'
7+
- '.github/**'
8+
- 'data/**'
9+
- 'dist/**'
10+
11+
permissions:
12+
contents: read
13+
14+
jobs:
15+
update-coverage-in-readme:
16+
name: Update Coverage in README
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@v6
20+
21+
- name: NPM Cache
22+
id: npm-cache
23+
uses: actions/cache@v5
24+
with:
25+
path: '**/node_modules'
26+
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
27+
restore-keys: |
28+
${{ runner.os }}-npm
29+
30+
- name: Install Dependencies
31+
if: steps.npm-cache.outputs.cache-hit != 'true'
32+
run: npm ci
33+
34+
- name: Check Format
35+
run: npm run format-check
36+
37+
- name: Check Lint
38+
run: npm run lint
39+
40+
- name: Check Build
41+
run: npm run build
42+
43+
- name: Run Tests
44+
run: npm run test:coverage
45+
46+
- name: Jest Coverage Comment
47+
id: coverageComment
48+
uses: MishaKav/jest-coverage-comment@main
49+
with:
50+
hide-comment: true
51+
coverage-summary-path: ./coverage/coverage-summary.json
52+
junitxml-path: ./coverage/junit.xml
53+
54+
- name: Check the output coverage
55+
run: |
56+
echo "Summary Report"
57+
echo "Coverage Percentage - ${{ steps.coverageComment.outputs.coverage }}"
58+
echo "Coverage Color - ${{ steps.coverageComment.outputs.color }}"
59+
echo "Summary Html - ${{ steps.coverageComment.outputs.summaryHtml }}"
60+
61+
echo "JUnit Report"
62+
echo "tests - ${{ steps.coverageComment.outputs.tests }}"
63+
echo "skipped - ${{ steps.coverageComment.outputs.skipped }}"
64+
echo "failures - ${{ steps.coverageComment.outputs.failures }}"
65+
echo "errors - ${{ steps.coverageComment.outputs.errors }}"
66+
echo "time - ${{ steps.coverageComment.outputs.time }}"
67+
68+
echo "Coverage Report"
69+
echo "lines - ${{ steps.coverageComment.outputs.lines }}"
70+
echo "branches - ${{ steps.coverageComment.outputs.branches }}"
71+
echo "functions - ${{ steps.coverageComment.outputs.functions }}"
72+
echo "statements - ${{ steps.coverageComment.outputs.statements }}"
73+
echo "coverage - ${{ steps.coverageComment.outputs.coverage }}"
74+
echo "color - ${{ steps.coverageComment.outputs.color }}"
75+
echo "Coverage Html - ${{ steps.coverageComment.outputs.coverageHtml }}"
76+
77+
- name: Create the badge
78+
if: github.ref == 'refs/heads/main'
79+
uses: schneegans/dynamic-badges-action@v1.7.0
80+
with:
81+
auth: ${{ secrets.JEST_COVERAGE_COMMENT }}
82+
gistID: 5e90d640f8c212ab7bbac38f72323f80
83+
filename: pytest-coverage-comment__main.json
84+
label: coverage
85+
message: ${{ steps.coverageComment.outputs.coverage }}%
86+
color: ${{ steps.coverageComment.outputs.color }}
87+
namedLogo: typescript

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
# Changelog of the Pytest Coverage Comment
22

3+
## [Pytest Coverage Comment 1.6.0](https://github.com/MishaKav/pytest-coverage-comment/tree/v1.6.0)
4+
5+
**Release Date:** 2026-03-06
6+
7+
#### Changes
8+
9+
- migrate codebase from JavaScript to TypeScript
10+
- add unit tests (91 tests) using Vitest with V8 coverage
11+
12+
**Note:** This is an internal rewrite — no changes to action inputs, outputs, or behavior. Fully backward compatible.
13+
314
## [Pytest Coverage Comment 1.5.0](https://github.com/MishaKav/pytest-coverage-comment/tree/v1.5.0)
415

516
**Release Date:** 2026-02-28

CLAUDE.md

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,50 +9,85 @@ pytest-coverage-comment is a GitHub Action that comments on pull requests with p
99
## Development Commands
1010

1111
### Build and Bundle
12+
1213
```bash
13-
npm run build # Bundle the action with ncc into dist/index.js
14-
npm run all # Run lint, format, and build in sequence
14+
npm run build # Bundle the action with ncc (compiles TS + bundles) into dist/index.js
15+
npm run all # Run typecheck, lint, format, test, and build in sequence
1516
```
1617

17-
### Code Quality
18+
### Type Checking and Code Quality
19+
1820
```bash
19-
npm run lint # Run ESLint on src/**/*.js
21+
npm run typecheck # Run tsc --noEmit (type-check only, no output)
22+
npm run lint # Run ESLint on src/**/*.ts
2023
npm run format # Format code with Prettier
2124
npm run format-check # Check formatting without changing files
2225
```
2326

27+
### Testing
28+
29+
```bash
30+
npm test # Run Vitest tests (vitest run)
31+
npm run test:watch # Run Vitest in watch mode
32+
npm run test:coverage # Run tests with V8 coverage
33+
```
34+
2435
### Version Management
36+
2537
```bash
2638
npm run bump-version # Increment patch version
2739
```
2840

2941
### Local Testing
30-
The `src/cli.js` file contains a CLI tool for local testing of coverage parsing functionality. It can be run directly to test coverage report generation without GitHub Actions.
42+
43+
The `src/cli.ts` file contains a CLI tool for local testing of coverage parsing functionality. It can be run directly to test coverage report generation without GitHub Actions.
3144

3245
## Architecture Overview
3346

34-
The codebase is a Node.js GitHub Action with the following key components:
47+
The codebase is a TypeScript GitHub Action with the following key components:
3548

3649
### Entry Points
37-
- **src/index.js**: Main GitHub Action entry point that orchestrates the entire workflow
38-
- **src/cli.js**: CLI utility for local testing and development
50+
51+
- **src/index.ts**: Main GitHub Action entry point that orchestrates the entire workflow
52+
- **src/cli.ts**: CLI utility for local testing and development
53+
54+
### Type Definitions
55+
56+
- **src/types.d.ts**: All shared TypeScript interfaces (Options, CoverageLine, TotalLine, etc.)
3957

4058
### Core Parsing Modules
41-
- **src/parse.js**: Parses pytest text coverage output (e.g., from `pytest --cov`)
42-
- **src/parseXml.js**: Parses XML coverage reports (e.g., from `pytest --cov-report=xml`)
43-
- **src/junitXml.js**: Parses JUnit XML test results for test statistics
59+
60+
- **src/parse.ts**: Parses pytest text coverage output (e.g., from `pytest --cov`)
61+
- **src/parseXml.ts**: Parses XML coverage reports (e.g., from `pytest --cov-report=xml`)
62+
- **src/junitXml.ts**: Parses JUnit XML test results for test statistics
4463

4564
### Supporting Modules
46-
- **src/multiFiles.js**: Handles multiple coverage files (useful for monorepos)
47-
- **src/utils.js**: Shared utilities for file operations, color determination, and GitHub API interactions
65+
66+
- **src/multiFiles.ts**: Handles multiple coverage files (useful for monorepos)
67+
- **src/utils.ts**: Shared utilities for file operations, color determination, and GitHub API interactions
68+
69+
### Test Infrastructure
70+
71+
- **\_\_tests\_\_/setup.ts**: Global test setup with `spyCore` mocks for `@actions/core`
72+
- **\_\_tests\_\_/\*.test.ts**: Vitest unit tests for each module (91 tests total)
73+
- Uses `exportedForTesting` pattern to expose internal functions for testing
74+
- Test fixtures in `data/` directory (pytest coverage txt, coverage xml, junit xml)
75+
76+
### Build System
77+
78+
- TypeScript is used for type-checking only (`noEmit: true` in tsconfig)
79+
- `@vercel/ncc` compiles TS and bundles directly to `dist/index.js` in a single step
80+
- No intermediate `lib/` or `outDir` needed
4881

4982
### Data Flow
83+
5084
1. Action receives coverage files (txt/xml) and JUnit XML as inputs
5185
2. Parsers extract coverage percentages, file details, and test statistics
5286
3. HTML report is generated with file links pointing to the repository
5387
4. Comment is created/updated on PR using GitHub API with coverage badge and collapsible report
5488

5589
### GitHub Integration
90+
5691
- Uses `@actions/core` for input/output handling
5792
- Uses `@actions/github` for API interactions (creating/updating PR comments)
5893
- Supports comment watermarking to update existing comments instead of creating duplicates
@@ -63,4 +98,7 @@ The codebase is a Node.js GitHub Action with the following key components:
6398
- Maximum comment length: 65,536 characters (GitHub limit)
6499
- Supports filtering to show only changed files in the current commit
65100
- Can skip files with 100% coverage from XML reports
66-
- Handles both absolute and relative file paths for coverage inputs
101+
- Handles both absolute and relative file paths for coverage inputs
102+
- xml2js `parseString` is used synchronously via callback pattern (not async)
103+
- `@actions/github` has ESM/CJS compatibility issues in test context — mock it with `vi.mock()` in tests
104+
- `@actions/core` v3+ and `@actions/github` v9+ are pure ESM — incompatible with ncc's webpack CJS bundling. Must stay on `@actions/core` v2.x and `@actions/github` v8.x until ncc supports ESM or the project switches bundlers

__tests__/index.test.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { expect, test, describe, vi } from 'vitest';
2+
3+
// Mock @actions/github before importing index to avoid ESM/CJS issues
4+
vi.mock('@actions/github', () => ({
5+
context: {
6+
repo: { repo: 'test', owner: 'owner' },
7+
eventName: 'push',
8+
payload: {},
9+
job: 'test-job',
10+
ref: 'refs/heads/main',
11+
sha: 'abc123',
12+
serverUrl: 'https://github.com',
13+
},
14+
getOctokit: vi.fn(),
15+
}));
16+
17+
import { truncateSummary } from '../src/index';
18+
19+
describe('truncateSummary', () => {
20+
test('should return content as-is when under limit', () => {
21+
const content = 'Short content';
22+
expect(truncateSummary(content, 1000)).toBe(content);
23+
});
24+
25+
test('should truncate content that exceeds limit', () => {
26+
const content = 'A'.repeat(2000);
27+
const result = truncateSummary(content, 1000);
28+
expect(result.length).toBeLessThanOrEqual(1000);
29+
expect(result).toContain('**Warning: Summary truncated');
30+
});
31+
32+
test('should try to break at newline', () => {
33+
const lines = Array.from({ length: 100 }, (_, i) => `Line ${i}`).join(
34+
'\n',
35+
);
36+
const result = truncateSummary(lines, 500);
37+
expect(result).toContain('**Warning: Summary truncated');
38+
});
39+
40+
test('should handle exact limit', () => {
41+
const content = 'Exact';
42+
expect(truncateSummary(content, 5)).toBe('Exact');
43+
});
44+
});

0 commit comments

Comments
 (0)