mobbdev 1.4.41 → 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.
@@ -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
- let skip = 0;
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
- if (page.length < PAGE) break;
5411
- skip += PAGE;
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
- while (page <= HARD_PAGE_CEILING) {
6559
- const res = await bitbucketClient.repositories.listCommits({
6560
- repo_slug: params2.repo_slug,
6561
- workspace: params2.workspace,
6562
- page: String(page),
6563
- pagelen: 100
6564
- });
6565
- const data = res.data;
6566
- const commits = data?.values ?? [];
6567
- if (commits.length === 0) break;
6568
- let sawInWindow = false;
6569
- for (const commit of commits) {
6570
- const record = commit;
6571
- const dateStr = record["date"];
6572
- if (dateStr && new Date(dateStr).getTime() < sinceMs) {
6573
- continue;
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 = true;
6576
- const author = record["author"];
6577
- if (!author?.raw) continue;
6578
- const match = author.raw.match(/^(.+?)\s*<([^>]+)>/);
6579
- if (!match) continue;
6580
- const [, name, email] = match;
6581
- if (!email) continue;
6582
- const externalId = author.user?.account_id ?? null;
6583
- const date = dateStr ?? params2.since;
6584
- const key = externalId ?? email.toLowerCase();
6585
- const prev = byKey.get(key);
6586
- if (!prev || new Date(date).getTime() > new Date(prev.date).getTime()) {
6587
- byKey.set(key, {
6588
- email: email.toLowerCase(),
6589
- name: name.trim() || null,
6590
- date,
6591
- externalId,
6592
- isBot: false
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 (!sawInWindow) break;
6597
- if (!data?.next) break;
6598
- page++;
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
- for await (const { data } of octokit.paginate.iterator(
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 ?? params2.since;
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 profileEmail = c.email ?? null;
8504
+ let email = c.email ?? null;
8415
8505
  let displayName = c.login ?? null;
8416
- let emailSource = profileEmail ? "collaborator_api" : "none";
8417
- if (!profileEmail && authUser && authUserPrimaryEmail && c.id === authUser.id) {
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
- profileEmail = profile.email;
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: profileEmail,
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 enrichLimit = pLimit5(5);
10201
- const enriched = await Promise.all(
10202
- members.map(
10203
- (m) => enrichLimit(async () => {
10204
- let email = null;
10205
- let emailSource = "none";
10206
- if (authUser?.email && authUser.id === m.id) {
10207
- email = authUser.email;
10208
- emailSource = "authenticated_user";
10209
- }
10210
- if (!email) {
10211
- try {
10212
- email = await getGitlabUserPublicEmail({
10213
- repoUrl: this.url,
10214
- accessToken: this.accessToken,
10215
- userId: m.id
10216
- });
10217
- if (email) emailSource = "public_email";
10218
- } catch (err) {
10219
- contextLogger.warn("[GitLab] getGitlabUserPublicEmail failed", {
10220
- username: m.username,
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 pLimit6 from "p-limit";
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 = pLimit6(SANITIZE_CONCURRENCY);
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 pLimit7 from "p-limit";
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 = pLimit7(UPLOAD_CONCURRENCY);
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.41" : "unknown";
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() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mobbdev",
3
- "version": "1.4.41",
3
+ "version": "1.4.42",
4
4
  "description": "Automated secure code remediation tool",
5
5
  "repository": "git+https://github.com/mobb-dev/bugsy.git",
6
6
  "main": "dist/index.mjs",