paperclip-github-plugin 0.6.0 → 0.6.1

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/README.md CHANGED
@@ -78,6 +78,8 @@ Each mapped project can expose a **Pull Requests** entry in the sidebar that ope
78
78
 
79
79
  Paperclip issue linkage on the queue prefers the GitHub issue that the pull request closes, so imported GitHub issues and delivery work stay connected in the same project view. If a pull request has no closing-issue-backed link yet, the queue falls back to the Paperclip issue created directly from that pull request and updates the table immediately when that create action returns.
80
80
 
81
+ Those pull-request-created Paperclip issues also stay in the scheduled/manual sync loop even when the pull request does not close a GitHub issue. GitHub Sync checks their CI, merge state, and review threads so new failures or unresolved feedback move the Paperclip issue back into active work.
82
+
81
83
  The issue detail panel and sync-created comment annotations also preserve cross-repository linked pull requests, showing those PRs with their real repository path so operators land in the right place on GitHub.
82
84
 
83
85
  ### Agent workflows built in
package/dist/manifest.js CHANGED
@@ -516,7 +516,7 @@ var require2 = createRequire(import.meta.url);
516
516
  var packageJson = require2("../package.json");
517
517
  var DASHBOARD_WIDGET_CAPABILITY = "ui.dashboardWidget.register";
518
518
  var SCHEDULE_TICK_CRON = "* * * * *";
