mobbdev 1.4.40 → 1.4.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/args/commands/upload_ai_blame.mjs +3 -4
- package/dist/index.mjs +247 -314
- package/package.json +1 -1
|
@@ -4602,6 +4602,9 @@ import pLimit from "p-limit";
|
|
|
4602
4602
|
import debugModule from "debug";
|
|
4603
4603
|
var debug3 = debugModule("mobb:shared");
|
|
4604
4604
|
|
|
4605
|
+
// src/features/analysis/scm/constants.ts
|
|
4606
|
+
var REPORT_DEFAULT_FILE_NAME = "report.json";
|
|
4607
|
+
|
|
4605
4608
|
// src/features/analysis/scm/utils/index.ts
|
|
4606
4609
|
import { z as z11 } from "zod";
|
|
4607
4610
|
|
|
@@ -4771,9 +4774,6 @@ var UserWorkspacePermissionsRepositoriesResponseZ = z17.object({
|
|
|
4771
4774
|
import { setTimeout as setTimeout3 } from "timers/promises";
|
|
4772
4775
|
import { z as z18 } from "zod";
|
|
4773
4776
|
|
|
4774
|
-
// src/features/analysis/scm/constants.ts
|
|
4775
|
-
var REPORT_DEFAULT_FILE_NAME = "report.json";
|
|
4776
|
-
|
|
4777
4777
|
// src/features/analysis/scm/index.ts
|
|
4778
4778
|
init_env();
|
|
4779
4779
|
|
|
@@ -4823,7 +4823,6 @@ var GitlabAuthResultZ = z20.object({
|
|
|
4823
4823
|
var debug6 = Debug5("scm:gitlab");
|
|
4824
4824
|
|
|
4825
4825
|
// src/features/analysis/scm/gitlab/GitlabSCMLib.ts
|
|
4826
|
-
import pLimit5 from "p-limit";
|
|
4827
4826
|
init_client_generates();
|
|
4828
4827
|
|
|
4829
4828
|
// src/features/analysis/scm/scmFactory.ts
|
package/dist/index.mjs
CHANGED
|
@@ -4256,6 +4256,12 @@ var contextLogger = {
|
|
|
4256
4256
|
}
|
|
4257
4257
|
};
|
|
4258
4258
|
|
|
4259
|
+
// src/features/analysis/scm/constants.ts
|
|
4260
|
+
var MOBB_ICON_IMG = "https://app.mobb.ai/gh-action/Logo_Rounded_Icon.svg";
|
|
4261
|
+
var MAX_BRANCHES_FETCH = 1e3;
|
|
4262
|
+
var MAX_ACTIVE_BRANCHES_SCAN = 250;
|
|
4263
|
+
var REPORT_DEFAULT_FILE_NAME = "report.json";
|
|
4264
|
+
|
|
4259
4265
|
// src/features/analysis/scm/errors.ts
|
|
4260
4266
|
var InvalidAccessTokenError = class extends Error {
|
|
4261
4267
|
constructor(m, scmType) {
|
|
@@ -5378,19 +5384,7 @@ async function getAdoSdk(params) {
|
|
|
5378
5384
|
const defaultBranch = repository.defaultBranch?.replace("refs/heads/", "");
|
|
5379
5385
|
const byEmail = /* @__PURE__ */ new Map();
|
|
5380
5386
|
const PAGE = 100;
|
|
5381
|
-
|
|
5382
|
-
while (true) {
|
|
5383
|
-
const page = await git.getCommits(
|
|
5384
|
-
repo,
|
|
5385
|
-
{
|
|
5386
|
-
fromDate: since,
|
|
5387
|
-
itemVersion: defaultBranch ? { version: defaultBranch } : void 0,
|
|
5388
|
-
$top: PAGE,
|
|
5389
|
-
$skip: skip
|
|
5390
|
-
},
|
|
5391
|
-
projectName
|
|
5392
|
-
);
|
|
5393
|
-
if (!page || page.length === 0) break;
|
|
5387
|
+
const accumulate = (page) => {
|
|
5394
5388
|
for (const c of page) {
|
|
5395
5389
|
const email = c.author?.email;
|
|
5396
5390
|
if (!email) continue;
|
|
@@ -5407,8 +5401,51 @@ async function getAdoSdk(params) {
|
|
|
5407
5401
|
});
|
|
5408
5402
|
}
|
|
5409
5403
|
}
|
|
5410
|
-
|
|
5411
|
-
|
|
5404
|
+
};
|
|
5405
|
+
const walk = async (branch) => {
|
|
5406
|
+
let skip = 0;
|
|
5407
|
+
let hasMore = true;
|
|
5408
|
+
while (hasMore) {
|
|
5409
|
+
const page = await git.getCommits(
|
|
5410
|
+
repo,
|
|
5411
|
+
{
|
|
5412
|
+
fromDate: since,
|
|
5413
|
+
itemVersion: branch ? { version: branch } : void 0,
|
|
5414
|
+
$top: PAGE,
|
|
5415
|
+
$skip: skip
|
|
5416
|
+
},
|
|
5417
|
+
projectName
|
|
5418
|
+
);
|
|
5419
|
+
const count = page?.length ?? 0;
|
|
5420
|
+
if (count > 0) {
|
|
5421
|
+
accumulate(page);
|
|
5422
|
+
}
|
|
5423
|
+
hasMore = count === PAGE;
|
|
5424
|
+
skip += PAGE;
|
|
5425
|
+
}
|
|
5426
|
+
};
|
|
5427
|
+
await walk(defaultBranch);
|
|
5428
|
+
try {
|
|
5429
|
+
const sinceMs = new Date(since).getTime();
|
|
5430
|
+
const branches = await git.getBranches(repo, projectName);
|
|
5431
|
+
const active = (branches ?? []).filter(
|
|
5432
|
+
(b) => !!b.name && b.name !== defaultBranch && !!b.commit?.committer?.date && b.commit.committer.date.getTime() >= sinceMs
|
|
5433
|
+
).sort(
|
|
5434
|
+
(a, b) => (b.commit?.committer?.date?.getTime() ?? 0) - (a.commit?.committer?.date?.getTime() ?? 0)
|
|
5435
|
+
).map((b) => b.name);
|
|
5436
|
+
if (active.length > MAX_ACTIVE_BRANCHES_SCAN) {
|
|
5437
|
+
console.warn(
|
|
5438
|
+
`[ADO] active-branch scan hit cap (${MAX_ACTIVE_BRANCHES_SCAN}) for ${repoUrl}; some branches skipped`
|
|
5439
|
+
);
|
|
5440
|
+
}
|
|
5441
|
+
for (const branch of active.slice(0, MAX_ACTIVE_BRANCHES_SCAN)) {
|
|
5442
|
+
await walk(branch);
|
|
5443
|
+
}
|
|
5444
|
+
} catch (err) {
|
|
5445
|
+
console.warn(
|
|
5446
|
+
`[ADO] all-branch author scan failed for ${repoUrl}; using default-branch count`,
|
|
5447
|
+
err instanceof Error ? err.message : String(err)
|
|
5448
|
+
);
|
|
5412
5449
|
}
|
|
5413
5450
|
return [...byEmail.values()];
|
|
5414
5451
|
},
|
|
@@ -6553,49 +6590,93 @@ function getBitbucketSdk(params) {
|
|
|
6553
6590
|
async streamRecentCommitAuthors(params2) {
|
|
6554
6591
|
const sinceMs = new Date(params2.since).getTime();
|
|
6555
6592
|
const byKey = /* @__PURE__ */ new Map();
|
|
6556
|
-
let page = 1;
|
|
6557
6593
|
const HARD_PAGE_CEILING = 1e4;
|
|
6558
|
-
|
|
6559
|
-
|
|
6560
|
-
|
|
6561
|
-
|
|
6562
|
-
|
|
6563
|
-
|
|
6564
|
-
|
|
6565
|
-
|
|
6566
|
-
|
|
6567
|
-
|
|
6568
|
-
|
|
6569
|
-
|
|
6570
|
-
|
|
6571
|
-
|
|
6572
|
-
|
|
6573
|
-
|
|
6594
|
+
const walkRef = async (include) => {
|
|
6595
|
+
let page = 1;
|
|
6596
|
+
while (page <= HARD_PAGE_CEILING) {
|
|
6597
|
+
const res = await bitbucketClient.repositories.listCommits({
|
|
6598
|
+
repo_slug: params2.repo_slug,
|
|
6599
|
+
workspace: params2.workspace,
|
|
6600
|
+
page: String(page),
|
|
6601
|
+
pagelen: 100,
|
|
6602
|
+
...include ? { include } : {}
|
|
6603
|
+
});
|
|
6604
|
+
const data = res.data;
|
|
6605
|
+
const commits = data?.values ?? [];
|
|
6606
|
+
if (commits.length === 0) break;
|
|
6607
|
+
let sawInWindow = false;
|
|
6608
|
+
for (const commit of commits) {
|
|
6609
|
+
const record = commit;
|
|
6610
|
+
const dateStr = record["date"];
|
|
6611
|
+
if (dateStr && new Date(dateStr).getTime() < sinceMs) {
|
|
6612
|
+
continue;
|
|
6613
|
+
}
|
|
6614
|
+
sawInWindow = true;
|
|
6615
|
+
const author = record["author"];
|
|
6616
|
+
if (!author?.raw) continue;
|
|
6617
|
+
const match = author.raw.match(/^(.+?)\s*<([^>]+)>/);
|
|
6618
|
+
if (!match) continue;
|
|
6619
|
+
const [, name, email] = match;
|
|
6620
|
+
if (!email) continue;
|
|
6621
|
+
const externalId = author.user?.account_id ?? null;
|
|
6622
|
+
const date = dateStr ?? params2.since;
|
|
6623
|
+
const key = externalId ?? email.toLowerCase();
|
|
6624
|
+
const prev = byKey.get(key);
|
|
6625
|
+
if (!prev || new Date(date).getTime() > new Date(prev.date).getTime()) {
|
|
6626
|
+
byKey.set(key, {
|
|
6627
|
+
email: email.toLowerCase(),
|
|
6628
|
+
name: name.trim() || null,
|
|
6629
|
+
date,
|
|
6630
|
+
externalId,
|
|
6631
|
+
isBot: false
|
|
6632
|
+
});
|
|
6633
|
+
}
|
|
6574
6634
|
}
|
|
6575
|
-
sawInWindow
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
|
|
6583
|
-
|
|
6584
|
-
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
|
|
6589
|
-
|
|
6590
|
-
|
|
6591
|
-
|
|
6592
|
-
|
|
6593
|
-
|
|
6635
|
+
if (!sawInWindow) break;
|
|
6636
|
+
if (!data?.next) break;
|
|
6637
|
+
page++;
|
|
6638
|
+
}
|
|
6639
|
+
};
|
|
6640
|
+
await walkRef(void 0);
|
|
6641
|
+
try {
|
|
6642
|
+
const branches = [];
|
|
6643
|
+
let bpage = 1;
|
|
6644
|
+
let bdone = false;
|
|
6645
|
+
while (!bdone && branches.length < MAX_ACTIVE_BRANCHES_SCAN) {
|
|
6646
|
+
const branchRes = await bitbucketClient.refs.listBranches({
|
|
6647
|
+
repo_slug: params2.repo_slug,
|
|
6648
|
+
workspace: params2.workspace,
|
|
6649
|
+
pagelen: 100,
|
|
6650
|
+
page: String(bpage),
|
|
6651
|
+
sort: "-target.date"
|
|
6652
|
+
});
|
|
6653
|
+
const vals = branchRes.data.values ?? [];
|
|
6654
|
+
if (vals.length === 0) break;
|
|
6655
|
+
for (const b of vals) {
|
|
6656
|
+
const d = b.target?.date;
|
|
6657
|
+
if (!d || new Date(d).getTime() < sinceMs) {
|
|
6658
|
+
bdone = true;
|
|
6659
|
+
break;
|
|
6660
|
+
}
|
|
6661
|
+
if (b.name) branches.push(b.name);
|
|
6662
|
+
if (branches.length >= MAX_ACTIVE_BRANCHES_SCAN) break;
|
|
6594
6663
|
}
|
|
6664
|
+
if (!branchRes.data.next) break;
|
|
6665
|
+
bpage++;
|
|
6595
6666
|
}
|
|
6596
|
-
if (
|
|
6597
|
-
|
|
6598
|
-
|
|
6667
|
+
if (branches.length >= MAX_ACTIVE_BRANCHES_SCAN) {
|
|
6668
|
+
console.warn(
|
|
6669
|
+
`[Bitbucket] active-branch scan hit cap (${MAX_ACTIVE_BRANCHES_SCAN}) for ${params2.workspace}/${params2.repo_slug}; some branches skipped`
|
|
6670
|
+
);
|
|
6671
|
+
}
|
|
6672
|
+
for (const branch of branches) {
|
|
6673
|
+
await walkRef(branch);
|
|
6674
|
+
}
|
|
6675
|
+
} catch (err) {
|
|
6676
|
+
console.warn(
|
|
6677
|
+
`[Bitbucket] all-branch author scan failed for ${params2.workspace}/${params2.repo_slug}; using main-branch count`,
|
|
6678
|
+
err instanceof Error ? err.message : String(err)
|
|
6679
|
+
);
|
|
6599
6680
|
}
|
|
6600
6681
|
return [...byKey.values()];
|
|
6601
6682
|
},
|
|
@@ -7088,11 +7169,6 @@ var BitbucketSCMLib = class extends SCMLib {
|
|
|
7088
7169
|
}
|
|
7089
7170
|
};
|
|
7090
7171
|
|
|
7091
|
-
// src/features/analysis/scm/constants.ts
|
|
7092
|
-
var MOBB_ICON_IMG = "https://app.mobb.ai/gh-action/Logo_Rounded_Icon.svg";
|
|
7093
|
-
var MAX_BRANCHES_FETCH = 1e3;
|
|
7094
|
-
var REPORT_DEFAULT_FILE_NAME = "report.json";
|
|
7095
|
-
|
|
7096
7172
|
// src/features/analysis/scm/index.ts
|
|
7097
7173
|
init_env();
|
|
7098
7174
|
|
|
@@ -7404,6 +7480,25 @@ async function executeBatchGraphQL(octokit, owner, repo, config2) {
|
|
|
7404
7480
|
});
|
|
7405
7481
|
return result;
|
|
7406
7482
|
}
|
|
7483
|
+
var RECENT_BRANCHES_QUERY = `
|
|
7484
|
+
query ($owner: String!, $repo: String!, $cursor: String) {
|
|
7485
|
+
repository(owner: $owner, name: $repo) {
|
|
7486
|
+
defaultBranchRef { name }
|
|
7487
|
+
refs(
|
|
7488
|
+
refPrefix: "refs/heads/"
|
|
7489
|
+
first: 100
|
|
7490
|
+
after: $cursor
|
|
7491
|
+
orderBy: { field: TAG_COMMIT_DATE, direction: DESC }
|
|
7492
|
+
) {
|
|
7493
|
+
pageInfo { hasNextPage endCursor }
|
|
7494
|
+
nodes {
|
|
7495
|
+
name
|
|
7496
|
+
target { ... on Commit { committedDate } }
|
|
7497
|
+
}
|
|
7498
|
+
}
|
|
7499
|
+
}
|
|
7500
|
+
}
|
|
7501
|
+
`;
|
|
7407
7502
|
function getGithubSdk(params = {}) {
|
|
7408
7503
|
const octokit = getOctoKit(params);
|
|
7409
7504
|
async function openPrWithFiles(params2) {
|
|
@@ -7872,21 +7967,14 @@ function getGithubSdk(params = {}) {
|
|
|
7872
7967
|
// commit volume, and the walk is uncapped so the 90-day count is exact even
|
|
7873
7968
|
// for a repo with hundreds of thousands of commits.
|
|
7874
7969
|
async streamRecentCommitAuthors(params2) {
|
|
7970
|
+
const { owner, repo, since } = params2;
|
|
7875
7971
|
const byAuthor = /* @__PURE__ */ new Map();
|
|
7876
|
-
|
|
7877
|
-
octokit.rest.repos.listCommits,
|
|
7878
|
-
{
|
|
7879
|
-
owner: params2.owner,
|
|
7880
|
-
repo: params2.repo,
|
|
7881
|
-
since: params2.since,
|
|
7882
|
-
per_page: 100
|
|
7883
|
-
}
|
|
7884
|
-
)) {
|
|
7972
|
+
const accumulate = (data) => {
|
|
7885
7973
|
for (const c of data) {
|
|
7886
7974
|
const email = c.commit?.author?.email;
|
|
7887
7975
|
if (!email) continue;
|
|
7888
7976
|
const externalId = c.author?.id != null ? String(c.author.id) : null;
|
|
7889
|
-
const date = c.commit?.committer?.date ?? c.commit?.author?.date ??
|
|
7977
|
+
const date = c.commit?.committer?.date ?? c.commit?.author?.date ?? since;
|
|
7890
7978
|
const key = externalId ?? email.toLowerCase();
|
|
7891
7979
|
const prev = byAuthor.get(key);
|
|
7892
7980
|
if (!prev || new Date(date).getTime() > new Date(prev.date).getTime()) {
|
|
@@ -7899,6 +7987,64 @@ function getGithubSdk(params = {}) {
|
|
|
7899
7987
|
});
|
|
7900
7988
|
}
|
|
7901
7989
|
}
|
|
7990
|
+
};
|
|
7991
|
+
const walkBranch = async (branch) => {
|
|
7992
|
+
for await (const { data } of octokit.paginate.iterator(
|
|
7993
|
+
octokit.rest.repos.listCommits,
|
|
7994
|
+
{
|
|
7995
|
+
owner,
|
|
7996
|
+
repo,
|
|
7997
|
+
since,
|
|
7998
|
+
per_page: 100,
|
|
7999
|
+
...branch ? { sha: branch } : {}
|
|
8000
|
+
}
|
|
8001
|
+
)) {
|
|
8002
|
+
accumulate(data);
|
|
8003
|
+
}
|
|
8004
|
+
};
|
|
8005
|
+
await walkBranch(void 0);
|
|
8006
|
+
try {
|
|
8007
|
+
const sinceMs = new Date(since).getTime();
|
|
8008
|
+
const activeBranches = [];
|
|
8009
|
+
let cursor = null;
|
|
8010
|
+
let defaultBranch = null;
|
|
8011
|
+
let done = false;
|
|
8012
|
+
while (!done && activeBranches.length < MAX_ACTIVE_BRANCHES_SCAN) {
|
|
8013
|
+
const resp = await octokit.graphql(
|
|
8014
|
+
RECENT_BRANCHES_QUERY,
|
|
8015
|
+
{ owner, repo, cursor }
|
|
8016
|
+
);
|
|
8017
|
+
defaultBranch = defaultBranch ?? resp.repository?.defaultBranchRef?.name ?? null;
|
|
8018
|
+
const refs = resp.repository?.refs;
|
|
8019
|
+
if (!refs) break;
|
|
8020
|
+
for (const node of refs.nodes) {
|
|
8021
|
+
const committedDate = node.target?.committedDate;
|
|
8022
|
+
if (committedDate && new Date(committedDate).getTime() < sinceMs) {
|
|
8023
|
+
done = true;
|
|
8024
|
+
break;
|
|
8025
|
+
}
|
|
8026
|
+
if (!committedDate) continue;
|
|
8027
|
+
if (node.name !== defaultBranch) {
|
|
8028
|
+
activeBranches.push(node.name);
|
|
8029
|
+
}
|
|
8030
|
+
if (activeBranches.length >= MAX_ACTIVE_BRANCHES_SCAN) break;
|
|
8031
|
+
}
|
|
8032
|
+
if (!refs.pageInfo.hasNextPage) break;
|
|
8033
|
+
cursor = refs.pageInfo.endCursor;
|
|
8034
|
+
}
|
|
8035
|
+
if (activeBranches.length >= MAX_ACTIVE_BRANCHES_SCAN) {
|
|
8036
|
+
console.warn(
|
|
8037
|
+
`[GitHub] active-branch scan hit cap (${MAX_ACTIVE_BRANCHES_SCAN}) for ${owner}/${repo}; some branches skipped`
|
|
8038
|
+
);
|
|
8039
|
+
}
|
|
8040
|
+
for (const branch of activeBranches) {
|
|
8041
|
+
await walkBranch(branch);
|
|
8042
|
+
}
|
|
8043
|
+
} catch (err) {
|
|
8044
|
+
console.warn(
|
|
8045
|
+
`[GitHub] all-branch author scan failed for ${owner}/${repo}; using default-branch count`,
|
|
8046
|
+
err instanceof Error ? err.message : String(err)
|
|
8047
|
+
);
|
|
7902
8048
|
}
|
|
7903
8049
|
return [...byAuthor.values()];
|
|
7904
8050
|
},
|
|
@@ -8127,19 +8273,6 @@ function getGithubSdk(params = {}) {
|
|
|
8127
8273
|
cache?.set(getProfileParams.username, data);
|
|
8128
8274
|
return data;
|
|
8129
8275
|
},
|
|
8130
|
-
async getLatestRepoCommitByAuthor(params2) {
|
|
8131
|
-
try {
|
|
8132
|
-
const { data } = await octokit.rest.repos.listCommits({
|
|
8133
|
-
owner: params2.owner,
|
|
8134
|
-
repo: params2.repo,
|
|
8135
|
-
author: params2.author,
|
|
8136
|
-
per_page: 1
|
|
8137
|
-
});
|
|
8138
|
-
return data[0] ?? null;
|
|
8139
|
-
} catch {
|
|
8140
|
-
return null;
|
|
8141
|
-
}
|
|
8142
|
-
},
|
|
8143
8276
|
async getAuthenticatedUser() {
|
|
8144
8277
|
try {
|
|
8145
8278
|
const { data } = await octokit.rest.users.getAuthenticated();
|
|
@@ -8157,49 +8290,6 @@ function getGithubSdk(params = {}) {
|
|
|
8157
8290
|
} catch {
|
|
8158
8291
|
return [];
|
|
8159
8292
|
}
|
|
8160
|
-
},
|
|
8161
|
-
async getEmailFromPublicEvents(params2) {
|
|
8162
|
-
try {
|
|
8163
|
-
const { data: events } = await octokit.rest.activity.listPublicEventsForUser({
|
|
8164
|
-
username: params2.username,
|
|
8165
|
-
per_page: 30
|
|
8166
|
-
});
|
|
8167
|
-
let fallback = null;
|
|
8168
|
-
for (const event of events) {
|
|
8169
|
-
if (event.type !== "PushEvent") continue;
|
|
8170
|
-
const payload = event.payload;
|
|
8171
|
-
if (!payload.commits) continue;
|
|
8172
|
-
for (const commit of payload.commits) {
|
|
8173
|
-
const email = commit.author?.email;
|
|
8174
|
-
if (!email) continue;
|
|
8175
|
-
if (!email.includes("noreply")) return email;
|
|
8176
|
-
if (!fallback) fallback = email;
|
|
8177
|
-
}
|
|
8178
|
-
}
|
|
8179
|
-
return fallback;
|
|
8180
|
-
} catch {
|
|
8181
|
-
return null;
|
|
8182
|
-
}
|
|
8183
|
-
},
|
|
8184
|
-
async getEmailFromCommitSearch(params2) {
|
|
8185
|
-
try {
|
|
8186
|
-
const { data } = await octokit.rest.search.commits({
|
|
8187
|
-
q: `author:${params2.username}`,
|
|
8188
|
-
sort: "author-date",
|
|
8189
|
-
order: "desc",
|
|
8190
|
-
per_page: 5
|
|
8191
|
-
});
|
|
8192
|
-
let fallback = null;
|
|
8193
|
-
for (const item of data.items) {
|
|
8194
|
-
const email = item.commit?.author?.email;
|
|
8195
|
-
if (!email) continue;
|
|
8196
|
-
if (!email.includes("noreply")) return email;
|
|
8197
|
-
if (!fallback) fallback = email;
|
|
8198
|
-
}
|
|
8199
|
-
return fallback;
|
|
8200
|
-
} catch {
|
|
8201
|
-
return null;
|
|
8202
|
-
}
|
|
8203
8293
|
}
|
|
8204
8294
|
};
|
|
8205
8295
|
}
|
|
@@ -8411,24 +8501,18 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
8411
8501
|
const enriched = await Promise.all(
|
|
8412
8502
|
collaborators.map(
|
|
8413
8503
|
(c) => enrichLimit(async () => {
|
|
8414
|
-
let
|
|
8504
|
+
let email = c.email ?? null;
|
|
8415
8505
|
let displayName = c.login ?? null;
|
|
8416
|
-
|
|
8417
|
-
|
|
8418
|
-
profileEmail = authUserPrimaryEmail;
|
|
8419
|
-
emailSource = "authenticated_user";
|
|
8506
|
+
if (!email && authUser && authUserPrimaryEmail && c.id === authUser.id) {
|
|
8507
|
+
email = authUserPrimaryEmail;
|
|
8420
8508
|
}
|
|
8421
|
-
const isRealEmail = (e) => e && !e.includes("noreply");
|
|
8422
|
-
let noreplyFallback = null;
|
|
8423
|
-
let noreplySource = "";
|
|
8424
8509
|
if (c.login) {
|
|
8425
8510
|
try {
|
|
8426
8511
|
const profile = await this.githubSdk.getUserProfile({
|
|
8427
8512
|
username: c.login
|
|
8428
8513
|
});
|
|
8429
8514
|
if (profile.email) {
|
|
8430
|
-
|
|
8431
|
-
emailSource = "user_profile";
|
|
8515
|
+
email = profile.email;
|
|
8432
8516
|
}
|
|
8433
8517
|
displayName = profile.name ?? displayName;
|
|
8434
8518
|
} catch (err) {
|
|
@@ -8437,112 +8521,12 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
8437
8521
|
error: err instanceof Error ? err.message : String(err)
|
|
8438
8522
|
});
|
|
8439
8523
|
}
|
|
8440
|
-
if (!isRealEmail(profileEmail)) {
|
|
8441
|
-
if (profileEmail && !noreplyFallback) {
|
|
8442
|
-
noreplyFallback = profileEmail;
|
|
8443
|
-
noreplySource = emailSource;
|
|
8444
|
-
}
|
|
8445
|
-
try {
|
|
8446
|
-
const commit = await this.githubSdk.getLatestRepoCommitByAuthor(
|
|
8447
|
-
{
|
|
8448
|
-
owner,
|
|
8449
|
-
repo,
|
|
8450
|
-
author: c.login
|
|
8451
|
-
}
|
|
8452
|
-
);
|
|
8453
|
-
const commitAuthor = commit?.commit?.author;
|
|
8454
|
-
const commitEmail = commitAuthor?.email;
|
|
8455
|
-
if (commitAuthor?.name && displayName === c.login) {
|
|
8456
|
-
displayName = commitAuthor.name;
|
|
8457
|
-
}
|
|
8458
|
-
if (commitEmail) {
|
|
8459
|
-
if (isRealEmail(commitEmail)) {
|
|
8460
|
-
profileEmail = commitEmail;
|
|
8461
|
-
emailSource = "commit_author";
|
|
8462
|
-
} else if (!noreplyFallback) {
|
|
8463
|
-
noreplyFallback = commitEmail;
|
|
8464
|
-
noreplySource = "commit_noreply";
|
|
8465
|
-
}
|
|
8466
|
-
}
|
|
8467
|
-
} catch (err) {
|
|
8468
|
-
contextLogger.warn(
|
|
8469
|
-
"[GitHub] getLatestRepoCommitByAuthor failed",
|
|
8470
|
-
{
|
|
8471
|
-
username: c.login,
|
|
8472
|
-
owner,
|
|
8473
|
-
repo,
|
|
8474
|
-
error: err instanceof Error ? err.message : String(err)
|
|
8475
|
-
}
|
|
8476
|
-
);
|
|
8477
|
-
}
|
|
8478
|
-
}
|
|
8479
|
-
if (!isRealEmail(profileEmail)) {
|
|
8480
|
-
try {
|
|
8481
|
-
const eventEmail = await this.githubSdk.getEmailFromPublicEvents({
|
|
8482
|
-
username: c.login
|
|
8483
|
-
});
|
|
8484
|
-
if (eventEmail) {
|
|
8485
|
-
if (isRealEmail(eventEmail)) {
|
|
8486
|
-
profileEmail = eventEmail;
|
|
8487
|
-
emailSource = "public_events";
|
|
8488
|
-
} else if (!noreplyFallback) {
|
|
8489
|
-
noreplyFallback = eventEmail;
|
|
8490
|
-
noreplySource = "events_noreply";
|
|
8491
|
-
}
|
|
8492
|
-
}
|
|
8493
|
-
} catch (err) {
|
|
8494
|
-
contextLogger.warn("[GitHub] getEmailFromPublicEvents failed", {
|
|
8495
|
-
username: c.login,
|
|
8496
|
-
error: err instanceof Error ? err.message : String(err)
|
|
8497
|
-
});
|
|
8498
|
-
}
|
|
8499
|
-
}
|
|
8500
|
-
if (!isRealEmail(profileEmail)) {
|
|
8501
|
-
try {
|
|
8502
|
-
const searchEmail = await this.githubSdk.getEmailFromCommitSearch({
|
|
8503
|
-
username: c.login
|
|
8504
|
-
});
|
|
8505
|
-
if (searchEmail) {
|
|
8506
|
-
if (isRealEmail(searchEmail)) {
|
|
8507
|
-
profileEmail = searchEmail;
|
|
8508
|
-
emailSource = "commit_search";
|
|
8509
|
-
} else if (!noreplyFallback) {
|
|
8510
|
-
noreplyFallback = searchEmail;
|
|
8511
|
-
noreplySource = "search_noreply";
|
|
8512
|
-
}
|
|
8513
|
-
}
|
|
8514
|
-
} catch (err) {
|
|
8515
|
-
contextLogger.warn("[GitHub] getEmailFromCommitSearch failed", {
|
|
8516
|
-
username: c.login,
|
|
8517
|
-
error: err instanceof Error ? err.message : String(err)
|
|
8518
|
-
});
|
|
8519
|
-
}
|
|
8520
|
-
}
|
|
8521
|
-
if (!isRealEmail(profileEmail) && noreplyFallback) {
|
|
8522
|
-
profileEmail = noreplyFallback;
|
|
8523
|
-
emailSource = noreplySource;
|
|
8524
|
-
}
|
|
8525
8524
|
}
|
|
8526
|
-
if (profileEmail) {
|
|
8527
|
-
contextLogger.info("[GitHub] Resolved contributor email", {
|
|
8528
|
-
username: c.login,
|
|
8529
|
-
emailSource
|
|
8530
|
-
});
|
|
8531
|
-
} else {
|
|
8532
|
-
contextLogger.debug("[GitHub] No email resolved for contributor", {
|
|
8533
|
-
username: c.login
|
|
8534
|
-
});
|
|
8535
|
-
}
|
|
8536
|
-
contextLogger.info("[GitHub] Contributor resolved", {
|
|
8537
|
-
username: c.login,
|
|
8538
|
-
profileName: displayName,
|
|
8539
|
-
displayNameIsNull: displayName === null
|
|
8540
|
-
});
|
|
8541
8525
|
return {
|
|
8542
8526
|
externalId: String(c.id),
|
|
8543
8527
|
username: c.login ?? null,
|
|
8544
8528
|
displayName,
|
|
8545
|
-
email
|
|
8529
|
+
email,
|
|
8546
8530
|
accessLevel: c.role_name ?? null
|
|
8547
8531
|
};
|
|
8548
8532
|
})
|
|
@@ -9587,6 +9571,7 @@ async function getGitlabRecentCommitAuthors({
|
|
|
9587
9571
|
while (hasMore) {
|
|
9588
9572
|
const response = await api2.Commits.all(projectPath, {
|
|
9589
9573
|
since,
|
|
9574
|
+
all: true,
|
|
9590
9575
|
perPage,
|
|
9591
9576
|
page,
|
|
9592
9577
|
showExpanded: true
|
|
@@ -9752,19 +9737,6 @@ async function listGitlabProjectMembers({
|
|
|
9752
9737
|
}
|
|
9753
9738
|
return projectMembers;
|
|
9754
9739
|
}
|
|
9755
|
-
async function getGitlabUserPublicEmail({
|
|
9756
|
-
repoUrl,
|
|
9757
|
-
accessToken,
|
|
9758
|
-
userId
|
|
9759
|
-
}) {
|
|
9760
|
-
try {
|
|
9761
|
-
const api2 = getGitBeaker({ url: repoUrl, gitlabAuthToken: accessToken });
|
|
9762
|
-
const user = await api2.Users.show(userId);
|
|
9763
|
-
return user["public_email"];
|
|
9764
|
-
} catch {
|
|
9765
|
-
return null;
|
|
9766
|
-
}
|
|
9767
|
-
}
|
|
9768
9740
|
async function listGitlabRepoContributors({
|
|
9769
9741
|
repoUrl,
|
|
9770
9742
|
accessToken
|
|
@@ -9796,7 +9768,6 @@ async function getGitlabAuthenticatedUser({
|
|
|
9796
9768
|
}
|
|
9797
9769
|
|
|
9798
9770
|
// src/features/analysis/scm/gitlab/GitlabSCMLib.ts
|
|
9799
|
-
import pLimit5 from "p-limit";
|
|
9800
9771
|
init_client_generates();
|
|
9801
9772
|
var GitlabSCMLib = class extends SCMLib {
|
|
9802
9773
|
constructor(url, accessToken, scmOrg) {
|
|
@@ -10197,65 +10168,27 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
10197
10168
|
memberCount: members.length,
|
|
10198
10169
|
repoContributorCount: repoContributors.length
|
|
10199
10170
|
});
|
|
10200
|
-
const
|
|
10201
|
-
|
|
10202
|
-
|
|
10203
|
-
|
|
10204
|
-
|
|
10205
|
-
|
|
10206
|
-
|
|
10207
|
-
|
|
10208
|
-
|
|
10209
|
-
|
|
10210
|
-
|
|
10211
|
-
|
|
10212
|
-
|
|
10213
|
-
|
|
10214
|
-
|
|
10215
|
-
|
|
10216
|
-
|
|
10217
|
-
|
|
10218
|
-
|
|
10219
|
-
|
|
10220
|
-
|
|
10221
|
-
userId: m.id,
|
|
10222
|
-
error: err instanceof Error ? err.message : String(err)
|
|
10223
|
-
});
|
|
10224
|
-
}
|
|
10225
|
-
}
|
|
10226
|
-
if (!email && m.username) {
|
|
10227
|
-
const match = repoContributors.find(
|
|
10228
|
-
(rc) => rc.name?.toLowerCase() === m.username?.toLowerCase() || rc.name?.toLowerCase() === m.name?.toLowerCase()
|
|
10229
|
-
);
|
|
10230
|
-
if (match?.email) {
|
|
10231
|
-
email = match.email;
|
|
10232
|
-
emailSource = match.email.includes("noreply") ? "commit_noreply" : "commit_author";
|
|
10233
|
-
} else {
|
|
10234
|
-
contextLogger.debug(
|
|
10235
|
-
"[GitLab] No commit author match for member",
|
|
10236
|
-
{
|
|
10237
|
-
username: m.username,
|
|
10238
|
-
displayName: m.name
|
|
10239
|
-
}
|
|
10240
|
-
);
|
|
10241
|
-
}
|
|
10242
|
-
}
|
|
10243
|
-
if (email) {
|
|
10244
|
-
contextLogger.info("[GitLab] Resolved contributor email", {
|
|
10245
|
-
username: m.username,
|
|
10246
|
-
emailSource
|
|
10247
|
-
});
|
|
10248
|
-
}
|
|
10249
|
-
return {
|
|
10250
|
-
externalId: String(m.id),
|
|
10251
|
-
username: m.username ?? null,
|
|
10252
|
-
displayName: m.name ?? null,
|
|
10253
|
-
email,
|
|
10254
|
-
accessLevel: m.access_level != null ? String(m.access_level) : null
|
|
10255
|
-
};
|
|
10256
|
-
})
|
|
10257
|
-
)
|
|
10258
|
-
);
|
|
10171
|
+
const enriched = members.map((m) => {
|
|
10172
|
+
let email = null;
|
|
10173
|
+
if (authUser?.email && authUser.id === m.id) {
|
|
10174
|
+
email = authUser.email;
|
|
10175
|
+
}
|
|
10176
|
+
if (!email && m.username) {
|
|
10177
|
+
const match = repoContributors.find(
|
|
10178
|
+
(rc) => rc.name?.toLowerCase() === m.username?.toLowerCase() || rc.name?.toLowerCase() === m.name?.toLowerCase()
|
|
10179
|
+
);
|
|
10180
|
+
if (match?.email) {
|
|
10181
|
+
email = match.email;
|
|
10182
|
+
}
|
|
10183
|
+
}
|
|
10184
|
+
return {
|
|
10185
|
+
externalId: String(m.id),
|
|
10186
|
+
username: m.username ?? null,
|
|
10187
|
+
displayName: m.name ?? null,
|
|
10188
|
+
email,
|
|
10189
|
+
accessLevel: m.access_level != null ? String(m.access_level) : null
|
|
10190
|
+
};
|
|
10191
|
+
});
|
|
10259
10192
|
if (enriched.length === 0 && repoContributors.length > 0) {
|
|
10260
10193
|
return repoContributors.filter((rc) => rc.email || rc.name).map((rc) => ({
|
|
10261
10194
|
// Synthetic key namespaced away from real numeric member ids so a
|
|
@@ -16040,7 +15973,7 @@ import path15 from "path";
|
|
|
16040
15973
|
import { createHash } from "crypto";
|
|
16041
15974
|
import path13 from "path";
|
|
16042
15975
|
import AdmZip3 from "adm-zip";
|
|
16043
|
-
import
|
|
15976
|
+
import pLimit5 from "p-limit";
|
|
16044
15977
|
var SANITIZE_CONCURRENCY = 5;
|
|
16045
15978
|
function md5Hex(data) {
|
|
16046
15979
|
return createHash("md5").update(typeof data === "string" ? Buffer.from(data, "utf-8") : data).digest("hex");
|
|
@@ -16052,7 +15985,7 @@ async function sanitizeFileContent(content) {
|
|
|
16052
15985
|
return sanitizedData;
|
|
16053
15986
|
}
|
|
16054
15987
|
async function processContextFiles(regularFiles, skillGroups) {
|
|
16055
|
-
const limit =
|
|
15988
|
+
const limit = pLimit5(SANITIZE_CONCURRENCY);
|
|
16056
15989
|
const processedFiles = await Promise.all(
|
|
16057
15990
|
regularFiles.map(
|
|
16058
15991
|
(entry) => limit(async () => {
|
|
@@ -17513,7 +17446,7 @@ import { promisify } from "util";
|
|
|
17513
17446
|
|
|
17514
17447
|
// src/features/analysis/context_file_uploader.ts
|
|
17515
17448
|
import { setTimeout as sleep3 } from "timers/promises";
|
|
17516
|
-
import
|
|
17449
|
+
import pLimit6 from "p-limit";
|
|
17517
17450
|
init_client_generates();
|
|
17518
17451
|
var UPLOAD_CONCURRENCY = 5;
|
|
17519
17452
|
var UPLOAD_MAX_ATTEMPTS = 2;
|
|
@@ -17555,7 +17488,7 @@ async function uploadContextRecords(opts) {
|
|
|
17555
17488
|
const uploadedSkillGroups = [];
|
|
17556
17489
|
const failedFiles = [];
|
|
17557
17490
|
const failedSkillGroups = [];
|
|
17558
|
-
const limit =
|
|
17491
|
+
const limit = pLimit6(UPLOAD_CONCURRENCY);
|
|
17559
17492
|
const extraFields = {
|
|
17560
17493
|
...repositoryUrl !== void 0 && { repositoryUrl },
|
|
17561
17494
|
...branch !== void 0 && { branch },
|
|
@@ -18043,7 +17976,7 @@ function createLogger(config2) {
|
|
|
18043
17976
|
|
|
18044
17977
|
// src/features/claude_code/hook_logger.ts
|
|
18045
17978
|
var DD_RUM_TOKEN = true ? "pubf59c0182545bfb4c299175119f1abf9b" : "";
|
|
18046
|
-
var CLI_VERSION = true ? "1.4.
|
|
17979
|
+
var CLI_VERSION = true ? "1.4.42" : "unknown";
|
|
18047
17980
|
var NAMESPACE = "mobbdev-claude-code-hook-logs";
|
|
18048
17981
|
var claudeCodeVersion;
|
|
18049
17982
|
function buildDdTags() {
|