mobbdev 1.4.30 → 1.4.31

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.
Files changed (2) hide show
  1. package/dist/index.mjs +100 -13
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -8814,6 +8814,35 @@ function getBitbucketSdk(params) {
8814
8814
  return { accountId: null, email: null };
8815
8815
  }
8816
8816
  },
8817
+ async listRecentCommits(params2) {
8818
+ const sinceDate = new Date(params2.since);
8819
+ const commits = [];
8820
+ const MAX_PAGES = 100;
8821
+ let page = 1;
8822
+ let done = false;
8823
+ while (!done && page <= MAX_PAGES) {
8824
+ const res = await bitbucketClient.repositories.listCommits({
8825
+ repo_slug: params2.repo_slug,
8826
+ workspace: params2.workspace,
8827
+ page: String(page),
8828
+ pagelen: 100
8829
+ });
8830
+ const data = res.data;
8831
+ const values = data?.values ?? [];
8832
+ if (values.length === 0) break;
8833
+ for (const commit of values) {
8834
+ const date = commit?.["date"];
8835
+ if (date && new Date(date) < sinceDate) {
8836
+ done = true;
8837
+ continue;
8838
+ }
8839
+ commits.push(commit);
8840
+ }
8841
+ if (!data?.next) break;
8842
+ page++;
8843
+ }
8844
+ return commits;
8845
+ },
8817
8846
  async getRepoCommitAuthors(params2) {
8818
8847
  try {
8819
8848
  const res = await bitbucketClient.repositories.listCommits({
@@ -9157,8 +9186,33 @@ var BitbucketSCMLib = class extends SCMLib {
9157
9186
  async getPullRequestMetrics(_prNumber) {
9158
9187
  throw new Error("getPullRequestMetrics not implemented for Bitbucket");
9159
9188
  }
9160
- async getRecentCommits(_since) {
9161
- throw new Error("getRecentCommits not implemented for Bitbucket");
9189
+ async getRecentCommits(since) {
9190
+ this._validateAccessTokenAndUrl();
9191
+ const { workspace, repo_slug } = parseBitbucketOrganizationAndRepo(this.url);
9192
+ const bitbucketSdk = createBitbucketSdk(this.accessToken);
9193
+ const rawCommits = await bitbucketSdk.listRecentCommits({
9194
+ workspace,
9195
+ repo_slug,
9196
+ since
9197
+ });
9198
+ return {
9199
+ data: rawCommits.map((commit) => {
9200
+ const c = commit;
9201
+ const author = c["author"];
9202
+ const match = author?.raw?.match(/^(.+?)\s*<([^>]+)>/);
9203
+ return {
9204
+ sha: c["hash"] ?? "",
9205
+ commit: {
9206
+ committer: c["date"] ? { date: c["date"] } : void 0,
9207
+ author: match ? { name: match[1]?.trim(), email: match[2] } : void 0,
9208
+ message: c["message"] ?? ""
9209
+ },
9210
+ // Bitbucket resolves the commit to an account when it can; account_id
9211
+ // matches repo_contributor.external_id for Bitbucket rows.
9212
+ authorExternalId: author?.user?.account_id ?? null
9213
+ };
9214
+ })
9215
+ };
9162
9216
  }
9163
9217
  async getRateLimitStatus() {
9164
9218
  return null;
@@ -9423,7 +9477,7 @@ function getOctoKit(options) {
9423
9477
  octokit.log.warn(
9424
9478
  `Request quota exhausted for request ${options2.method} ${options2.url}`
9425
9479
  );
9426
- if (retryCount === 0) {
9480
+ if (retryCount < 3) {
9427
9481
  octokit.log.info(`Retrying after ${retryAfter} seconds!`);
9428
9482
  return true;
9429
9483
  }
@@ -9433,7 +9487,7 @@ function getOctoKit(options) {
9433
9487
  octokit.log.warn(
9434
9488
  `SecondaryRateLimit detected for request ${options2.method} ${options2.url}`
9435
9489
  );
9436
- if (retryCount === 0) {
9490
+ if (retryCount < 3) {
9437
9491
  octokit.log.info(`Retrying after ${retryAfter} seconds!`);
9438
9492
  return true;
9439
9493
  }
@@ -10198,10 +10252,16 @@ function getGithubSdk(params = {}) {
10198
10252
  });
10199
10253
  return members;
10200
10254
  },
10201
- async getUserProfile(params2) {
10255
+ async getUserProfile(getProfileParams) {
10256
+ const cache = params.userProfileCache;
10257
+ const cached = cache?.get(getProfileParams.username);
10258
+ if (cached) {
10259
+ return cached;
10260
+ }
10202
10261
  const { data } = await octokit.rest.users.getByUsername({
10203
- username: params2.username
10262
+ username: getProfileParams.username
10204
10263
  });
10264
+ cache?.set(getProfileParams.username, data);
10205
10265
  return data;
10206
10266
  },
10207
10267
  async getLatestRepoCommitByAuthor(params2) {
@@ -10294,12 +10354,16 @@ function determinePrStatus(state, isDraft) {
10294
10354
  }
10295
10355
  var GithubSCMLib = class extends SCMLib {
10296
10356
  // we don't always need a url, what's important is that we have an access token
10297
- constructor(url, accessToken, scmOrg) {
10357
+ constructor(url, accessToken, scmOrg, options) {
10298
10358
  super(url, accessToken, scmOrg);
10299
10359
  __publicField(this, "githubSdk");
10300
10360
  this.githubSdk = getGithubSdk({
10301
10361
  auth: accessToken,
10302
- url
10362
+ url,
10363
+ // Honor GitHub's rate-limit/Retry-After backoff for bulk callers
10364
+ // (e.g. the contributor sync) instead of failing fast.
10365
+ isEnableRetries: options?.enableThrottling,
10366
+ userProfileCache: options?.userProfileCache
10303
10367
  });
10304
10368
  }
10305
10369
  async createSubmitRequest(params) {
@@ -10429,7 +10493,13 @@ var GithubSCMLib = class extends SCMLib {
10429
10493
  author: c.commit.author ? { email: c.commit.author.email, name: c.commit.author.name } : void 0,
10430
10494
  message: c.commit.message
10431
10495
  },
10432
- parents: c.parents?.map((p) => ({ sha: p.sha }))
10496
+ parents: c.parents?.map((p) => ({ sha: p.sha })),
10497
+ // Top-level `author` is GitHub's resolution of the commit to an account
10498
+ // (null when GitHub can't tie the commit email to a user). Its numeric
10499
+ // id matches repo_contributor.external_id (stored as String(id)), and
10500
+ // its type marks GitHub App / bot accounts authoritatively.
10501
+ authorExternalId: c.author?.id != null ? String(c.author.id) : null,
10502
+ authorIsBot: c.author?.type === "Bot"
10433
10503
  }))
10434
10504
  };
10435
10505
  }
@@ -10498,7 +10568,11 @@ var GithubSCMLib = class extends SCMLib {
10498
10568
  author: c.login
10499
10569
  }
10500
10570
  );
10501
- const commitEmail = commit?.commit?.author?.email;
10571
+ const commitAuthor = commit?.commit?.author;
10572
+ const commitEmail = commitAuthor?.email;
10573
+ if (commitAuthor?.name && displayName === c.login) {
10574
+ displayName = commitAuthor.name;
10575
+ }
10502
10576
  if (commitEmail) {
10503
10577
  if (isRealEmail(commitEmail)) {
10504
10578
  profileEmail = commitEmail;
@@ -10577,6 +10651,11 @@ var GithubSCMLib = class extends SCMLib {
10577
10651
  username: c.login
10578
10652
  });
10579
10653
  }
10654
+ contextLogger.info("[GitHub] Contributor resolved", {
10655
+ username: c.login,
10656
+ profileName: displayName,
10657
+ displayNameIsNull: displayName === null
10658
+ });
10580
10659
  return {
10581
10660
  externalId: String(c.id),
10582
10661
  username: c.login ?? null,
@@ -12355,12 +12434,20 @@ var StubSCMLib = class extends SCMLib {
12355
12434
  };
12356
12435
 
12357
12436
  // src/features/analysis/scm/scmFactory.ts
12358
- async function createScmLib({ url, accessToken, scmType, scmOrg }, { propagateExceptions = false, skipValidation = false } = {}) {
12437
+ async function createScmLib({ url, accessToken, scmType, scmOrg }, {
12438
+ propagateExceptions = false,
12439
+ skipValidation = false,
12440
+ enableThrottling = false,
12441
+ githubUserProfileCache
12442
+ } = {}) {
12359
12443
  const trimmedUrl = url ? url.trim().replace(/\/$/, "").replace(/.git$/i, "") : void 0;
12360
12444
  try {
12361
12445
  switch (scmType) {
12362
12446
  case "GITHUB" /* GITHUB */: {
12363
- const scm = new GithubSCMLib(trimmedUrl, accessToken, scmOrg);
12447
+ const scm = new GithubSCMLib(trimmedUrl, accessToken, scmOrg, {
12448
+ enableThrottling,
12449
+ userProfileCache: githubUserProfileCache
12450
+ });
12364
12451
  if (!skipValidation) await scm.validateParams();
12365
12452
  return scm;
12366
12453
  }
@@ -19977,7 +20064,7 @@ function createLogger(config2) {
19977
20064
 
19978
20065
  // src/features/claude_code/hook_logger.ts
19979
20066
  var DD_RUM_TOKEN = true ? "pubf59c0182545bfb4c299175119f1abf9b" : "";
19980
- var CLI_VERSION = true ? "1.4.30" : "unknown";
20067
+ var CLI_VERSION = true ? "1.4.31" : "unknown";
19981
20068
  var NAMESPACE = "mobbdev-claude-code-hook-logs";
19982
20069
  var claudeCodeVersion;
19983
20070
  function buildDdTags() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mobbdev",
3
- "version": "1.4.30",
3
+ "version": "1.4.31",
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",