@alphabin/trx
Version:
TRX reporter for Playwright tests with Azure Blob Storage upload support
263 lines (262 loc) • 10.9 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GitCollector = void 0;
const simple_git_1 = __importDefault(require("simple-git"));
const exec_util_1 = require("../utils/exec.util");
const fileSystem_util_1 = require("../utils/fileSystem.util");
const logger_util_1 = __importDefault(require("../utils/logger.util"));
const fs_1 = require("fs");
/**
* Collector for Git metadata
*/
class GitCollector {
constructor(rootDir = process.cwd()) {
this.rootDir = rootDir;
}
/**
* Collects Git metadata
*/
async collect() {
try {
const gitRoot = (0, fileSystem_util_1.findGitRoot)(this.rootDir);
if (!gitRoot) {
logger_util_1.default.debug('Not a git repository');
return {};
}
const git = (0, simple_git_1.default)(gitRoot);
if (!(await git.checkIsRepo())) {
logger_util_1.default.debug('Not a git repository');
return {};
}
// Collect basic git information
const [branch, commitInfo, remoteInfo] = await Promise.all([
this.getBranch(git),
this.getCommitInfo(git),
this.getRepositoryInfo(git)
]);
// Collect PR information if available
const prInfo = await this.getPRInfo();
const metadata = {
branch,
commit: commitInfo,
repository: remoteInfo
};
if (prInfo) {
metadata.pr = prInfo;
}
return metadata;
}
catch (error) {
logger_util_1.default.error('Failed to collect Git metadata', error);
return {};
}
}
/**
* Gets the current branch name
*/
async getBranch(git) {
try {
// First try environment variables (CI systems often set these)
const ciBranch = (0, exec_util_1.getEnvVar)('GITHUB_HEAD_REF') ||
(0, exec_util_1.getEnvVar)('GITHUB_REF_NAME') ||
(0, exec_util_1.getEnvVar)('CIRCLE_BRANCH') ||
(0, exec_util_1.getEnvVar)('BITBUCKET_BRANCH') ||
(0, exec_util_1.getEnvVar)('GITLAB_CI') && (0, exec_util_1.getEnvVar)('CI_COMMIT_REF_NAME') ||
(0, exec_util_1.getEnvVar)('TRAVIS_PULL_REQUEST_BRANCH') ||
(0, exec_util_1.getEnvVar)('TRAVIS_BRANCH');
if (ciBranch) {
return ciBranch;
}
// Fall back to git command
const { current } = await git.branch();
return current;
}
catch (error) {
logger_util_1.default.debug('Failed to get branch name', error);
return 'unknown';
}
}
/**
* Gets information about the current commit
*/
async getCommitInfo(git) {
try {
// Try environment variables first
const ciCommitHash = (0, exec_util_1.getEnvVar)('GITHUB_SHA') ||
(0, exec_util_1.getEnvVar)('CIRCLE_SHA1') ||
(0, exec_util_1.getEnvVar)('BITBUCKET_COMMIT') ||
(0, exec_util_1.getEnvVar)('GITLAB_CI') && (0, exec_util_1.getEnvVar)('CI_COMMIT_SHA') ||
(0, exec_util_1.getEnvVar)('TRAVIS_COMMIT');
if (ciCommitHash) {
// If we have a commit hash from CI, get other info using git show
const commitMessage = await (0, exec_util_1.execCommand)(`git show -s --format=%B ${ciCommitHash}`);
const authorName = await (0, exec_util_1.execCommand)(`git show -s --format=%an ${ciCommitHash}`);
const authorEmail = await (0, exec_util_1.execCommand)(`git show -s --format=%ae ${ciCommitHash}`);
const commitDate = await (0, exec_util_1.execCommand)(`git show -s --format=%aI ${ciCommitHash}`);
return {
hash: ciCommitHash,
message: commitMessage,
author: authorName,
email: authorEmail,
timestamp: commitDate
};
}
// Fall back to using simpleGit
const log = await git.log({ maxCount: 1 });
const latestCommit = log.latest;
if (!latestCommit) {
throw new Error('No commits found');
}
return {
hash: latestCommit.hash,
message: latestCommit.message,
author: latestCommit.author_name,
email: latestCommit.author_email,
timestamp: latestCommit.date
};
}
catch (error) {
logger_util_1.default.debug('Failed to get commit info', error);
return {
hash: 'unknown',
message: '',
author: '',
email: '',
timestamp: new Date().toISOString()
};
}
}
/**
* Gets information about the git repository
*/
async getRepositoryInfo(git) {
try {
// Try environment variables first
if ((0, exec_util_1.getEnvVar)('GITHUB_REPOSITORY')) {
const repoFullName = (0, exec_util_1.getEnvVar)('GITHUB_REPOSITORY') || '';
return {
name: repoFullName.split('/').pop() || 'unknown',
url: `https://github.com/${repoFullName}`
};
}
if ((0, exec_util_1.getEnvVar)('CIRCLE_PROJECT_USERNAME') && (0, exec_util_1.getEnvVar)('CIRCLE_PROJECT_REPONAME')) {
const username = (0, exec_util_1.getEnvVar)('CIRCLE_PROJECT_USERNAME') || '';
const reponame = (0, exec_util_1.getEnvVar)('CIRCLE_PROJECT_REPONAME') || '';
return {
name: reponame,
url: `https://github.com/${username}/${reponame}`
};
}
// Fall back to git remote
const remotes = await git.getRemotes(true);
const origin = remotes.find((remote) => remote.name === 'origin');
if (!origin) {
throw new Error('No origin remote found');
}
const url = origin.refs.fetch;
let name = 'unknown';
// Extract repo name from URL
const match = url.match(/\/([^\/]+?)(\.git)?$/);
if (match) {
name = match[1];
}
// Convert SSH URLs to HTTPS URLs for better presentation
let httpUrl = url;
if (url.startsWith('git@')) {
httpUrl = url
.replace(/^git@([^:]+):/, 'https://$1/')
.replace(/\.git$/, '');
}
return {
name,
url: httpUrl
};
}
catch (error) {
logger_util_1.default.debug('Failed to get repository info', error);
return {
name: 'unknown',
url: ''
};
}
}
/**
* Gets information about the current pull request, if available
*/
async getPRInfo() {
try {
// GitHub Actions: use event payload for PR details and status
if ((0, exec_util_1.getEnvVar)('GITHUB_EVENT_NAME') === 'pull_request') {
const prNumber = (0, exec_util_1.getEnvVar)('GITHUB_REF_NAME')?.replace('refs/pull/', '').replace('/merge', '') ||
(0, exec_util_1.getEnvVar)('GITHUB_REF')?.replace('refs/pull/', '').replace('/merge', '');
if (prNumber && (0, exec_util_1.getEnvVar)('GITHUB_EVENT_PATH')) {
const eventPath = (0, exec_util_1.getEnvVar)('GITHUB_EVENT_PATH');
const payload = JSON.parse(await fs_1.promises.readFile(eventPath, 'utf-8'));
const prData = payload.pull_request;
let status = prData.state;
if (prData.draft) {
status = 'draft';
}
else if (prData.merged) {
status = 'merged';
}
return {
id: prNumber,
title: prData.title,
url: prData.html_url,
status
};
}
else if (prNumber && (0, exec_util_1.getEnvVar)('GITHUB_REPOSITORY')) {
return {
id: prNumber,
title: (0, exec_util_1.getEnvVar)('GITHUB_PULL_REQUEST_TITLE') || `Pull Request #${prNumber}`,
url: `https://github.com/${(0, exec_util_1.getEnvVar)('GITHUB_REPOSITORY')}/pull/${prNumber}`,
status: 'open'
};
}
}
// CircleCI
if ((0, exec_util_1.getEnvVar)('CIRCLE_PULL_REQUEST')) {
const url = (0, exec_util_1.getEnvVar)('CIRCLE_PULL_REQUEST') || '';
const prNumber = url.split('/').pop();
return {
id: `PR-${prNumber}`,
title: `Pull Request #${prNumber}`,
url
};
}
// Travis CI
if ((0, exec_util_1.getEnvVar)('TRAVIS_PULL_REQUEST') && (0, exec_util_1.getEnvVar)('TRAVIS_PULL_REQUEST') !== 'false') {
const prNumber = (0, exec_util_1.getEnvVar)('TRAVIS_PULL_REQUEST');
const repo = (0, exec_util_1.getEnvVar)('TRAVIS_REPO_SLUG');
return {
id: `PR-${prNumber}`,
title: `Pull Request #${prNumber}`,
url: `https://github.com/${repo}/pull/${prNumber}`
};
}
// GitLab CI
if ((0, exec_util_1.getEnvVar)('CI_MERGE_REQUEST_IID')) {
const mrId = (0, exec_util_1.getEnvVar)('CI_MERGE_REQUEST_IID');
const mrTitle = (0, exec_util_1.getEnvVar)('CI_MERGE_REQUEST_TITLE');
const mrUrl = (0, exec_util_1.getEnvVar)('CI_MERGE_REQUEST_PROJECT_URL');
return {
id: `MR-${mrId}`,
title: mrTitle || `Merge Request #${mrId}`,
url: `${mrUrl}/-/merge_requests/${mrId}`
};
}
return undefined;
}
catch (error) {
logger_util_1.default.debug('Failed to get PR info', error);
return undefined;
}
}
}
exports.GitCollector = GitCollector;
exports.default = GitCollector;