= metadata => {
icon='externalLink'
/>
}
- {metadata['revision.localPendingChanges'] &&
- This report was generated with uncommitted changes.
- }
{metadata['generatedAt'] &&
Report generated on {Intl.DateTimeFormat(undefined, { dateStyle: 'full', timeStyle: 'long' }).format(metadata['generatedAt'])}
}
diff --git a/packages/playwright-test/src/ci.ts b/packages/playwright-test/src/ci.ts
index fb0e10ca1b..46a27dd7a6 100644
--- a/packages/playwright-test/src/ci.ts
+++ b/packages/playwright-test/src/ci.ts
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { spawnAsync } from 'playwright-core/lib/utils/utils';
+import { createGuid, spawnAsync } from 'playwright-core/lib/utils/utils';
const GIT_OPERATIONS_TIMEOUT_MS = 1500;
const kContentTypePlainText = 'text/plain';
@@ -26,24 +26,16 @@ export interface Attachment {
}
export const gitStatusFromCLI = async (gitDir: string): Promise => {
- const execGit = async (args: string[]) => {
- const { code, stdout } = await spawnAsync('git', args, { stdio: 'pipe', cwd: gitDir, timeout: GIT_OPERATIONS_TIMEOUT_MS });
- if (!!code)
- throw new Error('Exited with non-zero code.');
-
- return stdout.trim();
- };
-
- await execGit(['--help']).catch(() => { throw new Error('git --help failed; is git installed?');});
- const [ status, sha, subject, authorName, authorEmail, rawTimestamp ] = await Promise.all([
- execGit(['status', '--porcelain=v1']),
- execGit(['rev-parse', 'HEAD']),
- execGit(['show', '-s', '--format=%s', 'HEAD']),
- execGit(['show', '-s', '--format=%an', 'HEAD']),
- execGit(['show', '-s', '--format=%ae', 'HEAD']),
- execGit(['show', '-s', '--format=%ct', 'HEAD']),
- ]).catch(() => { throw new Error('one or more git commands failed');});
-
+ const separator = `:${createGuid().slice(0, 4)}:`;
+ const { code, stdout } = await spawnAsync(
+ 'git',
+ ['show', '-s', `--format=%H${separator}%s${separator}%an${separator}%ae${separator}%ct`, 'HEAD'],
+ { stdio: 'pipe', cwd: gitDir, timeout: GIT_OPERATIONS_TIMEOUT_MS }
+ );
+ if (code)
+ return [];
+ const showOutput = stdout.trim();
+ const [sha, subject, authorName, authorEmail, rawTimestamp] = showOutput.split(separator);
let timestamp: number = Number.parseInt(rawTimestamp, 10);
timestamp = Number.isInteger(timestamp) ? timestamp * 1000 : 0;
@@ -53,7 +45,6 @@ export const gitStatusFromCLI = async (gitDir: string): Promise =>
{ name: 'revision.email', body: Buffer.from(authorEmail), contentType: kContentTypePlainText },
{ name: 'revision.subject', body: Buffer.from(subject), contentType: kContentTypePlainText },
{ name: 'revision.timestamp', body: Buffer.from(JSON.stringify(timestamp)), contentType: kContentTypeJSON },
- { name: 'revision.localPendingChanges', body: Buffer.from(!!status + ''), contentType: kContentTypePlainText },
];
};
diff --git a/tests/config/globalSetup.ts b/tests/config/globalSetup.ts
index b148fefa5d..d21f563975 100644
--- a/tests/config/globalSetup.ts
+++ b/tests/config/globalSetup.ts
@@ -21,7 +21,7 @@ import * as ci from '@playwright/test/lib/ci';
async function globalSetup(config: FullConfig) {
config.attachments = [
...await ci.generationTimestamp(),
- ...await ci.gitStatusFromCLI(config.rootDir).catch(() => []),
+ ...await ci.gitStatusFromCLI(config.rootDir),
...await ci.githubEnv(),
// In the future, we would add some additional plugins like:
// ...await ci.azurePipelinePlugin(),
diff --git a/tests/playwright-test/reporter-html.spec.ts b/tests/playwright-test/reporter-html.spec.ts
index d73453b5c7..5c4e6fe6bd 100644
--- a/tests/playwright-test/reporter-html.spec.ts
+++ b/tests/playwright-test/reporter-html.spec.ts
@@ -679,7 +679,7 @@ test('should include metadata', async ({ runInlineTest, showReport, page }) => {
async function globalSetup(config: FullConfig) {
config.attachments = [
...await ci.generationTimestamp(),
- ...await ci.gitStatusFromCLI(config.rootDir).catch(() => []),
+ ...await ci.gitStatusFromCLI(config.rootDir),
...await ci.githubEnv(),
];
};
@@ -711,6 +711,5 @@ test('should include metadata', async ({ runInlineTest, showReport, page }) => {
await expect.soft(metadata).toContainText('William');
await expect.soft(metadata).toContainText('shakespeare@example.local');
await expect.soft(metadata.locator('text=CI/CD Logs')).toHaveAttribute('href', 'https://playwright.dev/microsoft/playwright-example-for-test/actions/runs/example-run-id');
- await expect.soft(metadata).toContainText('uncommitted changes');
await expect.soft(metadata.locator('text=Report generated on')).toContainText(/AM|PM/);
});