azdo-cli 0.10.0-develop.507 → 0.10.0-develop.526
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 +5 -0
- package/dist/index.js +85 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -62,6 +62,11 @@ azdo pr status # PR checks (status + branch policies +
|
|
|
62
62
|
azdo pr comment-resolve 17 --pr-number 64 # idempotent: exit 0 even when already resolved
|
|
63
63
|
azdo pr comment-reopen 17 --pr-number 64
|
|
64
64
|
|
|
65
|
+
# Reply to a PR comment thread
|
|
66
|
+
azdo pr comments reply 148 "Great suggestion, I'll address it." # human-readable output
|
|
67
|
+
azdo pr comments reply 148 "Done." --pr-number 64 --json # JSON: { pullRequestId, threadId, commentId, content }
|
|
68
|
+
azdo pr comment-reply 148 "Done." --pr-number 64 # flat alias, identical behaviour
|
|
69
|
+
|
|
65
70
|
# Pipelines — list, inspect runs, wait (exit code = result), start
|
|
66
71
|
azdo pipeline list --filter ci
|
|
67
72
|
azdo pipeline get-runs 12 --branch develop --limit 1
|
package/dist/index.js
CHANGED
|
@@ -624,7 +624,7 @@ function findDotEnvPat(startDir = process.cwd()) {
|
|
|
624
624
|
if (existsSync(envFile)) {
|
|
625
625
|
const contents = readFileSync2(envFile, "utf8");
|
|
626
626
|
for (const line of contents.split("\n")) {
|
|
627
|
-
const match = line.match(/^AZDO_PAT\s
|
|
627
|
+
const match = line.match(/^AZDO_PAT\s*=([^\n\r]+)$/);
|
|
628
628
|
if (match) {
|
|
629
629
|
const value = match[1].trim().replace(/^["']|["']$/g, "");
|
|
630
630
|
if (value.length > 0) return value;
|
|
@@ -3188,6 +3188,30 @@ async function getPullRequestThreads(context, repo, cred, prId) {
|
|
|
3188
3188
|
const data = await readJsonResponse(response);
|
|
3189
3189
|
return data.value.map(mapThread).filter((thread) => thread !== null);
|
|
3190
3190
|
}
|
|
3191
|
+
function buildThreadCommentUrl(context, repo, prId, threadId) {
|
|
3192
|
+
const url = new URL(
|
|
3193
|
+
`https://dev.azure.com/${encodeURIComponent(context.org)}/${encodeURIComponent(context.project)}/_apis/git/repositories/${encodeURIComponent(repo)}/pullRequests/${prId}/threads/${threadId}/comments`
|
|
3194
|
+
);
|
|
3195
|
+
url.searchParams.set("api-version", "7.1");
|
|
3196
|
+
return url;
|
|
3197
|
+
}
|
|
3198
|
+
async function postThreadComment(context, repo, cred, prId, threadId, content) {
|
|
3199
|
+
const response = await fetchWithErrors(buildThreadCommentUrl(context, repo, prId, threadId).toString(), {
|
|
3200
|
+
method: "POST",
|
|
3201
|
+
headers: {
|
|
3202
|
+
...authHeaders(cred),
|
|
3203
|
+
"Content-Type": "application/json"
|
|
3204
|
+
},
|
|
3205
|
+
body: JSON.stringify({ content, parentCommentId: 0, commentType: 1 })
|
|
3206
|
+
});
|
|
3207
|
+
const data = await readJsonResponse(response);
|
|
3208
|
+
return {
|
|
3209
|
+
id: data.id,
|
|
3210
|
+
author: data.author?.displayName ?? null,
|
|
3211
|
+
content: data.content ?? content,
|
|
3212
|
+
publishedAt: data.publishedDate ?? null
|
|
3213
|
+
};
|
|
3214
|
+
}
|
|
3191
3215
|
|
|
3192
3216
|
// src/commands/pr.ts
|
|
3193
3217
|
function parsePositivePrNumber(raw) {
|
|
@@ -3539,6 +3563,7 @@ function createPrCommentsCommand() {
|
|
|
3539
3563
|
handlePrCommandError(err, context, "read");
|
|
3540
3564
|
}
|
|
3541
3565
|
});
|
|
3566
|
+
command.addCommand(createPrCommentsReplyCommand());
|
|
3542
3567
|
return command;
|
|
3543
3568
|
}
|
|
3544
3569
|
async function resolveThreadTarget(threadIdRaw, options) {
|
|
@@ -3657,6 +3682,64 @@ function createPrCommentReopenCommand() {
|
|
|
3657
3682
|
});
|
|
3658
3683
|
return command;
|
|
3659
3684
|
}
|
|
3685
|
+
async function runCommentReply(threadIdRaw, text, options) {
|
|
3686
|
+
let context;
|
|
3687
|
+
try {
|
|
3688
|
+
const trimmedText = text.trim();
|
|
3689
|
+
if (!trimmedText) {
|
|
3690
|
+
writeError("Reply text must not be empty.");
|
|
3691
|
+
return;
|
|
3692
|
+
}
|
|
3693
|
+
const target = await resolveThreadTarget(threadIdRaw, options);
|
|
3694
|
+
if (target === null) {
|
|
3695
|
+
return;
|
|
3696
|
+
}
|
|
3697
|
+
context = target.context;
|
|
3698
|
+
const threads = await getPullRequestThreads(target.context, target.repo, target.pat, target.pullRequest.id);
|
|
3699
|
+
const thread = threads.find((t) => t.id === target.threadId);
|
|
3700
|
+
if (!thread) {
|
|
3701
|
+
writeError(`Thread #${target.threadId} not found on pull request #${target.pullRequest.id}.`);
|
|
3702
|
+
return;
|
|
3703
|
+
}
|
|
3704
|
+
const posted = await postThreadComment(
|
|
3705
|
+
target.context,
|
|
3706
|
+
target.repo,
|
|
3707
|
+
target.pat,
|
|
3708
|
+
target.pullRequest.id,
|
|
3709
|
+
target.threadId,
|
|
3710
|
+
trimmedText
|
|
3711
|
+
);
|
|
3712
|
+
const result = {
|
|
3713
|
+
pullRequestId: target.pullRequest.id,
|
|
3714
|
+
threadId: target.threadId,
|
|
3715
|
+
commentId: posted.id,
|
|
3716
|
+
content: posted.content
|
|
3717
|
+
};
|
|
3718
|
+
if (options.json) {
|
|
3719
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
3720
|
+
`);
|
|
3721
|
+
return;
|
|
3722
|
+
}
|
|
3723
|
+
process.stdout.write(`Reply posted to thread #${target.threadId} on pull request #${target.pullRequest.id}.
|
|
3724
|
+
`);
|
|
3725
|
+
} catch (err) {
|
|
3726
|
+
handlePrCommandError(err, context, "write");
|
|
3727
|
+
}
|
|
3728
|
+
}
|
|
3729
|
+
function createPrCommentsReplyCommand() {
|
|
3730
|
+
const command = new Command12("reply");
|
|
3731
|
+
configureUnwrappedHelp(command).description("Post a reply to a pull request comment thread").argument("<threadId>", "numeric id of the thread to reply to").argument("<text>", "text of the reply").option("--org <org>", "Azure DevOps organization").option("--project <project>", "Azure DevOps project").option("--pr-number <N>", PR_NUMBER_HELP).option("--json", "output JSON").action(async (threadIdRaw, text, options) => {
|
|
3732
|
+
await runCommentReply(threadIdRaw, text, options);
|
|
3733
|
+
});
|
|
3734
|
+
return command;
|
|
3735
|
+
}
|
|
3736
|
+
function createPrCommentReplyCommand() {
|
|
3737
|
+
const command = new Command12("comment-reply");
|
|
3738
|
+
configureUnwrappedHelp(command).description('Post a reply to a pull request comment thread (alias of "azdo pr comments reply")').argument("<threadId>", "numeric id of the thread to reply to").argument("<text>", "text of the reply").option("--org <org>", "Azure DevOps organization").option("--project <project>", "Azure DevOps project").option("--pr-number <N>", PR_NUMBER_HELP).option("--json", "output JSON").action(async (threadIdRaw, text, options) => {
|
|
3739
|
+
await runCommentReply(threadIdRaw, text, options);
|
|
3740
|
+
});
|
|
3741
|
+
return command;
|
|
3742
|
+
}
|
|
3660
3743
|
function createPrCommand() {
|
|
3661
3744
|
const command = new Command12("pr");
|
|
3662
3745
|
command.description("Manage Azure DevOps pull requests");
|
|
@@ -3665,6 +3748,7 @@ function createPrCommand() {
|
|
|
3665
3748
|
command.addCommand(createPrCommentsCommand());
|
|
3666
3749
|
command.addCommand(createPrCommentResolveCommand());
|
|
3667
3750
|
command.addCommand(createPrCommentReopenCommand());
|
|
3751
|
+
command.addCommand(createPrCommentReplyCommand());
|
|
3668
3752
|
return command;
|
|
3669
3753
|
}
|
|
3670
3754
|
|