UNPKG

@alphabin/trx

Version:

TRX reporter for Playwright tests with Azure Blob Storage upload support

263 lines (262 loc) 10.9 kB
"use strict"; 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;