diff --git a/packages/gatsby-telemetry/src/repository-id.ts b/packages/gatsby-telemetry/src/repository-id.ts index 703888866ca3b..3e1af93dfc20d 100644 --- a/packages/gatsby-telemetry/src/repository-id.ts +++ b/packages/gatsby-telemetry/src/repository-id.ts @@ -1,8 +1,11 @@ -import { createHash } from "crypto" +import path from "path" import { basename } from "path" +import { createHash } from "crypto" import { execSync } from "child_process" -import gitUp from "git-up" +import { readdirSync, readFileSync } from "fs" +import gitUp from "git-up" +import { getCIName } from "gatsby-core-utils" // there are no types for git-up, so we create our own // based on https://github.com/IonicaBizau/git-up/blob/60e6a4ff93d50360bbb80953bfab2f82d3418900/lib/index.js#L8-L28 const typedGitUp = gitUp as ( @@ -31,7 +34,8 @@ export const getRepoMetadata = (url: string): IRepositoryData | null => { const res: IRepositoryData = { provider: hash(provider) } const userAndRepo = pathname.split(`/`) - if (userAndRepo.length == 3) { + + if (userAndRepo.length >= 3) { res.owner = hash(userAndRepo[1]) res.name = hash(userAndRepo[2].replace(`.git`, ``)) } @@ -83,8 +87,48 @@ const getRepositoryFromNetlifyEnv = (): IRepositoryId | null => { return null } +function getRepositoryFromHerokuEnv(): IRepositoryId | null { + if (getCIName() !== `Heroku`) { + return null + } + + // Parse repository metadata from /proc/*/environ. This is a naive glob approach to only + // look pids in procfs. + const proc = readdirSync(`/proc`).filter(dir => Number.isFinite(Number(dir))) + const len = proc.length + for (let i = 0; i < len; i++) { + const dir = proc[i] + try { + // Piggyback on internal datastructures for control processes to see the git repo info + const environData = readFileSync(path.join(`/proc`, dir, `environ`)) + ?.toString(`utf8`) + ?.split(/\0/) + ?.find(e => e.indexOf(`RECEIVE_DATA`) >= 0) + ?.replace(`RECEIVE_DATA=`, ``) + + if (!environData) { + continue + } + const data = JSON.parse(environData) + const url = data?.push_metadata?.source_url + if (url) { + return { + repositoryId: `heroku:${hash(url)}`, + repositoryData: getRepoMetadata(url), + } + } + } catch (e) { + // ignore + } + } + return null +} + export const getRepositoryId = (): IRepositoryId => { - const gitRepo = getGitRemoteWithGit() || getRepositoryFromNetlifyEnv() + const gitRepo = + getGitRemoteWithGit() || + getRepositoryFromNetlifyEnv() || + getRepositoryFromHerokuEnv() if (gitRepo) { return gitRepo } else { diff --git a/packages/gatsby-telemetry/src/telemetry.ts b/packages/gatsby-telemetry/src/telemetry.ts index e689f2f7a83b5..7f8d68170b4cc 100644 --- a/packages/gatsby-telemetry/src/telemetry.ts +++ b/packages/gatsby-telemetry/src/telemetry.ts @@ -1,6 +1,5 @@ import uuidV4 from "uuid/v4" import { isCI, getCIName } from "gatsby-core-utils" - import { getRepositoryId as _getRepositoryId, IRepositoryId,