Skip to content

Commit a5d7760

Browse files
committed
wip - reworking anon project id
1 parent 30273db commit a5d7760

File tree

1 file changed

+53
-13
lines changed

1 file changed

+53
-13
lines changed

packages/varlock/src/cli/helpers/telemetry.ts

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ function loadVarlockConfig() {
8484
const userConfigStr = readFileSync(userVarlockConfigFilePath, 'utf-8');
8585
userVarlockConfig = userConfigStr.trim() ? JSON.parse(userConfigStr) : undefined;
8686
} catch (err) {
87-
// file does not exist (we jsut do this to avoid doing an extra step to check)
87+
// file does not exist (we just do this to avoid doing an extra step to check)
8888
if (err instanceof Error && 'code' in err && err.code === 'ENOENT') {
8989
debug(`User varlock config file not found - ${userVarlockConfigFilePath}`);
9090
} else if (err instanceof SyntaxError) {
@@ -102,7 +102,7 @@ function loadVarlockConfig() {
102102
const projectConfigStr = readFileSync(projectVarlockConfigPath, 'utf-8');
103103
projectVarlockConfig = projectConfigStr.trim() ? JSON.parse(projectConfigStr) : undefined;
104104
} catch (err) {
105-
// file does not exist (we jsut do this to avoid doing an extra step to check)
105+
// file does not exist (we just do this to avoid doing an extra step to check)
106106
if (err instanceof Error && 'code' in err && err.code === 'ENOENT') {
107107
debug(`Project varlock config file not found - ${projectVarlockConfigPath}`);
108108
} else if (err instanceof SyntaxError) {
@@ -216,31 +216,71 @@ function anonymizeValue(payload: BinaryLike): string {
216216
return hash.digest('hex');
217217
}
218218

219-
function getProjectGitRemoteUrl(): string | undefined {
219+
220+
// known CI providers which have owner/repo available as env vars
221+
// we should order these by popularity (most popular first)
222+
const OWNER_REPO_CI_ENV_VARS = [
223+
'GITHUB_ACTION_REPOSITORY', // github actions
224+
['NEXT_PUBLIC_VERCEL_GIT_REPO_OWNER', 'NEXT_PUBLIC_VERCEL_GIT_REPO_SLUG'], // vercel
225+
];
226+
227+
function getProjectOwnerRepoName(): string | undefined {
228+
// check all known providers which set env vars that have this permission (only for CI)
229+
if (isCI) {
230+
for (const envVarNames of OWNER_REPO_CI_ENV_VARS) {
231+
if (Array.isArray(envVarNames)) {
232+
if (process.env[envVarNames[0]]) {
233+
return `${process.env[envVarNames[0]]}/${process.env[envVarNames[1]]}`;
234+
}
235+
} else {
236+
if (process.env[envVarNames]) {
237+
return process.env[envVarNames];
238+
}
239+
}
240+
}
241+
}
242+
243+
// otherwise, we'll try to extract the owner/repo name from the .git/config in remote url
220244
findProjectDirs(); // finds the git folder
221245
if (!_gitDirPath) return undefined;
246+
let remoteUrl: string | undefined;
222247
try {
223248
const gitConfigContents = readFileSync(join(_gitDirPath, 'config'), 'utf-8');
224249
// first look for upstream
225250
const remoteUpstreamPos = gitConfigContents.indexOf('[remote "upstream"]');
226251
if (remoteUpstreamPos !== -1) {
227-
const remoteUpstreamUrl = gitConfigContents.slice(remoteUpstreamPos).match(/url = (.+)/)?.[1];
228-
return remoteUpstreamUrl;
252+
remoteUrl = gitConfigContents.slice(remoteUpstreamPos).match(/url = (.+)/)?.[1];
253+
} else {
254+
// otherwise fallback to origin
255+
const remoteOriginPos = gitConfigContents.indexOf('[remote "origin"]');
256+
if (remoteOriginPos === -1) return undefined;
257+
remoteUrl = gitConfigContents.slice(remoteOriginPos).match(/url = (.+)/)?.[1];
229258
}
230-
// otherwise fallback to origin
231-
const remoteOriginPos = gitConfigContents.indexOf('[remote "origin"]');
232-
if (remoteOriginPos === -1) return undefined;
233-
const remoteOriginUrl = gitConfigContents.slice(remoteOriginPos).match(/url = (.+)/)?.[1];
234-
return remoteOriginUrl;
235259
} catch (err) {
236260
return undefined;
237261
}
262+
if (!remoteUrl) return undefined;
263+
264+
265+
remoteUrl = remoteUrl
266+
.replace(/\?.*$/, '') // remove query params
267+
.replace(/\.git$/, ''); // remove git suffix
268+
269+
const protocol = remoteUrl.includes('://') ? remoteUrl.split('://')[0].toLowerCase() : undefined;
270+
if (protocol && ['https', 'http', 'git', 'ssh'].includes(protocol.toLowerCase())) {
271+
// ex: https://github.com/owner/repo.git
272+
return remoteUrl.split('/').slice(-2).join('/').replace(/\.git$/, '');
273+
} else if (remoteUrl?.startsWith('git@')) {
274+
// ex: git@github.com:owner/repo.git
275+
return remoteUrl.split(':')[1]?.replace(/\.git$/, '');
276+
}
277+
return undefined;
238278
}
239279
function getAnonymousProjectId() {
240280
// we want a project ID tied to the git repo, so we can group telemetry data by project
241-
// we could use the first commit hash, but this is more costly to compute, as we either need to rely
242-
// on the git cli and execSync, or we need to parse the git objects directly
243-
// so for now, we'll use the git remote URL (upstream if it exists, or origin)
281+
// Astro uses first commit hash, but it's costly to compute needing git cli and execSync, or parsing the git objects directly
282+
// so we will try to determing the git owner/repo name from .git/config or env vars
283+
// and then anonymize it
244284
const gitRemoteUrl = getProjectGitRemoteUrl();
245285
if (!gitRemoteUrl) return null;
246286
return anonymizeValue(gitRemoteUrl);

0 commit comments

Comments
 (0)