paperclip-github-plugin 0.9.5 → 0.9.7
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 +2 -0
- package/dist/manifest.js +1 -1
- package/dist/worker.js +59 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -94,6 +94,8 @@ If a Paperclip issue was created locally or by an agent workflow before GitHub S
|
|
|
94
94
|
|
|
95
95
|
Manual GitHub issue links are added to the same import registry and issue-link entity used by normal sync, so future syncs update the Paperclip issue from the GitHub issue. Manual pull request links are added to the PR-link entity used by the project Pull Requests page, so future syncs monitor PR status even when there is no closing GitHub issue.
|
|
96
96
|
|
|
97
|
+
When a Paperclip issue is linked to a GitHub issue and also has older direct pull request links, the GitHub issue remains the status source of truth. Direct pull request links only drive status for PR-only Paperclip issues, which prevents stale merged PR metadata from closing work while the GitHub issue and its current linked PR are still open.
|
|
98
|
+
|
|
97
99
|
Operators can unlink a linked Paperclip issue from the GitHub detail surface when they intentionally want GitHub Sync to stop updating it. Agent-facing tools and native agent API routes can create durable issue and pull request links, but they do not expose an unlink operation; internal sync repair may still tombstone a link when GitHub transfers an issue to an unmapped repository.
|
|
98
100
|
|
|
99
101
|
### Agent workflows built in
|
package/dist/manifest.js
CHANGED
|
@@ -642,7 +642,7 @@ var PULL_REQUEST_ASSET_API_ROUTE_URL_PATH = `/api/plugins/${GITHUB_SYNC_PLUGIN_I
|
|
|
642
642
|
var require2 = createRequire(import.meta.url);
|
|
643
643
|
var packageJson = require2("../package.json");
|
|
644
644
|
var SCHEDULE_TICK_CRON = "* * * * *";
|
|
645
|
-
var MANIFEST_VERSION = "0.9.
|
|
645
|
+
var MANIFEST_VERSION = "0.9.7"?.trim() || typeof packageJson.version === "string" && packageJson.version.trim() || process.env.npm_package_version?.trim() || "0.0.0-dev";
|
|
646
646
|
var manifest = {
|
|
647
647
|
id: GITHUB_SYNC_PLUGIN_ID,
|
|
648
648
|
apiVersion: 1,
|
package/dist/worker.js
CHANGED
|
@@ -5669,7 +5669,16 @@ function resolveSyncTransitionAssignee(params) {
|
|
|
5669
5669
|
}
|
|
5670
5670
|
function isHealthyMaintainerWaitTransition(params) {
|
|
5671
5671
|
const { currentStatus, nextStatus, syncContext } = params;
|
|
5672
|
-
return nextStatus === "in_review" && (currentStatus === "done" || currentStatus === "in_review") && syncContext.executionState
|
|
5672
|
+
return nextStatus === "in_review" && (currentStatus === "done" || currentStatus === "in_review") && isClearableMaintainerWaitExecutionState(syncContext.executionState);
|
|
5673
|
+
}
|
|
5674
|
+
function isClearableMaintainerWaitExecutionState(executionState) {
|
|
5675
|
+
if (executionState === null) {
|
|
5676
|
+
return true;
|
|
5677
|
+
}
|
|
5678
|
+
if (executionState.currentParticipant !== null || executionState.returnAssignee !== null || executionState.currentStageId !== null || executionState.currentStageIndex !== null || executionState.currentStageType !== null || executionState.completedStageIds.length > 0 || executionState.lastDecisionId || executionState.lastDecisionOutcome) {
|
|
5679
|
+
return false;
|
|
5680
|
+
}
|
|
5681
|
+
return !executionState.status || executionState.status === "idle" || executionState.status === "completed";
|
|
5673
5682
|
}
|
|
5674
5683
|
function shouldClearCompletedSyncExecutionPolicy(params) {
|
|
5675
5684
|
return (params.nextStatus === "done" || params.nextStatus === "cancelled") && (params.syncContext.executionPolicy !== null || params.syncContext.executionState !== null);
|
|
@@ -7338,6 +7347,23 @@ async function listGitHubPullRequestIssueLinksForMapping(ctx, mapping, target) {
|
|
|
7338
7347
|
}
|
|
7339
7348
|
return [...recordsByKey.values()];
|
|
7340
7349
|
}
|
|
7350
|
+
async function listGitHubIssueLinkedPaperclipIssueIdsForMapping(ctx, mapping, importedIssueRecords, target) {
|
|
7351
|
+
const issueIds = new Set(
|
|
7352
|
+
importedIssueRecords.map((record) => record.paperclipIssueId).filter(Boolean)
|
|
7353
|
+
);
|
|
7354
|
+
if (target?.kind === "issue" && target.issueId && target.githubIssueNumber) {
|
|
7355
|
+
issueIds.add(target.issueId);
|
|
7356
|
+
}
|
|
7357
|
+
const issueLinks = await listGitHubIssueLinkRecords(ctx, {
|
|
7358
|
+
...target?.kind === "issue" && target.issueId ? { paperclipIssueId: target.issueId } : {}
|
|
7359
|
+
});
|
|
7360
|
+
for (const record of issueLinks) {
|
|
7361
|
+
if (doesGitHubIssueLinkRecordMatchMapping(record, mapping) && doesGitHubIssueLinkRecordMatchTarget(record, target)) {
|
|
7362
|
+
issueIds.add(record.paperclipIssueId);
|
|
7363
|
+
}
|
|
7364
|
+
}
|
|
7365
|
+
return issueIds;
|
|
7366
|
+
}
|
|
7341
7367
|
function doesGitHubIssueLinkRecordMatchMapping(record, mapping) {
|
|
7342
7368
|
if (record.data.repositoryUrl !== getNormalizedMappingRepositoryUrl(mapping)) {
|
|
7343
7369
|
return false;
|
|
@@ -7375,6 +7401,7 @@ async function listExternalGitHubLinkSyncWork(ctx, mappings, target) {
|
|
|
7375
7401
|
const syncableMappings = getSyncableMappingsForTarget(mappings, target);
|
|
7376
7402
|
const issueLinksByKey = /* @__PURE__ */ new Map();
|
|
7377
7403
|
const pullRequestLinksByKey = /* @__PURE__ */ new Map();
|
|
7404
|
+
const issueLinkedPaperclipIssueIds = /* @__PURE__ */ new Set();
|
|
7378
7405
|
const [issueLinks, pullRequestLinks] = await Promise.all([
|
|
7379
7406
|
listGitHubIssueLinkRecords(ctx, {
|
|
7380
7407
|
...target?.kind === "issue" && target.issueId ? { paperclipIssueId: target.issueId } : {}
|
|
@@ -7384,7 +7411,11 @@ async function listExternalGitHubLinkSyncWork(ctx, mappings, target) {
|
|
|
7384
7411
|
})
|
|
7385
7412
|
]);
|
|
7386
7413
|
for (const record of issueLinks) {
|
|
7387
|
-
if (!doesGitHubIssueLinkRecordMatchTarget(record, target)
|
|
7414
|
+
if (!doesGitHubIssueLinkRecordMatchTarget(record, target)) {
|
|
7415
|
+
continue;
|
|
7416
|
+
}
|
|
7417
|
+
issueLinkedPaperclipIssueIds.add(record.paperclipIssueId);
|
|
7418
|
+
if (isGitHubIssueLinkCoveredByMappings(record, syncableMappings)) {
|
|
7388
7419
|
continue;
|
|
7389
7420
|
}
|
|
7390
7421
|
issueLinksByKey.set(
|
|
@@ -7393,7 +7424,7 @@ async function listExternalGitHubLinkSyncWork(ctx, mappings, target) {
|
|
|
7393
7424
|
);
|
|
7394
7425
|
}
|
|
7395
7426
|
for (const record of pullRequestLinks) {
|
|
7396
|
-
if (!doesGitHubPullRequestLinkRecordMatchTarget(record, target) || isGitHubPullRequestLinkCoveredByMappings(record, syncableMappings)) {
|
|
7427
|
+
if (!doesGitHubPullRequestLinkRecordMatchTarget(record, target) || issueLinkedPaperclipIssueIds.has(record.paperclipIssueId) || isGitHubPullRequestLinkCoveredByMappings(record, syncableMappings)) {
|
|
7397
7428
|
continue;
|
|
7398
7429
|
}
|
|
7399
7430
|
pullRequestLinksByKey.set(
|
|
@@ -8973,6 +9004,24 @@ async function updatePaperclipIssueState(ctx, params) {
|
|
|
8973
9004
|
});
|
|
8974
9005
|
if (!payloadResult.failure) {
|
|
8975
9006
|
issueUpdated = true;
|
|
9007
|
+
if (issuePatch.executionState === null && ctx.issues && typeof ctx.issues.update === "function") {
|
|
9008
|
+
try {
|
|
9009
|
+
await ctx.issues.update(
|
|
9010
|
+
issueId,
|
|
9011
|
+
{ executionState: null },
|
|
9012
|
+
companyId
|
|
9013
|
+
);
|
|
9014
|
+
} catch (error) {
|
|
9015
|
+
issueUpdated = false;
|
|
9016
|
+
ctx.logger.warn("GitHub sync could not clear Paperclip issue execution state after the local API update. Falling back to direct issue mutation.", {
|
|
9017
|
+
companyId,
|
|
9018
|
+
issueId,
|
|
9019
|
+
paperclipApiBaseUrl,
|
|
9020
|
+
nextStatus,
|
|
9021
|
+
error: getErrorMessage(error)
|
|
9022
|
+
});
|
|
9023
|
+
}
|
|
9024
|
+
}
|
|
8976
9025
|
}
|
|
8977
9026
|
if (payloadResult.failure && (payloadResult.failure.status ?? response.status) !== 404 && (payloadResult.failure.status ?? response.status) !== 405) {
|
|
8978
9027
|
logPaperclipIssueStatusUpdateFailure(ctx, {
|
|
@@ -14115,7 +14164,13 @@ async function performSync(ctx, trigger, options = {}) {
|
|
|
14115
14164
|
const importRegistryByIssueId = new Map(
|
|
14116
14165
|
importedIssueRecords.map((entry) => [entry.githubIssueId, entry])
|
|
14117
14166
|
);
|
|
14118
|
-
const
|
|
14167
|
+
const githubIssueLinkedPaperclipIssueIds = await listGitHubIssueLinkedPaperclipIssueIdsForMapping(
|
|
14168
|
+
ctx,
|
|
14169
|
+
mapping,
|
|
14170
|
+
importedIssueRecords,
|
|
14171
|
+
options.target
|
|
14172
|
+
);
|
|
14173
|
+
const pullRequestLinks = (await listGitHubPullRequestIssueLinksForMapping(ctx, mapping, options.target)).filter((record) => !githubIssueLinkedPaperclipIssueIds.has(record.paperclipIssueId));
|
|
14119
14174
|
const ensuredPaperclipIssueIds = /* @__PURE__ */ new Map();
|
|
14120
14175
|
const trackedIssueIds = /* @__PURE__ */ new Set([
|
|
14121
14176
|
...issues.map((issue) => issue.id),
|