UNPKG

trigger.dev

Version:

A Command-Line Interface for Trigger.dev projects

220 lines • 7.84 kB
import fs from "fs/promises"; import { join } from "path"; import ini from "ini"; import git from "git-last-commit"; import { x } from "tinyexec"; export async function createGitMeta(directory) { if (isGitHubApp()) { return getGitHubAppMeta(); } if (isGitHubActions()) { return getGitHubActionsMeta(); } // Fall back to git commands for local development const remoteUrl = await getOriginUrl(join(directory, ".git/config")); const [commitResult, dirtyResult] = await Promise.allSettled([ getLastCommit(directory), isDirty(directory), ]); if (commitResult.status === "rejected") { return; } if (dirtyResult.status === "rejected") { return; } const dirty = dirtyResult.value; const commit = commitResult.value; return { source: "local", remoteUrl: remoteUrl ?? undefined, commitAuthorName: commit.author.name, commitMessage: commit.subject, commitRef: commit.branch, commitSha: commit.hash, dirty, }; } function getLastCommit(directory) { return new Promise((resolve, reject) => { git.getLastCommit((err, commit) => { if (err) { return reject(err); } resolve(commit); }, { dst: directory }); }); } async function isDirty(directory) { try { const result = await x("git", ["--no-optional-locks", "status", "-s"], { nodeOptions: { cwd: directory, }, }); // Example output (when dirty): // M ../fs-detectors/src/index.ts return result.stdout.trim().length > 0; } catch (error) { throw error; } } async function parseGitConfig(configPath) { try { return ini.parse(await fs.readFile(configPath, "utf8")); } catch (err) { return; } } function pluckOriginUrl(gitConfig) { // Assuming "origin" is the remote url that the user would want to use return gitConfig['remote "origin"']?.url; } async function getOriginUrl(configPath) { const gitConfig = await parseGitConfig(configPath); if (!gitConfig) { return null; } const originUrl = pluckOriginUrl(gitConfig); if (originUrl) { return originUrl; } return null; } function errorToString(err) { return err instanceof Error ? err.message : String(err); } export function isGitHubActions() { // GH Actions CI sets these env variables return (process.env.GITHUB_ACTIONS === "true" && process.env.GITHUB_SHA !== undefined && process.env.GITHUB_REF !== undefined); } async function getGitHubActionsMeta() { const remoteUrl = process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY ? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}.git` : undefined; // GITHUB_SHA and GITHUB_REF are both set in GH Actions CI const githubSha = process.env.GITHUB_SHA ?? ""; const githubRef = process.env.GITHUB_REF ?? ""; // For push events, GITHUB_REF is fully qualified, e.g., "refs/heads/main" let commitRef = githubRef.replace(/^refs\/(heads|tags)\//, ""); let commitMessage; let commitSha = githubSha; let pullRequestNumber; let pullRequestTitle; let pullRequestState; if (process.env.GITHUB_EVENT_PATH) { try { const eventData = JSON.parse(await fs.readFile(process.env.GITHUB_EVENT_PATH, "utf8")); if (process.env.GITHUB_EVENT_NAME === "push") { commitMessage = eventData.head_commit?.message; } else if (process.env.GITHUB_EVENT_NAME === "pull_request") { // For PRs, use the head commit info pullRequestTitle = eventData.pull_request?.title; commitRef = eventData.pull_request?.head?.ref; pullRequestNumber = eventData.pull_request?.number; commitSha = eventData.pull_request?.head?.sha; pullRequestState = eventData.pull_request?.state; // Check if PR was merged if (pullRequestState === "closed" && eventData.pull_request?.merged === true) { pullRequestState = "merged"; } await x("git", ["status"], { nodeOptions: { cwd: process.cwd(), }, }).then((result) => console.debug(result.stdout)); commitMessage = await getCommitMessage(process.cwd(), commitSha, pullRequestNumber); } } catch (error) { console.debug("Failed to parse GitHub event payload:", errorToString(error)); } } else { console.debug("No GITHUB_EVENT_PATH found"); } return { provider: "github", source: "github_actions", remoteUrl, commitSha, commitRef, // In CI, the workspace is always clean dirty: false, // These fields might not be available in all GitHub Actions contexts commitAuthorName: process.env.GITHUB_ACTOR, commitMessage, pullRequestNumber: pullRequestNumber ?? (process.env.GITHUB_PULL_REQUEST_NUMBER ? parseInt(process.env.GITHUB_PULL_REQUEST_NUMBER) : undefined), pullRequestTitle, pullRequestState, }; } function isGitHubApp() { // we set this env variable in our build server return process.env.TRIGGER_GITHUB_APP === "true"; } function getGitHubAppMeta() { return { provider: "github", source: "trigger_github_app", remoteUrl: process.env.GITHUB_REPOSITORY_URL, commitSha: process.env.GITHUB_HEAD_COMMIT_SHA, commitRef: process.env.GITHUB_REF?.replace(/^refs\/(heads|tags)\//, ""), commitMessage: process.env.GITHUB_HEAD_COMMIT_MESSAGE, commitAuthorName: process.env.GITHUB_HEAD_COMMIT_AUTHOR_NAME, pullRequestNumber: process.env.GITHUB_PULL_REQUEST_NUMBER ? parseInt(process.env.GITHUB_PULL_REQUEST_NUMBER) : undefined, pullRequestTitle: process.env.GITHUB_PULL_REQUEST_TITLE, pullRequestState: process.env.GITHUB_PULL_REQUEST_STATE, // the workspace is always clean as we clone the repo in the build server dirty: false, ghUsername: process.env.GITHUB_USERNAME, ghUserAvatarUrl: process.env.GITHUB_USER_AVATAR_URL, }; } async function getCommitMessage(directory, sha, prNumber) { try { // First try to fetch the specific commit await x("git", ["fetch", "origin", sha], { nodeOptions: { cwd: directory, }, }); // Try to get the commit message const result = await x("git", ["log", "-1", "--format=%B", sha], { nodeOptions: { cwd: directory, }, }); const message = result.stdout.trim(); if (!message && prNumber) { // If that didn't work, try fetching the PR branch const branchResult = await x("git", ["fetch", "origin", `pull/${prNumber}/head:pr-${prNumber}`], { nodeOptions: { cwd: directory, }, }); // Try again with the fetched branch const branchCommitResult = await x("git", ["log", "-1", "--format=%B", `pr-${prNumber}`], { nodeOptions: { cwd: directory, }, }); return branchCommitResult.stdout.trim(); } return message; } catch (error) { console.debug("Error getting commit message:", errorToString(error)); return undefined; } } //# sourceMappingURL=gitMeta.js.map