diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 95f1dc2d..110a2e1e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,12 +22,12 @@ jobs: fetch-depth: 0 - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 20 - name: Install pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v4 with: version: 9 run_install: false @@ -39,7 +39,7 @@ jobs: - name: Cache node_modules id: cache-node-modules - uses: actions/cache@v3 + uses: actions/cache@v4 env: cache-name: cache-codecov-js-bundle-plugin-node-modules with: @@ -62,12 +62,12 @@ jobs: fetch-depth: 0 - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 20 - name: Install pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v4 with: version: 9 run_install: false @@ -79,7 +79,7 @@ jobs: - name: Cache node_modules id: cache-node-modules - uses: actions/cache@v3 + uses: actions/cache@v4 env: cache-name: cache-codecov-js-bundle-plugin-node-modules with: @@ -108,12 +108,12 @@ jobs: fetch-depth: 0 - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 20 - name: Install pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v4 with: version: 9 run_install: false @@ -125,7 +125,7 @@ jobs: - name: Cache node_modules id: cache-node-modules - uses: actions/cache@v3 + uses: actions/cache@v4 env: cache-name: cache-codecov-js-bundle-plugin-node-modules with: @@ -154,12 +154,12 @@ jobs: fetch-depth: 0 - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 20 - name: Install pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v4 with: version: 9 run_install: false @@ -171,7 +171,7 @@ jobs: - name: Cache node_modules id: cache-node-modules - uses: actions/cache@v3 + uses: actions/cache@v4 env: cache-name: cache-codecov-js-bundle-plugin-node-modules with: @@ -237,12 +237,12 @@ jobs: fetch-depth: 0 - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - name: Install pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v4 with: version: 9 run_install: false @@ -254,7 +254,7 @@ jobs: - name: Cache node_modules id: cache-node-modules - uses: actions/cache@v3 + uses: actions/cache@v4 env: cache-name: cache-codecov-js-bundle-plugin-node-modules with: @@ -288,12 +288,12 @@ jobs: fetch-depth: 0 - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 20 - name: Install pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v4 with: version: 9 run_install: false @@ -305,7 +305,7 @@ jobs: - name: Cache node_modules id: cache-node-modules - uses: actions/cache@v3 + uses: actions/cache@v4 env: cache-name: cache-codecov-js-bundle-plugin-node-modules with: @@ -326,6 +326,8 @@ jobs: - name: Build ${{ matrix.example }} app for production working-directory: ./examples/${{ matrix.example }} env: + HEAD_SHA: ${{ github.event.pull_request.head.sha }} + BASE_SHA: ${{ github.event.pull_request.base.sha }} NEXT_UPLOAD_TOKEN: ${{ secrets.CODECOV_ORG_TOKEN }} NEXT_API_URL: ${{ secrets.CODECOV_API_URL }} NUXT_UPLOAD_TOKEN: ${{ secrets.CODECOV_ORG_TOKEN }} @@ -358,12 +360,12 @@ jobs: fetch-depth: 0 - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 20 - name: Install pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v4 with: version: 9 run_install: false @@ -375,7 +377,7 @@ jobs: - name: Cache node_modules id: cache-node-modules - uses: actions/cache@v3 + uses: actions/cache@v4 env: cache-name: cache-codecov-js-bundle-plugin-node-modules with: @@ -396,6 +398,8 @@ jobs: - name: Build ${{ matrix.example }} app for staging working-directory: ./examples/${{ matrix.example }} env: + HEAD_SHA: ${{ github.event.pull_request.head.sha }} + BASE_SHA: ${{ github.event.pull_request.base.sha }} NEXT_UPLOAD_TOKEN: ${{ secrets.CODECOV_ORG_TOKEN_STAGING }} NEXT_API_URL: ${{ secrets.CODECOV_STAGING_API_URL }} NUXT_UPLOAD_TOKEN: ${{ secrets.CODECOV_ORG_TOKEN }} @@ -436,12 +440,12 @@ jobs: fetch-depth: 0 - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 20 - name: Install pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v4 with: version: 9 run_install: false @@ -453,7 +457,7 @@ jobs: - name: Cache node_modules id: cache-node-modules - uses: actions/cache@v3 + uses: actions/cache@v4 env: cache-name: cache-codecov-js-bundle-plugin-node-modules with: @@ -502,12 +506,12 @@ jobs: fetch-depth: 0 - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 20 - name: Install pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v4 with: version: 9 run_install: false @@ -519,7 +523,7 @@ jobs: - name: Cache node_modules id: cache-node-modules - uses: actions/cache@v3 + uses: actions/cache@v4 env: cache-name: cache-codecov-js-bundle-plugin-node-modules with: diff --git a/examples/next-js/next.config.js b/examples/next-js/next.config.js index b4368457..43611997 100644 --- a/examples/next-js/next.config.js +++ b/examples/next-js/next.config.js @@ -9,6 +9,7 @@ const nextConfig = { bundleName: "@codecov/example-next-app", uploadToken: process.env.NEXT_UPLOAD_TOKEN, apiUrl: process.env.NEXT_API_URL, + debug: true, }), ); diff --git a/examples/nuxt/nuxt.config.ts b/examples/nuxt/nuxt.config.ts index 560966a2..c8cfd417 100644 --- a/examples/nuxt/nuxt.config.ts +++ b/examples/nuxt/nuxt.config.ts @@ -9,6 +9,7 @@ export default defineNuxtConfig({ bundleName: "@codecov/example-nuxt-app", uploadToken: process.env.NUXT_UPLOAD_TOKEN, apiUrl: process.env.NUXT_API_URL, + debug: true, }, ], ], diff --git a/examples/remix/vite.config.ts b/examples/remix/vite.config.ts index f3240312..d5b0b053 100644 --- a/examples/remix/vite.config.ts +++ b/examples/remix/vite.config.ts @@ -18,6 +18,7 @@ export default defineConfig({ bundleName: "@codecov/example-remix-app", uploadToken: process.env.REMIX_UPLOAD_TOKEN, apiUrl: process.env.REMIX_API_URL, + debug: true, }), ], }); diff --git a/examples/rollup/rollup.config.js b/examples/rollup/rollup.config.js index 1d458c2d..9a679b69 100644 --- a/examples/rollup/rollup.config.js +++ b/examples/rollup/rollup.config.js @@ -22,6 +22,11 @@ export default defineConfig({ bundleName: "@codecov/example-rollup-app", apiUrl: process.env.ROLLUP_API_URL, uploadToken: process.env.ROLLUP_UPLOAD_TOKEN, + debug: true, + uploadOverrides: { + sha: process.env.HEAD_SHA, + compareSha: process.env.BASE_SHA, + }, }), ], }); diff --git a/examples/sveltekit/vite.config.ts b/examples/sveltekit/vite.config.ts index d2bbd283..486d7203 100644 --- a/examples/sveltekit/vite.config.ts +++ b/examples/sveltekit/vite.config.ts @@ -10,6 +10,7 @@ export default defineConfig({ bundleName: "@codecov/example-sveltekit-app", uploadToken: process.env.SVELTEKIT_UPLOAD_TOKEN, apiUrl: process.env.SVELTEKIT_API_URL, + debug: true, }), ], }); diff --git a/examples/vite/vite.config.ts b/examples/vite/vite.config.ts index 3ad45864..adaf7ba6 100644 --- a/examples/vite/vite.config.ts +++ b/examples/vite/vite.config.ts @@ -19,6 +19,7 @@ export default defineConfig({ bundleName: "@codecov/example-vite-app", uploadToken: process.env.VITE_UPLOAD_TOKEN, apiUrl: process.env.VITE_API_URL, + debug: true, }), ], }); diff --git a/examples/webpack/webpack.config.js b/examples/webpack/webpack.config.js index 301ad860..d55fb99a 100644 --- a/examples/webpack/webpack.config.js +++ b/examples/webpack/webpack.config.js @@ -14,6 +14,7 @@ module.exports = { bundleName: "@codecov/example-webpack-app", uploadToken: process.env.WEBPACK_UPLOAD_TOKEN, apiUrl: process.env.WEBPACK_API_URL, + debug: true, }), ], }; diff --git a/packages/bundler-plugin-core/src/types.ts b/packages/bundler-plugin-core/src/types.ts index fc3725fd..4a8af554 100644 --- a/packages/bundler-plugin-core/src/types.ts +++ b/packages/bundler-plugin-core/src/types.ts @@ -123,6 +123,8 @@ export interface UploadOverrides { branch?: string; /** Specify the build number manually. */ build?: string; + /** Specify the compare SHA manually. **GH Actions only**. */ + compareSha?: string; /** Specify the pull request number manually. */ pr?: string; /** Specify the commit SHA manually. */ @@ -153,6 +155,8 @@ export interface ProviderServiceParams { build: string; buildURL: string; commit: string; + // this is a custom field that is only used for GH pre-merge commits + compareSha?: string; job: string; pr: string; service: string; diff --git a/packages/bundler-plugin-core/src/utils/__tests__/normalizeOptions.test.ts b/packages/bundler-plugin-core/src/utils/__tests__/normalizeOptions.test.ts index 520b7443..0f8227f6 100644 --- a/packages/bundler-plugin-core/src/utils/__tests__/normalizeOptions.test.ts +++ b/packages/bundler-plugin-core/src/utils/__tests__/normalizeOptions.test.ts @@ -55,6 +55,7 @@ const tests: Test[] = [ uploadOverrides: { branch: "test-branch", build: "test-build", + compareSha: "test-compare-sha", sha: "test-sha", slug: "test-slug", pr: "1234", @@ -74,6 +75,7 @@ const tests: Test[] = [ uploadOverrides: { branch: "test-branch", build: "test-build", + compareSha: "test-compare-sha", sha: "test-sha", slug: "test-slug", pr: "1234", @@ -104,6 +106,8 @@ const tests: Test[] = [ // @ts-expect-error - testing invalid input build: 123, // @ts-expect-error - testing invalid input + compareSha: 123, + // @ts-expect-error - testing invalid input sha: 123, // @ts-expect-error - testing invalid input slug: 123, @@ -123,6 +127,7 @@ const tests: Test[] = [ "`uploadToken` must be a string.", "`branch` must be a string.", "`build` must be a string.", + "`compareSha` must be a string.", "`pr` must be a string.", "`sha` must be a string.", "`slug` must be a string.", diff --git a/packages/bundler-plugin-core/src/utils/normalizeOptions.ts b/packages/bundler-plugin-core/src/utils/normalizeOptions.ts index 64892250..38d04869 100644 --- a/packages/bundler-plugin-core/src/utils/normalizeOptions.ts +++ b/packages/bundler-plugin-core/src/utils/normalizeOptions.ts @@ -20,6 +20,11 @@ const UploadOverridesSchema = z.object({ invalid_type_error: "`build` must be a string.", }) .optional(), + compareSha: z + .string({ + invalid_type_error: "`compareSha` must be a string.", + }) + .optional(), pr: z .string({ invalid_type_error: "`pr` must be a string.", diff --git a/packages/bundler-plugin-core/src/utils/providers/GitHubActions.ts b/packages/bundler-plugin-core/src/utils/providers/GitHubActions.ts index 853ae8e2..da08fb0c 100644 --- a/packages/bundler-plugin-core/src/utils/providers/GitHubActions.ts +++ b/packages/bundler-plugin-core/src/utils/providers/GitHubActions.ts @@ -158,6 +158,43 @@ function _getSHA(inputs: ProviderUtilInputs, output: Output): string { return commit ?? ""; } +function _getCompareSHA(inputs: ProviderUtilInputs, output: Output): string { + const { args } = inputs; + if (args?.compareSha && args.compareSha !== "") { + debug(`Using commit: ${args.compareSha}`, { enabled: output.debug }); + return args.compareSha; + } + + let compareSha = ""; + const pr = _getPR(inputs); + if (pr) { + const mergeCommitRegex = /^[a-z0-9]{40} [a-z0-9]{40}$/; + const mergeCommitMessage = runExternalProgram("git", [ + "show", + "--no-patch", + "--format=%P", + ]); + + debug(`Merge commit message: ${mergeCommitMessage}`, { + enabled: output.debug, + }); + + if (mergeCommitRegex.exec(mergeCommitMessage)) { + const splitMergeCommit = mergeCommitMessage.split(" "); + + debug(`Split commit message: ${splitMergeCommit}`, { + enabled: output.debug, + }); + + compareSha = splitMergeCommit?.[0] ? splitMergeCommit[0] : ""; + } + } + + debug(`Using compareSha: ${compareSha ?? ""}`, { enabled: output.debug }); + + return compareSha ?? ""; +} + function _getSlug(inputs: ProviderUtilInputs): string { const { args, envs } = inputs; if (args?.slug && args.slug !== "") { @@ -175,6 +212,7 @@ export async function getServiceParams( build: _getBuild(inputs), buildURL: await _getBuildURL(inputs), commit: _getSHA(inputs, output), + compareSha: _getCompareSHA(inputs, output), job: _getJob(inputs.envs), pr: _getPR(inputs), service: _getService(), diff --git a/packages/bundler-plugin-core/src/utils/providers/__tests__/GitHubActions.test.ts b/packages/bundler-plugin-core/src/utils/providers/__tests__/GitHubActions.test.ts index 6d0af1ad..dcc2e544 100644 --- a/packages/bundler-plugin-core/src/utils/providers/__tests__/GitHubActions.test.ts +++ b/packages/bundler-plugin-core/src/utils/providers/__tests__/GitHubActions.test.ts @@ -90,6 +90,7 @@ describe("GitHub Actions Params", () => { build: "2", buildURL: "https://github.com/testOrg/testRepo/actions/runs/2", commit: "testingsha", + compareSha: "", job: "testWorkflow", pr: "", service: "github-actions", @@ -123,16 +124,6 @@ describe("GitHub Actions Params", () => { GITHUB_WORKFLOW: "testWorkflow", }, }; - const expected: ProviderServiceParams = { - branch: "branch", - build: "2", - buildURL: "https://github.com/testOrg/testRepo/actions/runs/2", - commit: "testingsha", - job: "testWorkflow", - pr: "1", - service: "github-actions", - slug: "testOrg/testRepo", - }; const spawnSync = td.replace(childProcess, "spawnSync"); td.when( @@ -152,6 +143,18 @@ describe("GitHub Actions Params", () => { retryCount: 0, }); const params = await GitHubActions.getServiceParams(inputs, output); + + const expected: ProviderServiceParams = { + branch: "branch", + build: "2", + buildURL: "https://github.com/testOrg/testRepo/actions/runs/2", + commit: "testingsha", + compareSha: "", + job: "testWorkflow", + pr: "1", + service: "github-actions", + slug: "testOrg/testRepo", + }; expect(params).toMatchObject(expected); }); @@ -191,17 +194,6 @@ describe("GitHub Actions Params", () => { }, }; - const expected: ProviderServiceParams = { - branch: "branch", - build: "2", - buildURL: "https://github.com/testOrg/testRepo/actions/runs/2", - commit: "testingsha", - job: "testWorkflow", - pr: "1", - service: "github-actions", - slug: "testOrg/testRepo", - }; - const spawnSync = td.replace(childProcess, "spawnSync"); td.when( spawnSync("git", ["show", "--no-patch", "--format=%P"], { @@ -220,6 +212,18 @@ describe("GitHub Actions Params", () => { retryCount: 0, }); const params = await GitHubActions.getServiceParams(inputs, output); + + const expected: ProviderServiceParams = { + branch: "branch", + build: "2", + buildURL: "https://github.com/testOrg/testRepo/actions/runs/2", + commit: "testingsha", + compareSha: "", + job: "testWorkflow", + pr: "1", + service: "github-actions", + slug: "testOrg/testRepo", + }; expect(params).toMatchObject(expected); }); @@ -257,16 +261,6 @@ describe("GitHub Actions Params", () => { GITHUB_WORKFLOW: "testWorkflow", }, }; - const expected: ProviderServiceParams = { - branch: "branch", - build: "2", - buildURL: "https://github.com/testOrg/testRepo/actions/runs/2/jobs/2", - commit: "testingsha", - job: "testWorkflow", - pr: "1", - service: "github-actions", - slug: "testOrg/testRepo", - }; const spawnSync = td.replace(childProcess, "spawnSync"); td.when( @@ -286,6 +280,18 @@ describe("GitHub Actions Params", () => { retryCount: 0, }); const params = await GitHubActions.getServiceParams(inputs, output); + + const expected: ProviderServiceParams = { + branch: "branch", + build: "2", + buildURL: "https://github.com/testOrg/testRepo/actions/runs/2/jobs/2", + commit: "testingsha", + compareSha: "", + job: "testWorkflow", + pr: "1", + service: "github-actions", + slug: "testOrg/testRepo", + }; expect(params).toMatchObject(expected); }); @@ -304,16 +310,6 @@ describe("GitHub Actions Params", () => { GITHUB_WORKFLOW: "testWorkflow", }, }; - const expected: ProviderServiceParams = { - branch: "branch", - build: "2", - buildURL: "https://github.com/testOrg/testRepo/actions/runs/2", - commit: "testingmergecommitsha2345678901234567890", - job: "testWorkflow", - pr: "1", - service: "github-actions", - slug: "testOrg/testRepo", - }; const spawnSync = td.replace(childProcess, "spawnSync"); td.when( @@ -335,6 +331,18 @@ describe("GitHub Actions Params", () => { retryCount: 0, }); const params = await GitHubActions.getServiceParams(inputs, output); + + const expected: ProviderServiceParams = { + branch: "branch", + build: "2", + buildURL: "https://github.com/testOrg/testRepo/actions/runs/2", + commit: "testingmergecommitsha2345678901234567890", + compareSha: "testingsha123456789012345678901234567890", + job: "testWorkflow", + pr: "1", + service: "github-actions", + slug: "testOrg/testRepo", + }; expect(params).toMatchObject(expected); }); @@ -356,16 +364,6 @@ describe("GitHub Actions Params", () => { GITHUB_SERVER_URL: "https://github.com", }, }; - const expected: ProviderServiceParams = { - branch: "branch", - build: "3", - buildURL: "https://github.com/testOrg/testRepo/actions/runs/3", - commit: "testsha", - job: "", - pr: "2", - service: "github-actions", - slug: "testOrg/testRepo", - }; const spawnSync = td.replace(childProcess, "spawnSync"); td.when( @@ -383,6 +381,18 @@ describe("GitHub Actions Params", () => { retryCount: 0, }); const params = await GitHubActions.getServiceParams(inputs, output); + + const expected: ProviderServiceParams = { + branch: "branch", + build: "3", + buildURL: "https://github.com/testOrg/testRepo/actions/runs/3", + commit: "testsha", + compareSha: "", + job: "", + pr: "2", + service: "github-actions", + slug: "testOrg/testRepo", + }; expect(params).toMatchObject(expected); }); @@ -401,16 +411,6 @@ describe("GitHub Actions Params", () => { GITHUB_WORKFLOW: "testWorkflow", }, }; - const expected: ProviderServiceParams = { - branch: "branch", - build: "2", - buildURL: "https://github.com/testOrg/testRepo/actions/runs/2", - commit: "testingsha", - job: "testWorkflow", - pr: "1", - service: "github-actions", - slug: "testOrg/testRepo", - }; const spawnSync = td.replace(childProcess, "spawnSync"); td.when( @@ -428,6 +428,18 @@ describe("GitHub Actions Params", () => { retryCount: 0, }); const params = await GitHubActions.getServiceParams(inputs, output); + + const expected: ProviderServiceParams = { + branch: "branch", + build: "2", + buildURL: "https://github.com/testOrg/testRepo/actions/runs/2", + commit: "testingsha", + compareSha: "", + job: "testWorkflow", + pr: "1", + service: "github-actions", + slug: "testOrg/testRepo", + }; expect(params).toMatchObject(expected); }); });