519
- var MANIFEST_VERSION = "0.6.0"?.trim() || typeof packageJson.version === "string" && packageJson.version.trim() || process.env.npm_package_version?.trim() || "0.0.0-dev";
519
+ var MANIFEST_VERSION = "0.6.1"?.trim() || typeof packageJson.version === "string" && packageJson.version.trim() || process.env.npm_package_version?.trim() || "0.0.0-dev";
520
520
  var manifest = {
521
521
  id: GITHUB_SYNC_PLUGIN_ID,
522
522
  apiVersion: 1,
package/dist/worker.js CHANGED
@@ -4262,6 +4262,12 @@ function countImportedIssuesForMappings(importRegistry, mappings) {
4262
4262
  function buildTrackedIssueProgressKey(mapping, githubIssueId) {
4263
4263
  return `${mapping.id}:${githubIssueId}`;
4264
4264
  }
4265
+ function buildTrackedPullRequestIssueProgressKey(mapping, record) {
4266
+ return `${mapping.id}:pull-request:${record.paperclipIssueId}:${buildGitHubPullRequestReferenceKey({
4267
+ number: record.data.githubPullRequestNumber,
4268
+ repositoryUrl: record.data.repositoryUrl
4269
+ })}`;
4270
+ }
4265
4271
  function buildImportedIssueRecord(mapping, issue, paperclipIssueId, importedAt) {
4266
4272
  return {
4267
4273
  mappingId: mapping.id,
@@ -5104,6 +5110,27 @@ function buildSyncFallbackExecutionStatePatch(params) {
5104
5110
  }
5105
5111
  return void 0;
5106
5112
  }
5113
+ function describeGitHubLinkedPullRequestsStatusReason(linkedPullRequests) {
5114
+ const linkedPullRequestSubject = linkedPullRequests.length === 1 ? "the linked pull request" : "linked pull requests";
5115
+ const linkedPullRequestVerb = linkedPullRequests.length === 1 ? "has" : "have";
5116
+ const blockingConditions = [...new Set(
5117
+ linkedPullRequests.flatMap((pullRequest) => listGitHubPullRequestSyncBlockingConditions(pullRequest))
5118
+ )];
5119
+ const hasUnfinishedCi = linkedPullRequests.some((pullRequest) => pullRequest.ciState === "unfinished");
5120
+ const hasUnknownMergeability = linkedPullRequests.some(
5121
+ (pullRequest) => pullRequest.mergeStateStatus === "unknown"
5122
+ );
5123
+ if (blockingConditions.length > 0) {
5124
+ return `${linkedPullRequestSubject} ${linkedPullRequestVerb} ${formatPlainTextList(blockingConditions)}`;
5125
+ }
5126
+ if (hasUnfinishedCi) {
5127
+ return `${linkedPullRequestSubject} still ${linkedPullRequestVerb} unfinished CI jobs`;
5128
+ }
5129
+ if (hasUnknownMergeability) {
5130
+ return `${linkedPullRequestSubject} ${linkedPullRequestVerb} unknown mergeability`;
5131
+ }
5132
+ return `${linkedPullRequestSubject} ${linkedPullRequestVerb} green CI with all review threads resolved`;
5133
+ }
5107
5134
  function describeGitHubStatusTransitionReason(params) {
5108
5135
  const { snapshot, hasTrustedNewComment, maintainerAuthoredImportedIssue } = params;
5109
5136
  if (snapshot.state === "closed") {
@@ -5125,25 +5152,7 @@ function describeGitHubStatusTransitionReason(params) {
5125
5152
  }
5126
5153
  return "the GitHub issue is open with no linked pull requests";
5127
5154
  }
5128
- const linkedPullRequestSubject = snapshot.linkedPullRequests.length === 1 ? "the linked pull request" : "linked pull requests";
5129
- const linkedPullRequestVerb = snapshot.linkedPullRequests.length === 1 ? "has" : "have";
5130
- const blockingConditions = [...new Set(
5131
- snapshot.linkedPullRequests.flatMap((pullRequest) => listGitHubPullRequestSyncBlockingConditions(pullRequest))
5132
- )];
5133
- const hasUnfinishedCi = snapshot.linkedPullRequests.some((pullRequest) => pullRequest.ciState === "unfinished");
5134
- const hasUnknownMergeability = snapshot.linkedPullRequests.some(
5135
- (pullRequest) => pullRequest.mergeStateStatus === "unknown"
5136
- );
5137
- if (blockingConditions.length > 0) {
5138
- return `${linkedPullRequestSubject} ${linkedPullRequestVerb} ${formatPlainTextList(blockingConditions)}`;
5139
- }
5140
- if (hasUnfinishedCi) {
5141
- return `${linkedPullRequestSubject} still ${linkedPullRequestVerb} unfinished CI jobs`;
5142
- }
5143
- if (hasUnknownMergeability) {
5144
- return `${linkedPullRequestSubject} ${linkedPullRequestVerb} unknown mergeability`;
5145
- }
5146
- return `${linkedPullRequestSubject} ${linkedPullRequestVerb} green CI with all review threads resolved`;
5155
+ return describeGitHubLinkedPullRequestsStatusReason(snapshot.linkedPullRequests);
5147
5156
  }
5148
5157
  function buildStatusTransitionCommentAnnotation(params) {
5149
5158
  const { repository, snapshot, previousStatus, nextStatus, reason } = params;
@@ -5186,6 +5195,10 @@ function buildPaperclipIssueStatusTransitionComment(params) {
5186
5195
  })
5187
5196
  };
5188
5197
  }
5198
+ function buildPaperclipPullRequestIssueStatusTransitionComment(params) {
5199
+ const reason = describeGitHubLinkedPullRequestsStatusReason([params.pullRequest]);
5200
+ return `GitHub Sync updated the status from \`${formatPaperclipIssueStatus(params.previousStatus)}\` to \`${formatPaperclipIssueStatus(params.nextStatus)}\` because ${reason}.`;
5201
+ }
5189
5202
  function resolvePaperclipIssueStatus(params) {
5190
5203
  const {
5191
5204
  currentStatus,
@@ -5218,6 +5231,15 @@ function resolvePaperclipIssueStatus(params) {
5218
5231
  }
5219
5232
  return currentStatus;
5220
5233
  }
5234
+ function resolvePaperclipPullRequestIssueStatus(params) {
5235
+ const { currentStatus, pullRequest, hasExecutorHandoffTarget } = params;
5236
+ if (currentStatus === "done" || currentStatus === "cancelled") {
5237
+ return currentStatus;
5238
+ }
5239
+ return resolvePaperclipStatusFromLinkedPullRequests([pullRequest], {
5240
+ preferInProgress: hasExecutorHandoffTarget
5241
+ });
5242
+ }
5221
5243
  async function listLinkedPullRequestsForIssue(octokit, repository, issueNumber) {
5222
5244
  const linkedPullRequests = [];
5223
5245
  const seenPullRequestKeys = /* @__PURE__ */ new Set();
@@ -6531,6 +6553,52 @@ async function listGitHubPullRequestLinkRecords(ctx, query = {}) {
6531
6553
  }
6532
6554
  return records;
6533
6555
  }
6556
+ function doesGitHubPullRequestLinkRecordMatchMapping(record, mapping) {
6557
+ if (record.data.repositoryUrl !== getNormalizedMappingRepositoryUrl(mapping)) {
6558
+ return false;
6559
+ }
6560
+ if (record.data.companyId && record.data.companyId !== mapping.companyId) {
6561
+ return false;
6562
+ }
6563
+ if (record.data.paperclipProjectId && record.data.paperclipProjectId !== mapping.paperclipProjectId) {
6564
+ return false;
6565
+ }
6566
+ return Boolean(mapping.companyId && mapping.paperclipProjectId);
6567
+ }
6568
+ function doesGitHubPullRequestLinkRecordMatchTarget(record, target) {
6569
+ if (!target) {
6570
+ return true;
6571
+ }
6572
+ switch (target.kind) {
6573
+ case "company":
6574
+ return !record.data.companyId || record.data.companyId === target.companyId;
6575
+ case "project":
6576
+ return (!record.data.companyId || record.data.companyId === target.companyId) && (!record.data.paperclipProjectId || record.data.paperclipProjectId === target.projectId);
6577
+ case "issue":
6578
+ return Boolean(target.issueId && record.paperclipIssueId === target.issueId);
6579
+ default:
6580
+ return true;
6581
+ }
6582
+ }
6583
+ async function listGitHubPullRequestIssueLinksForMapping(ctx, mapping, target) {
6584
+ const records = await listGitHubPullRequestLinkRecords(ctx, {
6585
+ ...target?.kind === "issue" && target.issueId ? { paperclipIssueId: target.issueId } : {}
6586
+ });
6587
+ const recordsByKey = /* @__PURE__ */ new Map();
6588
+ for (const record of records) {
6589
+ if (!doesGitHubPullRequestLinkRecordMatchMapping(record, mapping) || !doesGitHubPullRequestLinkRecordMatchTarget(record, target)) {
6590
+ continue;
6591
+ }
6592
+ recordsByKey.set(
6593
+ `${record.paperclipIssueId}:${buildGitHubPullRequestReferenceKey({
6594
+ number: record.data.githubPullRequestNumber,
6595
+ repositoryUrl: record.data.repositoryUrl
6596
+ })}`,
6597
+ record
6598
+ );
6599
+ }
6600
+ return [...recordsByKey.values()];
6601
+ }
6534
6602
  async function findStoredStatusTransitionCommentAnnotation(ctx, params) {
6535
6603
  const issueId = params.issueId.trim();
6536
6604
  const commentId = params.commentId.trim();
@@ -8140,6 +8208,171 @@ async function synchronizePaperclipIssueStatuses(ctx, octokit, repository, mappi
8140
8208
  updatedDescriptionsCount
8141
8209
  };
8142
8210
  }
8211
+ async function synchronizePaperclipPullRequestIssueStatuses(ctx, octokit, mapping, advancedSettings, pullRequestLinks, paperclipApiBaseUrl, pullRequestStatusCache, syncFailureContext, failures, assertNotCancelled, onProgress) {
8212
+ if (!mapping.companyId || !mapping.paperclipProjectId || !ctx.issues || typeof ctx.issues.get !== "function" || typeof ctx.issues.update !== "function") {
8213
+ return {
8214
+ updatedStatusesCount: 0
8215
+ };
8216
+ }
8217
+ let updatedStatusesCount = 0;
8218
+ let completedIssueCount = 0;
8219
+ const mappingCompanyId = mapping.companyId;
8220
+ const mappingProjectId = mapping.paperclipProjectId;
8221
+ const totalIssueCount = pullRequestLinks.length;
8222
+ const queuedIssueWakeups = [];
8223
+ for (const pullRequestLink of pullRequestLinks) {
8224
+ if (assertNotCancelled) {
8225
+ await assertNotCancelled();
8226
+ }
8227
+ try {
8228
+ const pullRequestRepository = requireRepositoryReference(pullRequestLink.data.repositoryUrl);
8229
+ updateSyncFailureContext(syncFailureContext, {
8230
+ phase: "evaluating_github_status",
8231
+ repositoryUrl: pullRequestRepository.url,
8232
+ githubIssueNumber: void 0
8233
+ });
8234
+ const pullRequestResponse = await octokit.rest.pulls.get({
8235
+ owner: pullRequestRepository.owner,
8236
+ repo: pullRequestRepository.repo,
8237
+ pull_number: pullRequestLink.data.githubPullRequestNumber,
8238
+ headers: {
8239
+ "X-GitHub-Api-Version": GITHUB_API_VERSION
8240
+ }
8241
+ });
8242
+ const livePullRequestState = getPullRequestApiState({
8243
+ state: pullRequestResponse.data.state,
8244
+ merged: pullRequestResponse.data.merged
8245
+ }) === "open" ? "open" : "closed";
8246
+ if (livePullRequestState !== pullRequestLink.data.githubPullRequestState || pullRequestResponse.data.html_url !== pullRequestLink.data.githubPullRequestUrl || pullRequestResponse.data.title !== pullRequestLink.data.title) {
8247
+ await upsertGitHubPullRequestLinkRecord(ctx, {
8248
+ companyId: pullRequestLink.data.companyId ?? mappingCompanyId,
8249
+ projectId: pullRequestLink.data.paperclipProjectId ?? mappingProjectId,
8250
+ issueId: pullRequestLink.paperclipIssueId,
8251
+ repositoryUrl: pullRequestRepository.url,
8252
+ pullRequestNumber: pullRequestLink.data.githubPullRequestNumber,
8253
+ pullRequestUrl: pullRequestResponse.data.html_url ?? pullRequestLink.data.githubPullRequestUrl,
8254
+ pullRequestTitle: pullRequestResponse.data.title || pullRequestLink.data.title || `Pull request #${pullRequestLink.data.githubPullRequestNumber}`,
8255
+ pullRequestState: livePullRequestState
8256
+ });
8257
+ }
8258
+ if (livePullRequestState !== "open") {
8259
+ continue;
8260
+ }
8261
+ const pullRequest = await getGitHubPullRequestStatusSnapshot(
8262
+ octokit,
8263
+ pullRequestRepository,
8264
+ pullRequestLink.data.githubPullRequestNumber,
8265
+ pullRequestStatusCache
8266
+ );
8267
+ const paperclipIssue = await ctx.issues.get(pullRequestLink.paperclipIssueId, mapping.companyId);
8268
+ if (!paperclipIssue) {
8269
+ continue;
8270
+ }
8271
+ const paperclipIssueSyncContext = getPaperclipIssueSyncContext(paperclipIssue);
8272
+ const executorTransitionAssignee = resolvePaperclipIssueExecutorAssignee(
8273
+ paperclipIssueSyncContext,
8274
+ advancedSettings
8275
+ );
8276
+ const nextStatus = resolvePaperclipPullRequestIssueStatus({
8277
+ currentStatus: paperclipIssue.status,
8278
+ pullRequest,
8279
+ hasExecutorHandoffTarget: Boolean(executorTransitionAssignee)
8280
+ });
8281
+ const nextTransitionAssignee = resolveSyncTransitionAssignee({
8282
+ nextStatus,
8283
+ syncContext: paperclipIssueSyncContext,
8284
+ advancedSettings
8285
+ });
8286
+ const shouldClearTransitionAssignee = nextStatus === "in_review" && nextTransitionAssignee === null && paperclipIssueSyncContext.assignee !== null;
8287
+ const nextAssigneeChanged = nextTransitionAssignee ? !doesPaperclipIssueAssigneeMatch(paperclipIssueSyncContext.assignee, nextTransitionAssignee.principal) : false;
8288
+ const shouldWakeTransitionAssignee = paperclipIssue.status !== nextStatus && nextTransitionAssignee?.principal.kind === "agent" && isActionablePaperclipIssueStatus(nextStatus) && (nextAssigneeChanged || paperclipIssue.status !== nextStatus);
8289
+ if (paperclipIssue.status === nextStatus) {
8290
+ if (shouldClearTransitionAssignee) {
8291
+ updateSyncFailureContext(syncFailureContext, {
8292
+ phase: "updating_paperclip_status",
8293
+ repositoryUrl: pullRequestRepository.url,
8294
+ githubIssueNumber: void 0
8295
+ });
8296
+ await updatePaperclipIssueState(ctx, {
8297
+ companyId: mapping.companyId,
8298
+ issueId: pullRequestLink.paperclipIssueId,
8299
+ currentStatus: paperclipIssue.status,
8300
+ syncContext: paperclipIssueSyncContext,
8301
+ nextStatus,
8302
+ clearAssignee: true,
8303
+ transitionComment: "",
8304
+ paperclipApiBaseUrl
8305
+ });
8306
+ }
8307
+ continue;
8308
+ }
8309
+ const transitionComment = buildPaperclipPullRequestIssueStatusTransitionComment({
8310
+ previousStatus: paperclipIssue.status,
8311
+ nextStatus,
8312
+ pullRequest
8313
+ });
8314
+ updateSyncFailureContext(syncFailureContext, {
8315
+ phase: "updating_paperclip_status",
8316
+ repositoryUrl: pullRequestRepository.url,
8317
+ githubIssueNumber: void 0
8318
+ });
8319
+ await updatePaperclipIssueState(ctx, {
8320
+ companyId: mapping.companyId,
8321
+ issueId: pullRequestLink.paperclipIssueId,
8322
+ currentStatus: paperclipIssue.status,
8323
+ syncContext: paperclipIssueSyncContext,
8324
+ nextStatus,
8325
+ ...nextTransitionAssignee ? { nextAssignee: nextTransitionAssignee.principal } : {},
8326
+ ...shouldClearTransitionAssignee ? { clearAssignee: true } : {},
8327
+ transitionComment,
8328
+ paperclipApiBaseUrl
8329
+ });
8330
+ updatedStatusesCount += 1;
8331
+ if (shouldWakeTransitionAssignee && nextTransitionAssignee?.principal.kind === "agent") {
8332
+ queuedIssueWakeups.push({
8333
+ assigneeAgentId: nextTransitionAssignee.principal.id,
8334
+ paperclipIssueId: pullRequestLink.paperclipIssueId,
8335
+ reason: STATUS_TRANSITION_WAKE_REASON,
8336
+ mutation: "status_transition",
8337
+ previousStatus: paperclipIssue.status,
8338
+ nextStatus
8339
+ });
8340
+ }
8341
+ } catch (error) {
8342
+ if (isGitHubRateLimitError(error)) {
8343
+ throw error;
8344
+ }
8345
+ recordRecoverableSyncFailure(ctx, failures, error, syncFailureContext);
8346
+ continue;
8347
+ } finally {
8348
+ completedIssueCount += 1;
8349
+ if (onProgress) {
8350
+ await onProgress({
8351
+ pullRequestLink,
8352
+ completedIssueCount,
8353
+ totalIssueCount
8354
+ });
8355
+ }
8356
+ }
8357
+ }
8358
+ await mapWithConcurrency(
8359
+ queuedIssueWakeups,
8360
+ IMPORTED_ISSUE_WAKEUP_CONCURRENCY,
8361
+ async (queuedWakeup) => wakePaperclipIssueAssignee(ctx, {
8362
+ assigneeAgentId: queuedWakeup.assigneeAgentId,
8363
+ paperclipIssueId: queuedWakeup.paperclipIssueId,
8364
+ companyId: mapping.companyId,
8365
+ paperclipApiBaseUrl,
8366
+ reason: queuedWakeup.reason,
8367
+ mutation: queuedWakeup.mutation,
8368
+ previousStatus: queuedWakeup.previousStatus,
8369
+ nextStatus: queuedWakeup.nextStatus
8370
+ })
8371
+ );
8372
+ return {
8373
+ updatedStatusesCount
8374
+ };
8375
+ }
8143
8376
  async function getResolvedConfig(ctx) {
8144
8377
  const [savedConfig, externalConfig] = await Promise.all([
8145
8378
  ctx.config.get(),
@@ -11697,6 +11930,14 @@ async function performSync(ctx, trigger, options = {}) {
11697
11930
  completedTrackedIssueKeys.add(key);
11698
11931
  completedTrackedIssueCount += 1;
11699
11932
  }
11933
+ function markTrackedPullRequestIssueProcessed(mapping, record) {
11934
+ const key = buildTrackedPullRequestIssueProgressKey(mapping, record);
11935
+ if (completedTrackedIssueKeys.has(key)) {
11936
+ return;
11937
+ }
11938
+ completedTrackedIssueKeys.add(key);
11939
+ completedTrackedIssueCount += 1;
11940
+ }
11700
11941
  function recordCompanyBacklogSnapshotsFromPlans(repositoryPlans2) {
11701
11942
  if (options.target?.kind === "project" || options.target?.kind === "issue") {
11702
11943
  return;
@@ -11804,12 +12045,13 @@ async function performSync(ctx, trigger, options = {}) {
11804
12045
  const importRegistryByIssueId = new Map(
11805
12046
  importedIssueRecords.map((entry) => [entry.githubIssueId, entry])
11806
12047
  );
12048
+ const pullRequestLinks = await listGitHubPullRequestIssueLinksForMapping(ctx, mapping, options.target);
11807
12049
  const ensuredPaperclipIssueIds = /* @__PURE__ */ new Map();
11808
12050
  const trackedIssueIds = /* @__PURE__ */ new Set([
11809
12051
  ...issues.map((issue) => issue.id),
11810
12052
  ...importRegistryByIssueId.keys()
11811
12053
  ]);
11812
- const trackedIssueCount = [...trackedIssueIds].filter((issueId) => allIssuesById.has(issueId)).length;
12054
+ const trackedIssueCount = [...trackedIssueIds].filter((issueId) => allIssuesById.has(issueId)).length + pullRequestLinks.length;
11813
12055
  totalTrackedIssueCount += trackedIssueCount;
11814
12056
  syncedIssuesCount = totalTrackedIssueCount;
11815
12057
  currentProgress = {
@@ -11828,6 +12070,7 @@ async function performSync(ctx, trigger, options = {}) {
11828
12070
  allIssues: eligibleIssues,
11829
12071
  issues,
11830
12072
  allIssuesById,
12073
+ pullRequestLinks,
11831
12074
  trackedIssueCount
11832
12075
  });
11833
12076
  } catch (error) {
@@ -11863,7 +12106,7 @@ async function performSync(ctx, trigger, options = {}) {
11863
12106
  for (const plan of repositoryPlans) {
11864
12107
  await throwIfSyncCancelled();
11865
12108
  try {
11866
- const { mapping, advancedSettings, repository, repositoryIndex, allIssuesById, issues } = plan;
12109
+ const { mapping, advancedSettings, repository, repositoryIndex, allIssuesById, issues, pullRequestLinks } = plan;
11867
12110
  const companyId = mapping.companyId;
11868
12111
  let availableLabels = companyId ? companyLabelDirectoryCache.get(companyId) : void 0;
11869
12112
  if (!availableLabels) {
@@ -11916,6 +12159,15 @@ async function performSync(ctx, trigger, options = {}) {
11916
12159
  }
11917
12160
  }
11918
12161
  }
12162
+ for (const pullRequestLink of pullRequestLinks) {
12163
+ const pullRequestRepository = requireRepositoryReference(pullRequestLink.data.repositoryUrl);
12164
+ const entry = openLinkedPullRequestNumbersByRepository.get(pullRequestRepository.url) ?? {
12165
+ repository: pullRequestRepository,
12166
+ numbers: /* @__PURE__ */ new Set()
12167
+ };
12168
+ entry.numbers.add(pullRequestLink.data.githubPullRequestNumber);
12169
+ openLinkedPullRequestNumbersByRepository.set(pullRequestRepository.url, entry);
12170
+ }
11919
12171
  for (const entry of openLinkedPullRequestNumbersByRepository.values()) {
11920
12172
  await warmGitHubPullRequestStatusCache(
11921
12173
  octokit,
@@ -12053,6 +12305,33 @@ async function performSync(ctx, trigger, options = {}) {
12053
12305
  updatedStatusesCount += synchronizationResult.updatedStatusesCount;
12054
12306
  updatedLabelsCount += synchronizationResult.updatedLabelsCount;
12055
12307
  updatedDescriptionsCount += synchronizationResult.updatedDescriptionsCount;
12308
+ const pullRequestSynchronizationResult = await synchronizePaperclipPullRequestIssueStatuses(
12309
+ ctx,
12310
+ octokit,
12311
+ mapping,
12312
+ advancedSettings,
12313
+ pullRequestLinks,
12314
+ paperclipApiBaseUrl,
12315
+ pullRequestStatusCache,
12316
+ failureContext,
12317
+ recoverableFailures,
12318
+ throwIfSyncCancelled,
12319
+ async (progress) => {
12320
+ markTrackedPullRequestIssueProcessed(mapping, progress.pullRequestLink);
12321
+ const pullRequestRepository = requireRepositoryReference(progress.pullRequestLink.data.repositoryUrl);
12322
+ currentProgress = {
12323
+ phase: "syncing",
12324
+ totalRepositoryCount: mappings.length,
12325
+ currentRepositoryIndex: repositoryIndex,
12326
+ currentRepositoryUrl: repository.url,
12327
+ completedIssueCount: completedTrackedIssueCount,
12328
+ totalIssueCount: totalTrackedIssueCount,
12329
+ detailLabel: `Synced pull request #${progress.pullRequestLink.data.githubPullRequestNumber} in ${pullRequestRepository.owner}/${pullRequestRepository.repo}.`
12330
+ };
12331
+ await persistRunningProgress(progress.completedIssueCount === progress.totalIssueCount);
12332
+ }
12333
+ );
12334
+ updatedStatusesCount += pullRequestSynchronizationResult.updatedStatusesCount;
12056
12335
  } catch (error) {
12057
12336
  if (error instanceof SyncCancellationError || isGitHubRateLimitError(error)) {
12058
12337
  throw error;
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "paperclip-github-plugin",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Paperclip plugin for synchronizing GitHub issues into Paperclip projects.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
- "packageManager": "pnpm@10.33.0",
7
+ "packageManager": "pnpm@10.33.2",
8
8
  "engines": {
9
9
  "node": ">=20"
10
10
  },