From e6b405c0124698e7e3e0dc2be6103f415066835e Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Fri, 14 Feb 2025 09:32:06 +0000 Subject: [PATCH] chore: show gha pull request title instead of a merge commit (#34781) --- packages/html-reporter/src/metadataView.tsx | 30 +++++---- packages/playwright/src/isomorphic/types.d.ts | 1 + .../src/plugins/gitCommitInfoPlugin.ts | 22 +++++-- .../playwright-test-fixtures.ts | 1 + tests/playwright-test/reporter-html.spec.ts | 65 +++++++++++++++++-- 5 files changed, 95 insertions(+), 24 deletions(-) diff --git a/packages/html-reporter/src/metadataView.tsx b/packages/html-reporter/src/metadataView.tsx index 03a5ed06f4..0f54bb4249 100644 --- a/packages/html-reporter/src/metadataView.tsx +++ b/packages/html-reporter/src/metadataView.tsx @@ -107,14 +107,24 @@ const InnerMetadataView = () => { const GitCommitInfoView: React.FC<{ info: GitCommitInfo }> = ({ info }) => { const email = info['revision.email'] ? ` <${info['revision.email']}>` : ''; const author = `${info['revision.author'] || ''}${email}`; - const subject = info['revision.subject'] || ''; + + let subject = info['revision.subject'] || ''; + let link = info['revision.link']; + let shortSubject = info['revision.id']?.slice(0, 7) || 'unknown'; + + if (info['pull.link'] && info['pull.title']) { + subject = info['pull.title']; + link = info['pull.link']; + shortSubject = link ? 'Pull Request' : ''; + } + const shortTimestamp = Intl.DateTimeFormat(undefined, { dateStyle: 'medium' }).format(info['revision.timestamp']); const longTimestamp = Intl.DateTimeFormat(undefined, { dateStyle: 'full', timeStyle: 'long' }).format(info['revision.timestamp']); return
- {info['revision.link'] ? ( - + {link ? ( + {subject} ) : @@ -130,18 +140,12 @@ const GitCommitInfoView: React.FC<{ info: GitCommitInfo }> = ({ info }) => { Logs )} - {info['pull.link'] && ( - <> - ยท - Pull Request - - )}
- {!!info['revision.link'] ? ( - - {info['revision.id']?.slice(0, 7) || 'unknown'} + {link ? ( + + {shortSubject} - ) : !!info['revision.id'] && {info['revision.id'].slice(0, 7)}} + ) : !!shortSubject && {shortSubject}}
; }; diff --git a/packages/playwright/src/isomorphic/types.d.ts b/packages/playwright/src/isomorphic/types.d.ts index 213f350514..2619c0df33 100644 --- a/packages/playwright/src/isomorphic/types.d.ts +++ b/packages/playwright/src/isomorphic/types.d.ts @@ -25,5 +25,6 @@ export interface GitCommitInfo { 'pull.link'?: string; 'pull.diff'?: string; 'pull.base'?: string; + 'pull.title'?: string; 'ci.link'?: string; } diff --git a/packages/playwright/src/plugins/gitCommitInfoPlugin.ts b/packages/playwright/src/plugins/gitCommitInfoPlugin.ts index 29010183c7..7ade4a005c 100644 --- a/packages/playwright/src/plugins/gitCommitInfoPlugin.ts +++ b/packages/playwright/src/plugins/gitCommitInfoPlugin.ts @@ -14,6 +14,8 @@ * limitations under the License. */ +import fs from 'fs'; + import { createGuid, spawnAsync } from 'playwright-core/lib/utils'; import type { TestRunnerPlugin } from './'; @@ -33,7 +35,7 @@ export const gitCommitInfo = (options?: GitCommitInfoPluginOptions): TestRunnerP name: 'playwright:git-commit-info', setup: async (config: FullConfig, configDir: string) => { - const fromEnv = linksFromEnv(); + const fromEnv = await linksFromEnv(); const fromCLI = await gitStatusFromCLI(options?.directory || configDir, fromEnv); config.metadata = config.metadata || {}; config.metadata['git.commit.info'] = { ...fromEnv, ...fromCLI }; @@ -45,7 +47,7 @@ interface GitCommitInfoPluginOptions { directory?: string; } -function linksFromEnv() { +async function linksFromEnv() { const out: Partial = {}; // Jenkins: https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#using-environment-variables if (process.env.BUILD_URL) @@ -55,15 +57,21 @@ function linksFromEnv() { out['revision.link'] = `${process.env.CI_PROJECT_URL}/-/commit/${process.env.CI_COMMIT_SHA}`; if (process.env.CI_JOB_URL) out['ci.link'] = process.env.CI_JOB_URL; - // GitHub: https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables + // GitHub: https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables if (process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY && process.env.GITHUB_SHA) out['revision.link'] = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/commit/${process.env.GITHUB_SHA}`; if (process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY && process.env.GITHUB_RUN_ID) out['ci.link'] = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`; - if (process.env.GITHUB_REF_NAME && process.env.GITHUB_REF_NAME.endsWith('/merge')) { - const pullId = process.env.GITHUB_REF_NAME.substring(0, process.env.GITHUB_REF_NAME.indexOf('/merge')); - out['pull.link'] = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/pull/${pullId}`; - out['pull.base'] = process.env.GITHUB_BASE_REF; + if (process.env.GITHUB_EVENT_PATH) { + try { + const json = JSON.parse(await fs.promises.readFile(process.env.GITHUB_EVENT_PATH, 'utf8')); + if (json.pull_request) { + out['pull.title'] = json.pull_request.title; + out['pull.link'] = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/pull/${json.pull_request.number}`; + out['pull.base'] = json.pull_request.base.ref; + } + } catch { + } } return out; } diff --git a/tests/playwright-test/playwright-test-fixtures.ts b/tests/playwright-test/playwright-test-fixtures.ts index 789ed1feb6..43503497d2 100644 --- a/tests/playwright-test/playwright-test-fixtures.ts +++ b/tests/playwright-test/playwright-test-fixtures.ts @@ -227,6 +227,7 @@ export function cleanEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv { GITHUB_RUN_ID: undefined, GITHUB_SERVER_URL: undefined, GITHUB_SHA: undefined, + GITHUB_EVENT_PATH: undefined, // END: Reserved CI PW_TEST_HTML_REPORT_OPEN: undefined, PLAYWRIGHT_HTML_OPEN: undefined, diff --git a/tests/playwright-test/reporter-html.spec.ts b/tests/playwright-test/reporter-html.spec.ts index bf88f52ade..78ef741415 100644 --- a/tests/playwright-test/reporter-html.spec.ts +++ b/tests/playwright-test/reporter-html.spec.ts @@ -1221,11 +1221,8 @@ for (const useIntermediateMergeReport of [true, false] as const) { const result = await runInlineTest(files, { reporter: 'dot,html' }, { PLAYWRIGHT_HTML_OPEN: 'never', GITHUB_REPOSITORY: 'microsoft/playwright-example-for-test', - GITHUB_RUN_ID: 'example-run-id', GITHUB_SERVER_URL: 'https://playwright.dev', GITHUB_SHA: 'example-sha', - GITHUB_REF_NAME: '42/merge', - GITHUB_BASE_REF: 'HEAD~1', }); await showReport(); @@ -1235,9 +1232,69 @@ for (const useIntermediateMergeReport of [true, false] as const) { await expect(page.locator('.metadata-view')).toMatchAriaSnapshot(` - 'link "chore(html): make this test look nice"' - text: /^William on/ + - link /^[a-f0-9]{7}$/ + - text: 'foo : value1 bar : {"prop":"value2"} baz : ["value3",123]' + `); + }); + + test('should include metadata with populateGitInfo on GHA', async ({ runInlineTest, writeFiles, showReport, page }) => { + const files = { + 'uncommitted.txt': `uncommitted file`, + 'playwright.config.ts': ` + export default { + populateGitInfo: true, + metadata: { foo: 'value1', bar: { prop: 'value2' }, baz: ['value3', 123] } + }; + `, + 'example.spec.ts': ` + import { test, expect } from '@playwright/test'; + test('sample', async ({}) => { expect(2).toBe(2); }); + `, + }; + const baseDir = await writeFiles(files); + + const execGit = async (args: string[]) => { + const { code, stdout, stderr } = await spawnAsync('git', args, { stdio: 'pipe', cwd: baseDir }); + if (!!code) + throw new Error(`Non-zero exit of:\n$ git ${args.join(' ')}\nConsole:\nstdout:\n${stdout}\n\nstderr:\n${stderr}\n\n`); + return; + }; + + await execGit(['init']); + await execGit(['config', '--local', 'user.email', 'shakespeare@example.local']); + await execGit(['config', '--local', 'user.name', 'William']); + await execGit(['add', 'playwright.config.ts']); + await execGit(['commit', '-m', 'init']); + await execGit(['add', '*.ts']); + await execGit(['commit', '-m', 'chore(html): make this test look nice']); + + const eventPath = path.join(baseDir, 'event.json'); + await fs.promises.writeFile(eventPath, JSON.stringify({ + pull_request: { + title: 'My PR', + number: 42, + base: { ref: 'main' }, + }, + })); + + const result = await runInlineTest(files, { reporter: 'dot,html' }, { + PLAYWRIGHT_HTML_OPEN: 'never', + GITHUB_REPOSITORY: 'microsoft/playwright-example-for-test', + GITHUB_RUN_ID: 'example-run-id', + GITHUB_SERVER_URL: 'https://playwright.dev', + GITHUB_SHA: 'example-sha', + GITHUB_EVENT_PATH: eventPath, + }); + + await showReport(); + + expect(result.exitCode).toBe(0); + await page.getByRole('button', { name: 'Metadata' }).click(); + await expect(page.locator('.metadata-view')).toMatchAriaSnapshot(` + - 'link "My PR"' + - text: /^William on/ - link "Logs" - link "Pull Request" - - link /^[a-f0-9]{7}$/ - text: 'foo : value1 bar : {"prop":"value2"} baz : ["value3",123]' `); });