azdo-cli 0.22.0-develop.782 → 0.22.0-develop.787
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 -1
- package/dist/index.js +141 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -85,10 +85,11 @@ azdo pr status --pr-number 64 # same view for one PR by number, any st
|
|
|
85
85
|
azdo pr comment-resolve 17 --pr-number 64 # idempotent: exit 0 even when already resolved
|
|
86
86
|
azdo pr comment-reopen 17 --pr-number 64
|
|
87
87
|
|
|
88
|
-
# Write to a PR — new thread, in-place edit, reply
|
|
88
|
+
# Write to a PR — new thread, in-place edit, delete, reply
|
|
89
89
|
azdo pr comments add --file plan.md --pr-number 64 --dry-run # preview, writes nothing
|
|
90
90
|
azdo pr comments add --file plan.md --pr-number 64 # NEW thread on the overview
|
|
91
91
|
azdo pr comments edit 148 --file plan.md --pr-number 64 # rewrite it in place
|
|
92
|
+
azdo pr comments delete 148 --comment-id 3 --pr-number 64 # delete a comment (irreversible; no prompt)
|
|
92
93
|
azdo pr comments reply 148 "Great suggestion, I'll address it." # human-readable output
|
|
93
94
|
azdo pr comments reply 148 "Done." --pr-number 64 --json # JSON: { pullRequestId, threadId, commentId, content }
|
|
94
95
|
azdo pr comment-reply 148 "Done." --pr-number 64 # flat alias, identical behaviour
|
package/dist/index.js
CHANGED
|
@@ -4105,6 +4105,19 @@ async function updateThreadComment(context, repo, cred, prId, threadId, commentI
|
|
|
4105
4105
|
publishedAt: data.publishedDate ?? null
|
|
4106
4106
|
};
|
|
4107
4107
|
}
|
|
4108
|
+
async function deleteThreadComment(context, repo, cred, prId, threadId, commentId) {
|
|
4109
|
+
const url = new URL(
|
|
4110
|
+
`https://dev.azure.com/${encodeURIComponent(context.org)}/${encodeURIComponent(context.project)}/_apis/git/repositories/${encodeURIComponent(repo)}/pullRequests/${prId}/threads/${threadId}/comments/${commentId}`
|
|
4111
|
+
);
|
|
4112
|
+
url.searchParams.set("api-version", "7.1");
|
|
4113
|
+
const response = await fetchWithErrors(url.toString(), {
|
|
4114
|
+
method: "DELETE",
|
|
4115
|
+
headers: authHeaders(cred)
|
|
4116
|
+
});
|
|
4117
|
+
if (!response.ok) {
|
|
4118
|
+
throw httpError(response);
|
|
4119
|
+
}
|
|
4120
|
+
}
|
|
4108
4121
|
async function postThreadComment(context, repo, cred, prId, threadId, content) {
|
|
4109
4122
|
const response = await fetchWithErrors(buildThreadCommentUrl(context, repo, prId, threadId).toString(), {
|
|
4110
4123
|
method: "POST",
|
|
@@ -5229,6 +5242,7 @@ function createPrCommentsCommand() {
|
|
|
5229
5242
|
command.addCommand(createPrCommentsReplyCommand());
|
|
5230
5243
|
command.addCommand(createPrCommentsAddCommand());
|
|
5231
5244
|
command.addCommand(createPrCommentsEditCommand());
|
|
5245
|
+
command.addCommand(createPrCommentsDeleteCommand());
|
|
5232
5246
|
return command;
|
|
5233
5247
|
}
|
|
5234
5248
|
function parseTargetPrNumber(options) {
|
|
@@ -5547,7 +5561,26 @@ function createPrCommentAddCommand() {
|
|
|
5547
5561
|
'Post a new comment thread on the pull request overview (alias of "azdo pr comments add")'
|
|
5548
5562
|
);
|
|
5549
5563
|
}
|
|
5550
|
-
|
|
5564
|
+
function parseExplicitCommentId(options) {
|
|
5565
|
+
if (options.commentId === void 0) {
|
|
5566
|
+
return null;
|
|
5567
|
+
}
|
|
5568
|
+
const parsed = parsePositivePrNumber(options.commentId);
|
|
5569
|
+
if (parsed === null) {
|
|
5570
|
+
writeError(`Invalid --comment-id "${options.commentId}"; expected a positive integer.`);
|
|
5571
|
+
return "invalid";
|
|
5572
|
+
}
|
|
5573
|
+
return parsed;
|
|
5574
|
+
}
|
|
5575
|
+
function findCommentInThread(thread, commentId, target) {
|
|
5576
|
+
const match = thread.comments.find((comment) => comment.id === commentId);
|
|
5577
|
+
if (match === void 0) {
|
|
5578
|
+
writeError(`Comment #${commentId} not found in thread #${target.threadId} on pull request #${target.pullRequest.id}.`, EXIT_NOT_FOUND);
|
|
5579
|
+
return null;
|
|
5580
|
+
}
|
|
5581
|
+
return match;
|
|
5582
|
+
}
|
|
5583
|
+
async function fetchTargetThread(target) {
|
|
5551
5584
|
try {
|
|
5552
5585
|
return await getPullRequestThread(
|
|
5553
5586
|
target.context,
|
|
@@ -5566,12 +5599,7 @@ async function fetchThreadForEdit(target) {
|
|
|
5566
5599
|
}
|
|
5567
5600
|
function selectEditableComment(thread, explicitCommentId, target) {
|
|
5568
5601
|
if (explicitCommentId !== null) {
|
|
5569
|
-
|
|
5570
|
-
if (match === void 0) {
|
|
5571
|
-
writeError(`Comment #${explicitCommentId} not found in thread #${target.threadId} on pull request #${target.pullRequest.id}.`, EXIT_NOT_FOUND);
|
|
5572
|
-
return null;
|
|
5573
|
-
}
|
|
5574
|
-
return match;
|
|
5602
|
+
return findCommentInThread(thread, explicitCommentId, target);
|
|
5575
5603
|
}
|
|
5576
5604
|
const first = [...thread.comments].sort((a, b) => a.id - b.id)[0];
|
|
5577
5605
|
if (first === void 0) {
|
|
@@ -5606,13 +5634,9 @@ async function runCommentEdit(threadIdRaw, text, options) {
|
|
|
5606
5634
|
if (body === null) {
|
|
5607
5635
|
return;
|
|
5608
5636
|
}
|
|
5609
|
-
|
|
5610
|
-
if (
|
|
5611
|
-
|
|
5612
|
-
if (explicitCommentId === null) {
|
|
5613
|
-
writeError(`Invalid --comment-id "${options.commentId}"; expected a positive integer.`);
|
|
5614
|
-
return;
|
|
5615
|
-
}
|
|
5637
|
+
const explicitCommentId = parseExplicitCommentId(options);
|
|
5638
|
+
if (explicitCommentId === "invalid") {
|
|
5639
|
+
return;
|
|
5616
5640
|
}
|
|
5617
5641
|
const target = await resolveThreadTarget(threadIdRaw, options, {
|
|
5618
5642
|
onContextResolved: (resolved) => {
|
|
@@ -5622,7 +5646,7 @@ async function runCommentEdit(threadIdRaw, text, options) {
|
|
|
5622
5646
|
if (target === null) {
|
|
5623
5647
|
return;
|
|
5624
5648
|
}
|
|
5625
|
-
const thread = await
|
|
5649
|
+
const thread = await fetchTargetThread(target);
|
|
5626
5650
|
if (thread === null) {
|
|
5627
5651
|
return;
|
|
5628
5652
|
}
|
|
@@ -5684,6 +5708,107 @@ function createPrCommentEditCommand() {
|
|
|
5684
5708
|
'Edit an existing pull request comment in place (alias of "azdo pr comments edit")'
|
|
5685
5709
|
);
|
|
5686
5710
|
}
|
|
5711
|
+
function selectDeletableComment(thread, explicitCommentId, target) {
|
|
5712
|
+
if (explicitCommentId !== null) {
|
|
5713
|
+
return findCommentInThread(thread, explicitCommentId, target);
|
|
5714
|
+
}
|
|
5715
|
+
const comments = [...thread.comments].sort((a, b) => a.id - b.id);
|
|
5716
|
+
if (comments.length === 1) {
|
|
5717
|
+
return comments[0];
|
|
5718
|
+
}
|
|
5719
|
+
if (comments.length === 0) {
|
|
5720
|
+
writeError(`Thread #${target.threadId} on pull request #${target.pullRequest.id} has no comment to delete.`, EXIT_NOT_FOUND);
|
|
5721
|
+
return null;
|
|
5722
|
+
}
|
|
5723
|
+
const candidates = comments.map((comment) => `#${comment.id} (${comment.author ?? "Unknown"})`).join(", ");
|
|
5724
|
+
writeError(
|
|
5725
|
+
`Thread #${target.threadId} on pull request #${target.pullRequest.id} holds ${comments.length} comments; pass --comment-id to choose one: ${candidates}.`
|
|
5726
|
+
);
|
|
5727
|
+
return null;
|
|
5728
|
+
}
|
|
5729
|
+
function reportDeleteResult(result, json, comment) {
|
|
5730
|
+
if (json) {
|
|
5731
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
5732
|
+
`);
|
|
5733
|
+
return;
|
|
5734
|
+
}
|
|
5735
|
+
if (result.dryRun) {
|
|
5736
|
+
process.stdout.write(
|
|
5737
|
+
`Dry run: would delete comment #${result.commentId} by ${comment.author ?? "Unknown"} (${comment.content.length} chars) from thread #${result.threadId} on pull request #${result.pullRequestId}.
|
|
5738
|
+
`
|
|
5739
|
+
);
|
|
5740
|
+
return;
|
|
5741
|
+
}
|
|
5742
|
+
process.stdout.write(
|
|
5743
|
+
`Comment #${result.commentId} deleted from thread #${result.threadId} on pull request #${result.pullRequestId}.
|
|
5744
|
+
`
|
|
5745
|
+
);
|
|
5746
|
+
}
|
|
5747
|
+
async function runCommentDelete(threadIdRaw, options) {
|
|
5748
|
+
let context;
|
|
5749
|
+
try {
|
|
5750
|
+
const explicitCommentId = parseExplicitCommentId(options);
|
|
5751
|
+
if (explicitCommentId === "invalid") {
|
|
5752
|
+
return;
|
|
5753
|
+
}
|
|
5754
|
+
const target = await resolveThreadTarget(threadIdRaw, options, {
|
|
5755
|
+
onContextResolved: (resolved) => {
|
|
5756
|
+
context = resolved;
|
|
5757
|
+
}
|
|
5758
|
+
});
|
|
5759
|
+
if (target === null) {
|
|
5760
|
+
return;
|
|
5761
|
+
}
|
|
5762
|
+
const thread = await fetchTargetThread(target);
|
|
5763
|
+
if (thread === null) {
|
|
5764
|
+
return;
|
|
5765
|
+
}
|
|
5766
|
+
const comment = selectDeletableComment(thread, explicitCommentId, target);
|
|
5767
|
+
if (comment === null) {
|
|
5768
|
+
return;
|
|
5769
|
+
}
|
|
5770
|
+
const dryRun = options.dryRun === true;
|
|
5771
|
+
if (!dryRun) {
|
|
5772
|
+
await deleteThreadComment(
|
|
5773
|
+
target.context,
|
|
5774
|
+
target.repo,
|
|
5775
|
+
target.pat,
|
|
5776
|
+
target.pullRequest.id,
|
|
5777
|
+
target.threadId,
|
|
5778
|
+
comment.id
|
|
5779
|
+
);
|
|
5780
|
+
}
|
|
5781
|
+
reportDeleteResult(
|
|
5782
|
+
{
|
|
5783
|
+
pullRequestId: target.pullRequest.id,
|
|
5784
|
+
threadId: target.threadId,
|
|
5785
|
+
commentId: comment.id,
|
|
5786
|
+
deleted: !dryRun,
|
|
5787
|
+
dryRun
|
|
5788
|
+
},
|
|
5789
|
+
options.json === true,
|
|
5790
|
+
comment
|
|
5791
|
+
);
|
|
5792
|
+
} catch (err) {
|
|
5793
|
+
handlePrCommandError(err, context, "write");
|
|
5794
|
+
}
|
|
5795
|
+
}
|
|
5796
|
+
function buildCommentDeleteCommand(name, description) {
|
|
5797
|
+
const command = new Command12(name);
|
|
5798
|
+
withCommonPrOptions(configureUnwrappedHelp(command)).description(description).argument("<threadId>", "numeric id of the thread holding the comment").option("--comment-id <N>", "numeric id of the comment to delete; may be omitted only when the thread holds a single comment").option("--dry-run", "resolve the target comment and print what would be deleted, without deleting anything").option("--pr-number <N>", PR_NUMBER_HELP).option("--json", "output JSON").action(async (threadIdRaw, _options, command2) => {
|
|
5799
|
+
await runCommentDelete(threadIdRaw, mergedPrOptions(command2));
|
|
5800
|
+
});
|
|
5801
|
+
return command;
|
|
5802
|
+
}
|
|
5803
|
+
function createPrCommentsDeleteCommand() {
|
|
5804
|
+
return buildCommentDeleteCommand("delete", "Delete a pull request comment (no confirmation prompt; irreversible)");
|
|
5805
|
+
}
|
|
5806
|
+
function createPrCommentDeleteCommand() {
|
|
5807
|
+
return buildCommentDeleteCommand(
|
|
5808
|
+
"comment-delete",
|
|
5809
|
+
'Delete a pull request comment (alias of "azdo pr comments delete"; no confirmation prompt; irreversible)'
|
|
5810
|
+
);
|
|
5811
|
+
}
|
|
5687
5812
|
var LIST_STATUS_VALUES = ["active", "completed", "abandoned", "all"];
|
|
5688
5813
|
var DEFAULT_LIST_TOP = 25;
|
|
5689
5814
|
function formatPullRequestListEntry(pullRequest) {
|
|
@@ -5949,6 +6074,7 @@ function createPrCommand() {
|
|
|
5949
6074
|
command.addCommand(createPrWorkItemsCommand());
|
|
5950
6075
|
command.addCommand(createPrReviewersCommand());
|
|
5951
6076
|
command.addCommand(createPrCommentEditCommand());
|
|
6077
|
+
command.addCommand(createPrCommentDeleteCommand());
|
|
5952
6078
|
return command;
|
|
5953
6079
|
}
|
|
5954
6080
|
|