Skip to content

Commit 68b8496

Browse files
authored
chore: compiler observability (#1726)
* chore(compiler): observability * chore: add changeset * chore: fix tests
1 parent 3e91e1c commit 68b8496

File tree

11 files changed

+460
-22
lines changed

11 files changed

+460
-22
lines changed

.changeset/heavy-ants-boil.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@lingo.dev/compiler": patch
3+
"@lingo.dev/_compiler": patch
4+
"lingo.dev": patch
5+
---
6+
7+
Observability improvement

packages/cli/src/cli/utils/repository-id.spec.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,79 +20,79 @@ describe("getRepositoryId", () => {
2020
describe("CI environment variables", () => {
2121
it("should detect GitHub repository from GITHUB_REPOSITORY", () => {
2222
process.env.GITHUB_REPOSITORY = "owner/repo";
23-
expect(getRepositoryId()).toBe("github:owner/repo");
23+
expect(getRepositoryId()).toBe("github:owner/071ca222");
2424
});
2525

2626
it("should detect GitLab repository from CI_PROJECT_PATH", () => {
2727
process.env.CI_PROJECT_PATH = "namespace/project";
28-
expect(getRepositoryId()).toBe("gitlab:namespace/project");
28+
expect(getRepositoryId()).toBe("gitlab:namespace/244210e4");
2929
});
3030

3131
it("should detect Bitbucket repository from BITBUCKET_REPO_FULL_NAME", () => {
3232
process.env.BITBUCKET_REPO_FULL_NAME = "workspace/repo";
33-
expect(getRepositoryId()).toBe("bitbucket:workspace/repo");
33+
expect(getRepositoryId()).toBe("bitbucket:workspace/071ca222");
3434
});
3535

3636
it("should prioritize CI environment variables over git remote", () => {
3737
process.env.GITHUB_REPOSITORY = "owner/repo";
3838
vi.mocked(execSync).mockReturnValue(
3939
"git@gitlab.com:other/project.git" as any,
4040
);
41-
expect(getRepositoryId()).toBe("github:owner/repo");
41+
expect(getRepositoryId()).toBe("github:owner/071ca222");
4242
});
4343
});
4444

4545
describe("git remote URL parsing", () => {
4646
it("should parse GitHub SSH URL", () => {
4747
vi.mocked(execSync).mockReturnValue("git@github.com:owner/repo.git" as any);
48-
expect(getRepositoryId()).toBe("github:owner/repo");
48+
expect(getRepositoryId()).toBe("github:owner/071ca222");
4949
});
5050

5151
it("should parse GitHub HTTPS URL", () => {
5252
vi.mocked(execSync).mockReturnValue(
5353
"https://github.com/owner/repo.git" as any,
5454
);
55-
expect(getRepositoryId()).toBe("github:owner/repo");
55+
expect(getRepositoryId()).toBe("github:owner/071ca222");
5656
});
5757

5858
it("should parse GitLab SSH URL", () => {
5959
vi.mocked(execSync).mockReturnValue(
6060
"git@gitlab.com:namespace/project.git" as any,
6161
);
62-
expect(getRepositoryId()).toBe("gitlab:namespace/project");
62+
expect(getRepositoryId()).toBe("gitlab:namespace/244210e4");
6363
});
6464

6565
it("should parse GitLab HTTPS URL", () => {
6666
vi.mocked(execSync).mockReturnValue(
6767
"https://gitlab.com/namespace/project.git" as any,
6868
);
69-
expect(getRepositoryId()).toBe("gitlab:namespace/project");
69+
expect(getRepositoryId()).toBe("gitlab:namespace/244210e4");
7070
});
7171

7272
it("should parse Bitbucket SSH URL", () => {
7373
vi.mocked(execSync).mockReturnValue(
7474
"git@bitbucket.org:workspace/repo.git" as any,
7575
);
76-
expect(getRepositoryId()).toBe("bitbucket:workspace/repo");
76+
expect(getRepositoryId()).toBe("bitbucket:workspace/071ca222");
7777
});
7878

7979
it("should parse Bitbucket HTTPS URL", () => {
8080
vi.mocked(execSync).mockReturnValue(
8181
"https://bitbucket.org/workspace/repo.git" as any,
8282
);
83-
expect(getRepositoryId()).toBe("bitbucket:workspace/repo");
83+
expect(getRepositoryId()).toBe("bitbucket:workspace/071ca222");
8484
});
8585

8686
it("should parse self-hosted git URL with generic prefix", () => {
8787
vi.mocked(execSync).mockReturnValue(
8888
"git@custom-git.company.com:team/project.git" as any,
8989
);
90-
expect(getRepositoryId()).toBe("git:team/project");
90+
expect(getRepositoryId()).toBe("git:team/244210e4");
9191
});
9292

9393
it("should handle URLs without .git extension", () => {
9494
vi.mocked(execSync).mockReturnValue("git@github.com:owner/repo" as any);
95-
expect(getRepositoryId()).toBe("github:owner/repo");
95+
expect(getRepositoryId()).toBe("github:owner/071ca222");
9696
});
9797

9898
it("should return null when git command fails", () => {

packages/cli/src/cli/utils/repository-id.ts

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,23 @@
11
import { execSync } from "child_process";
2+
import { createHash } from "crypto";
23

34
let cachedGitRepoId: string | null | undefined = undefined;
45

6+
function hashProjectName(fullPath: string): string {
7+
const parts = fullPath.split("/");
8+
if (parts.length !== 2) {
9+
return createHash("sha256").update(fullPath).digest("hex").slice(0, 8);
10+
}
11+
12+
const [org, project] = parts;
13+
const hashedProject = createHash("sha256")
14+
.update(project)
15+
.digest("hex")
16+
.slice(0, 8);
17+
18+
return `${org}/${hashedProject}`;
19+
}
20+
521
export function clearRepositoryIdCache(): void {
622
cachedGitRepoId = undefined;
723
}
@@ -17,15 +33,18 @@ export function getRepositoryId(): string | null {
1733

1834
function getCIRepositoryId(): string | null {
1935
if (process.env.GITHUB_REPOSITORY) {
20-
return `github:${process.env.GITHUB_REPOSITORY}`;
36+
const hashed = hashProjectName(process.env.GITHUB_REPOSITORY);
37+
return `github:${hashed}`;
2138
}
2239

2340
if (process.env.CI_PROJECT_PATH) {
24-
return `gitlab:${process.env.CI_PROJECT_PATH}`;
41+
const hashed = hashProjectName(process.env.CI_PROJECT_PATH);
42+
return `gitlab:${hashed}`;
2543
}
2644

2745
if (process.env.BITBUCKET_REPO_FULL_NAME) {
28-
return `bitbucket:${process.env.BITBUCKET_REPO_FULL_NAME}`;
46+
const hashed = hashProjectName(process.env.BITBUCKET_REPO_FULL_NAME);
47+
return `bitbucket:${hashed}`;
2948
}
3049

3150
return null;
@@ -74,9 +93,11 @@ function parseGitUrl(url: string): string | null {
7493

7594
if (!repoPath) return null;
7695

96+
const hashedPath = hashProjectName(repoPath);
97+
7798
if (platform) {
78-
return `${platform}:${repoPath}`;
99+
return `${platform}:${hashedPath}`;
79100
}
80101

81-
return `git:${repoPath}`;
102+
return `git:${hashedPath}`;
82103
}

packages/compiler/src/utils/repository-id.ts

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,23 @@
11
import { execSync } from "child_process";
2+
import { createHash } from "crypto";
23

34
let cachedGitRepoId: string | null | undefined = undefined;
45

6+
function hashProjectName(fullPath: string): string {
7+
const parts = fullPath.split("/");
8+
if (parts.length !== 2) {
9+
return createHash("sha256").update(fullPath).digest("hex").slice(0, 8);
10+
}
11+
12+
const [org, project] = parts;
13+
const hashedProject = createHash("sha256")
14+
.update(project)
15+
.digest("hex")
16+
.slice(0, 8);
17+
18+
return `${org}/${hashedProject}`;
19+
}
20+
521
export function getRepositoryId(): string | null {
622
const ciRepoId = getCIRepositoryId();
723
if (ciRepoId) return ciRepoId;
@@ -14,15 +30,18 @@ export function getRepositoryId(): string | null {
1430

1531
function getCIRepositoryId(): string | null {
1632
if (process.env.GITHUB_REPOSITORY) {
17-
return `github:${process.env.GITHUB_REPOSITORY}`;
33+
const hashed = hashProjectName(process.env.GITHUB_REPOSITORY);
34+
return `github:${hashed}`;
1835
}
1936

2037
if (process.env.CI_PROJECT_PATH) {
21-
return `gitlab:${process.env.CI_PROJECT_PATH}`;
38+
const hashed = hashProjectName(process.env.CI_PROJECT_PATH);
39+
return `gitlab:${hashed}`;
2240
}
2341

2442
if (process.env.BITBUCKET_REPO_FULL_NAME) {
25-
return `bitbucket:${process.env.BITBUCKET_REPO_FULL_NAME}`;
43+
const hashed = hashProjectName(process.env.BITBUCKET_REPO_FULL_NAME);
44+
return `bitbucket:${hashed}`;
2645
}
2746

2847
return null;
@@ -71,9 +90,11 @@ function parseGitUrl(url: string): string | null {
7190

7291
if (!repoPath) return null;
7392

93+
const hashedPath = hashProjectName(repoPath);
94+
7495
if (platform) {
75-
return `${platform}:${repoPath}`;
96+
return `${platform}:${hashedPath}`;
7697
}
7798

78-
return `git:${repoPath}`;
99+
return `git:${hashedPath}`;
79100
}

packages/new-compiler/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@
141141
"@types/babel__core": "^7.20.5",
142142
"@types/babel__generator": "^7.27.0",
143143
"@types/babel__traverse": "^7.28.0",
144+
"@types/ini": "4.1.1",
144145
"@types/node": "^25.0.3",
145146
"@types/proper-lockfile": "^4.1.4",
146147
"@types/react": "^19.2.7",
@@ -170,9 +171,12 @@
170171
"ai-sdk-ollama": "^3.0.0",
171172
"dotenv": "^17.2.3",
172173
"fast-xml-parser": "^5.3.3",
174+
"ini": "5.0.0",
173175
"intl-messageformat": "^11.0.6",
174176
"lingo.dev": "^0.117.23",
175177
"lodash": "^4.17.21",
178+
"node-machine-id": "1.1.12",
179+
"posthog-node": "5.14.0",
176180
"proper-lockfile": "^4.1.2",
177181
"ws": "^8.18.3"
178182
},

0 commit comments

Comments
 (0)