Skip to content
Draft
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
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ on:
permissions:
contents: read
statuses: write
pull-requests: write

jobs:
test-typescript:
Expand Down Expand Up @@ -54,3 +55,4 @@ jobs:
difference-threshold: 0
patch-threshold: 10
skip-empty-patch: true
flag: unit
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,30 @@ A GitHub action to upload coverage to codelyze.com.
path: coverage/lcov.info
```

For projects with multiple test types, use the `flag` input to track each
independently:

```yml
- name: Upload unit coverage
uses: codelyze/action@2.1.0
with:
token: ${{ secrets.CODELYZE_TOKEN }}
path: coverage/unit.lcov
flag: unit

- name: Upload e2e coverage
uses: codelyze/action@2.1.0
with:
token: ${{ secrets.CODELYZE_TOKEN }}
path: coverage/e2e.lcov
flag: e2e
```

Flags must be configured in the codelyze.com project settings before uploading.
Each flagged upload creates a `codelyze/{flag}` commit status alongside the
overall `codelyze/project` status. Coverage from flags is union-merged (a line
is covered if any flag covers it).

### Permission

The following workflow permissions are necessary:
Expand All @@ -26,6 +50,7 @@ The following workflow permissions are necessary:
permissions:
contents: read
statuses: write
pull-requests: write
```

### Inputs
Expand All @@ -42,6 +67,7 @@ permissions:
| `difference-threshold` | The minimum total difference allowed between the current commit and the reference one | no | 0 |
| `patch-threshold` | the minimum value for patch coverage: the minimum ratio of new lines that are not covered. | no | 0 |
| `skip-empty-patch` | If true don't even add a commit status for a patch that has no changes. | no | false |
| `flag` | Flag identifier for this coverage upload (e.g. `unit`, `e2e`). Used to track multiple test types independently. Creates a `codelyze/{flag}` commit status in addition to `codelyze/project`. | no | |

### Outputs

Expand Down
87 changes: 86 additions & 1 deletion __tests__/coverage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import * as coreMock from './fixture/mocks/core.ts'
import * as githubMock from './fixture/mocks/github.ts'
import * as codelyzeMock from './fixture/mocks/codelyze.ts'
import * as utilMock from './fixture/mocks/util.ts'
import * as commentMock from './fixture/mocks/comment.ts'

jest.unstable_mockModule('@actions/core', () => coreMock)
jest.unstable_mockModule('@actions/github', () => githubMock)
jest.unstable_mockModule('../src/codelyze', () => codelyzeMock)
jest.unstable_mockModule('../src/util', () => utilMock)
jest.unstable_mockModule('../src/comment', () => commentMock)

describe('coverage', () => {
const createMockContext = (): {
Expand Down Expand Up @@ -56,6 +58,9 @@ describe('coverage', () => {
coreMock.getInput.mockReturnValue('')
coreMock.getBooleanInput.mockReturnValue(false)

commentMock.upsertPrComment.mockResolvedValue(undefined)
commentMock.fetchFlagSummaries.mockResolvedValue([])

codelyzeMock.coverage.mockResolvedValue({
check: {
linesHit: 50,
Expand All @@ -79,7 +84,8 @@ describe('coverage', () => {
email: 'test@test.com',
date: '2024-01-01'
}
}
},
parents: [{ sha: 'parent-sha' }]
}
})
}
Expand Down Expand Up @@ -451,4 +457,83 @@ describe('coverage', () => {
expect(call.description).toContain('difference-threshold')
})
})

describe('flags', () => {
it('forwards flag to codelyze.coverage', async () => {
const { coverage } = await import('../src/coverage')
await coverage({
token: 'test',
ghToken: 'gh-test',
summary: createMockSummary(50, 100),
data: createMockLcov(),
context: createMockContext(),
diffCoverage: createMockDiffCoverage(),
shouldAddAnnotation: false,
threshold: 0,
differenceThreshold: 0,
patchThreshold: 0,
emptyPatch: false,
flag: 'unit'
})

expect(codelyzeMock.coverage).toHaveBeenCalledWith(
expect.objectContaining({ flag: 'unit' })
)
})

it('forwards parentShas to codelyze.coverage', async () => {
const { coverage } = await import('../src/coverage')
await coverage({
token: 'test',
ghToken: 'gh-test',
summary: createMockSummary(50, 100),
data: createMockLcov(),
context: createMockContext(),
diffCoverage: createMockDiffCoverage(),
shouldAddAnnotation: false,
threshold: 0,
differenceThreshold: 0,
patchThreshold: 0,
emptyPatch: false
})

expect(codelyzeMock.coverage).toHaveBeenCalledWith(
expect.objectContaining({ parentShas: ['parent-sha'] })
)
})

it('posts a commit status for each flag returned by fetchFlagSummaries', async () => {
commentMock.fetchFlagSummaries.mockResolvedValue([
{
flagName: 'unit',
linesHit: 80,
linesFound: 100,
carryforward: false
},
{ flagName: 'e2e', linesHit: 40, linesFound: 50, carryforward: true }
])

const { coverage } = await import('../src/coverage')
await coverage({
token: 'test',
ghToken: 'gh-test',
summary: createMockSummary(50, 100),
data: createMockLcov(),
context: createMockContext(),
diffCoverage: createMockDiffCoverage(),
shouldAddAnnotation: false,
threshold: 0,
differenceThreshold: 0,
patchThreshold: 0,
emptyPatch: false
})

expect(utilMock.createCommitStatus).toHaveBeenCalledWith(
expect.objectContaining({ commitContext: 'codelyze/unit' })
)
expect(utilMock.createCommitStatus).toHaveBeenCalledWith(
expect.objectContaining({ commitContext: 'codelyze/e2e' })
)
})
})
})
5 changes: 5 additions & 0 deletions __tests__/fixture/mocks/comment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type * as comment from '../../../src/comment.ts'
import { jest } from '@jest/globals'

export const upsertPrComment = jest.fn<typeof comment.upsertPrComment>()
export const fetchFlagSummaries = jest.fn<typeof comment.fetchFlagSummaries>()
6 changes: 6 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ inputs:
'if true, skip the commit status for a patch that has no coverable line
changes.'
default: 'false'
flag:
description:
'Flag identifier for this coverage upload (e.g. "unit", "e2e"). Used to
track multiple test types independently.'
required: false
default: ''

outputs:
coverage:
Expand Down
119 changes: 116 additions & 3 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/codelyze.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ interface Coverage {
commitDate?: string
compareSha?: string
data?: Lcov
flag?: string
parentShas?: string[]
}

interface Response {
Expand Down
Loading
Loading