fix(html-report): only invoke git once (#13165)

This commit is contained in:
Pavel Feldman 2022-03-29 14:49:58 -08:00 committed by GitHub
parent eb09306db2
commit 5e17ed137b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 13 additions and 26 deletions

View file

@ -104,9 +104,6 @@ const MetadataView: React.FC<Metadata> = metadata => {
icon='externalLink' icon='externalLink'
/> />
} }
{metadata['revision.localPendingChanges'] &&
<p style={{ fontStyle: 'italic', color: 'var(--color-fg-subtle)' }}>This report was generated with <strong>uncommitted changes</strong>.</p>
}
{metadata['generatedAt'] && {metadata['generatedAt'] &&
<p style={{ fontStyle: 'italic', color: 'var(--color-fg-subtle)' }}>Report generated on {Intl.DateTimeFormat(undefined, { dateStyle: 'full', timeStyle: 'long' }).format(metadata['generatedAt'])}</p> <p style={{ fontStyle: 'italic', color: 'var(--color-fg-subtle)' }}>Report generated on {Intl.DateTimeFormat(undefined, { dateStyle: 'full', timeStyle: 'long' }).format(metadata['generatedAt'])}</p>
} }

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * 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 GIT_OPERATIONS_TIMEOUT_MS = 1500;
const kContentTypePlainText = 'text/plain'; const kContentTypePlainText = 'text/plain';
@ -26,24 +26,16 @@ export interface Attachment {
} }
export const gitStatusFromCLI = async (gitDir: string): Promise<Attachment[]> => { export const gitStatusFromCLI = async (gitDir: string): Promise<Attachment[]> => {
const execGit = async (args: string[]) => { const separator = `:${createGuid().slice(0, 4)}:`;
const { code, stdout } = await spawnAsync('git', args, { stdio: 'pipe', cwd: gitDir, timeout: GIT_OPERATIONS_TIMEOUT_MS }); const { code, stdout } = await spawnAsync(
if (!!code) 'git',
throw new Error('Exited with non-zero code.'); ['show', '-s', `--format=%H${separator}%s${separator}%an${separator}%ae${separator}%ct`, 'HEAD'],
{ stdio: 'pipe', cwd: gitDir, timeout: GIT_OPERATIONS_TIMEOUT_MS }
return stdout.trim(); );
}; if (code)
return [];
await execGit(['--help']).catch(() => { throw new Error('git --help failed; is git installed?');}); const showOutput = stdout.trim();
const [ status, sha, subject, authorName, authorEmail, rawTimestamp ] = await Promise.all([ const [sha, subject, authorName, authorEmail, rawTimestamp] = showOutput.split(separator);
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');});
let timestamp: number = Number.parseInt(rawTimestamp, 10); let timestamp: number = Number.parseInt(rawTimestamp, 10);
timestamp = Number.isInteger(timestamp) ? timestamp * 1000 : 0; timestamp = Number.isInteger(timestamp) ? timestamp * 1000 : 0;
@ -53,7 +45,6 @@ export const gitStatusFromCLI = async (gitDir: string): Promise<Attachment[]> =>
{ name: 'revision.email', body: Buffer.from(authorEmail), contentType: kContentTypePlainText }, { name: 'revision.email', body: Buffer.from(authorEmail), contentType: kContentTypePlainText },
{ name: 'revision.subject', body: Buffer.from(subject), contentType: kContentTypePlainText }, { name: 'revision.subject', body: Buffer.from(subject), contentType: kContentTypePlainText },
{ name: 'revision.timestamp', body: Buffer.from(JSON.stringify(timestamp)), contentType: kContentTypeJSON }, { name: 'revision.timestamp', body: Buffer.from(JSON.stringify(timestamp)), contentType: kContentTypeJSON },
{ name: 'revision.localPendingChanges', body: Buffer.from(!!status + ''), contentType: kContentTypePlainText },
]; ];
}; };

View file

@ -21,7 +21,7 @@ import * as ci from '@playwright/test/lib/ci';
async function globalSetup(config: FullConfig) { async function globalSetup(config: FullConfig) {
config.attachments = [ config.attachments = [
...await ci.generationTimestamp(), ...await ci.generationTimestamp(),
...await ci.gitStatusFromCLI(config.rootDir).catch(() => []), ...await ci.gitStatusFromCLI(config.rootDir),
...await ci.githubEnv(), ...await ci.githubEnv(),
// In the future, we would add some additional plugins like: // In the future, we would add some additional plugins like:
// ...await ci.azurePipelinePlugin(), // ...await ci.azurePipelinePlugin(),

View file

@ -679,7 +679,7 @@ test('should include metadata', async ({ runInlineTest, showReport, page }) => {
async function globalSetup(config: FullConfig) { async function globalSetup(config: FullConfig) {
config.attachments = [ config.attachments = [
...await ci.generationTimestamp(), ...await ci.generationTimestamp(),
...await ci.gitStatusFromCLI(config.rootDir).catch(() => []), ...await ci.gitStatusFromCLI(config.rootDir),
...await ci.githubEnv(), ...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('William');
await expect.soft(metadata).toContainText('shakespeare@example.local'); 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.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/); await expect.soft(metadata.locator('text=Report generated on')).toContainText(/AM|PM/);
}); });