Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add coverage generation step to CircleCI and OtherCI onboarding #3596

Merged
Merged
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
52 changes: 45 additions & 7 deletions src/pages/RepoPage/CoverageOnboarding/CircleCI/CircleCI.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,37 @@ describe('CircleCI', () => {
return { mockMetricMutationVariables, user }
}

describe('step one', () => {
describe('output coverage step', () => {
it('renders header', async () => {
setup({})
render(<CircleCI />, { wrapper })

const header = await screen.findByRole('heading', { name: /Step 1/ })
const header = await screen.findByText(
/Step \d: Output a Coverage report file in your CI/
)
expect(header).toBeInTheDocument()
})

it('renders body', async () => {
setup({})
render(<CircleCI />, { wrapper })

const body = await screen.findByText(/Select your language below/)
expect(body).toBeInTheDocument()

const jest = await screen.findByText(/Jest/)
expect(jest).toBeInTheDocument()
})
})

describe('token step', () => {
it('renders header', async () => {
setup({})
render(<CircleCI />, { wrapper })

const header = await screen.findByRole('heading', {
name: /Step \d: add repository token to environment variables/,
})
expect(header).toBeInTheDocument()
})

Expand Down Expand Up @@ -204,13 +229,15 @@ describe('CircleCI', () => {
})
})

describe('step two', () => {
describe('orb yaml step', () => {
beforeEach(() => setup({}))

it('renders header', async () => {
render(<CircleCI />, { wrapper })

const header = await screen.findByRole('heading', { name: /Step 2/ })
const header = await screen.findByRole('heading', {
name: /Step \d: add Codecov orb to CircleCI/,
})
expect(header).toBeInTheDocument()

const CircleCIJSWorkflowLink = await screen.findByRole('link', {
Expand Down Expand Up @@ -252,8 +279,18 @@ describe('CircleCI', () => {
})
})

describe('step three', () => {
describe('merge step', () => {
beforeEach(() => setup({}))

it('renders header', async () => {
render(<CircleCI />, { wrapper })

const header = await screen.findByText(
/Step \d: merge to main or your preferred feature branch/
)
expect(header).toBeInTheDocument()
})

it('renders body', async () => {
render(<CircleCI />, { wrapper })

Expand Down Expand Up @@ -299,20 +336,21 @@ describe('CircleCI', () => {

describe('user copies text', () => {
it('stores codecov metric', async () => {
// will be removing this stuff soon, backend for this doesn't exist anymore
const { mockMetricMutationVariables } = setup({})
const user = userEvent.setup()
render(<CircleCI />, { wrapper })

const copyCommands = await screen.findAllByTestId(
'clipboard-code-snippet'
)
expect(copyCommands.length).toEqual(3)
expect(copyCommands.length).toEqual(5)

await user.click(copyCommands[1] as HTMLElement)

await user.click(copyCommands[2] as HTMLElement)
await waitFor(() =>
expect(mockMetricMutationVariables).toHaveBeenCalledTimes(2)
expect(mockMetricMutationVariables).toHaveBeenCalledTimes(1)
)
})
})
Expand Down
41 changes: 30 additions & 11 deletions src/pages/RepoPage/CoverageOnboarding/CircleCI/CircleCI.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useState } from 'react'
import { useParams } from 'react-router-dom'

import envVarScreenshot from 'assets/onboarding/env_variable_screenshot.png'
Expand All @@ -17,6 +18,11 @@ import { ExpandableSection } from 'ui/ExpandableSection'

import ExampleBlurb from '../ExampleBlurb'
import LearnMoreBlurb from '../LearnMoreBlurb'
import OutputCoverageStep from '../OutputCoverageStep/OutputCoverageStep'
import {
Framework,
UseFrameworkInstructions,
} from '../UseFrameworkInstructions'

const orbsString = `orbs:
codecov: codecov/codecov@5
Expand Down Expand Up @@ -49,15 +55,28 @@ function CircleCI() {
const uploadToken = orgUploadToken ?? data?.repository?.uploadToken ?? ''
const tokenCopy = orgUploadToken ? 'global' : 'repository'

const [framework, setFramework] = useState<Framework>('Jest')
const frameworkInstructions = UseFrameworkInstructions({
orgUploadToken,
owner,
repo,
})

return (
<div className="flex flex-col gap-5">
<Step1
<OutputCoverageStep
framework={framework}
frameworkInstructions={frameworkInstructions}
owner={owner}
setFramework={setFramework}
/>
<TokenStep
tokenCopy={tokenCopy}
uploadToken={uploadToken}
providerName={providerName!}
/>
<Step2 defaultBranch={data?.repository?.defaultBranch ?? ''} />
<Step3 />
<OrbYAMLStep defaultBranch={data?.repository?.defaultBranch ?? ''} />
<MergeStep />
<FeedbackCTA />
<LearnMoreBlurb />
</div>
Expand All @@ -66,20 +85,20 @@ function CircleCI() {

export default CircleCI

interface Step1Props {
interface TokenStepProps {
tokenCopy: string
uploadToken: string
providerName: string
}

function Step1({ tokenCopy, uploadToken, providerName }: Step1Props) {
function TokenStep({ tokenCopy, uploadToken, providerName }: TokenStepProps) {
const { mutate: storeEventMetric } = useStoreCodecovEventMetric()
const { owner } = useParams<URLParams>()
return (
<Card>
<Card.Header>
<Card.Title size="base">
Step 1: add {tokenCopy} token to environment variables
Step 2: add {tokenCopy} token to environment variables
</Card.Title>
</Card.Header>
<Card.Content className="flex flex-col gap-4">
Expand Down Expand Up @@ -133,18 +152,18 @@ function Step1({ tokenCopy, uploadToken, providerName }: Step1Props) {
)
}

interface Step2Props {
interface OrbYAMLStepProps {
defaultBranch: string
}

function Step2({ defaultBranch }: Step2Props) {
function OrbYAMLStep({ defaultBranch }: OrbYAMLStepProps) {
const { mutate: storeEventMetric } = useStoreCodecovEventMetric()
const { owner } = useParams<URLParams>()
return (
<Card>
<Card.Header>
<Card.Title size="base">
Step 2: add Codecov orb to CircleCI{' '}
Step 3: add Codecov orb to CircleCI{' '}
<A
hook="circleCIyamlLink"
isExternal
Expand Down Expand Up @@ -180,12 +199,12 @@ function Step2({ defaultBranch }: Step2Props) {
)
}

function Step3() {
function MergeStep() {
return (
<Card>
<Card.Header>
<Card.Title size="base">
Step 3: merge to main or your preferred feature branch
Step 4: merge to main or your preferred feature branch
</Card.Title>
</Card.Header>
<Card.Content className="flex flex-col gap-4">
Expand Down
167 changes: 11 additions & 156 deletions src/pages/RepoPage/CoverageOnboarding/GitHubActions/GitHubActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@ import A from 'ui/A'
import { Card } from 'ui/Card'

import MergeStep from './MergeStep'
import OutputCoverageStep from './OutputCoverageStep'
import TokenStep from './TokenStep'
import { Framework } from './types'
import WorkflowYMLStep from './WorkflowYMLStep'

import LearnMoreBlurb from '../LearnMoreBlurb'
import OutputCoverageStep from '../OutputCoverageStep/OutputCoverageStep'
import {
Framework,
UseFrameworkInstructions,
} from '../UseFrameworkInstructions'

interface URLParams {
provider: Provider
owner: string
Expand Down Expand Up @@ -60,161 +64,12 @@ function GitHubActions() {
}

const [framework, setFramework] = useState<Framework>('Jest')
const frameworkInstructions = UseFrameworkInstructions({
orgUploadToken,
owner,
repo,
})

const frameworkInstructions = {
Jest: {
install: 'npm install --save-dev jest',
run: 'npx jest --coverage',
workflow: `name: Run tests and upload coverage

on:
push

jobs:
test:
name: Run tests and collect coverage
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Node
uses: actions/setup-node@v4

- name: Install dependencies
run: npm install

- name: Run tests
run: npx jest --coverage

- name: Upload results to Codecov
uses: codecov/codecov-action@v5
with:
token: \${{ secrets.CODECOV_TOKEN }}${
orgUploadToken
? `
slug: ${owner}/${repo}`
: ''
}
`,
},
Vitest: {
install: 'npm install --save-dev vitest @vitest/coverage-v8',
run: 'npx vitest run --coverage',
workflow: `name: Run tests and upload coverage

on:
push

jobs:
test:
name: Run tests and collect coverage
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Node
uses: actions/setup-node@v4

- name: Install dependencies
run: npm install

- name: Run tests
run: npx vitest run --coverage

- name: Upload results to Codecov
uses: codecov/codecov-action@v5
with:
token: \${{ secrets.CODECOV_TOKEN }}${
orgUploadToken
? `
slug: ${owner}/${repo}`
: ''
}
`,
},
Pytest: {
install: 'pip install pytest pytest-cov',
run: 'pytest --cov --cov-report=xml',
workflow: `name: Run tests and upload coverage

on:
push

jobs:
test:
name: Run tests and collect coverage
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v4

- name: Install dependencies
run: pip install pytest pytest-cov

- name: Run tests
run: pytest --cov --cov-report=xml

- name: Upload results to Codecov
uses: codecov/codecov-action@v5
with:
token: \${{ secrets.CODECOV_TOKEN }}${
orgUploadToken
? `
slug: ${owner}/${repo}`
: ''
}
`,
},
Go: {
install: undefined,
run: 'go test -coverprofile=coverage.txt',
workflow: `name: Run tests and upload coverage

on:
push

jobs:
test:
name: Run tests and collect coverage
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Go
uses: actions/setup-go@v5

- name: Install dependencies
run: go mod download

- name: Run tests
run: go test -coverprofile=coverage.txt

- name: Upload results to Codecov
uses: codecov/codecov-action@v5
with:
token: \${{ secrets.CODECOV_TOKEN }}${
orgUploadToken
? `
slug: ${owner}/${repo}`
: ''
}
`,
},
}
return (
<div className="flex flex-col gap-5">
<OutputCoverageStep
Expand Down
Loading
Loading