azdo-cli 0.5.0-010-work-item-comments.149 → 0.5.0-develop.148

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 (3) hide show
  1. package/README.md +0 -39
  2. package/dist/index.js +2 -169
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -13,7 +13,6 @@ Azure DevOps CLI focused on work item read/write workflows.
13
13
  - Assign and unassign work items (`assign`)
14
14
  - Set any work item field by reference name (`set-field`)
15
15
  - Create or update work items from markdown documents (`upsert`)
16
- - Read and post work item comments (`comments`)
17
16
  - Read rich-text fields as markdown (`get-md-field`)
18
17
  - Set rich-text fields as markdown from inline text, file, or stdin (`set-md-field`)
19
18
  - Check branch pull request status, open PRs to `develop`, and review active comments (`pr`)
@@ -68,10 +67,6 @@ azdo set-state 12345 "Active"
68
67
 
69
68
  # 4) Create or update a work item from markdown
70
69
  azdo upsert --type "User Story" --content $'---\nTitle: Improve markdown import UX\nState: New\n---'
71
-
72
- # 5) Review work item discussion and post an update
73
- azdo comments list 12345
74
- azdo comments add 12345 "Investigating the root cause now."
75
70
  ```
76
71
 
77
72
  ## Command Cheat Sheet
@@ -83,7 +78,6 @@ azdo comments add 12345 "Investigating the root cause now."
83
78
  | `azdo assign <id> [name]` | Assign or unassign owner | `--unassign`, `--json`, `--org`, `--project` |
84
79
  | `azdo set-field <id> <field> <value>` | Update any field | `--json`, `--org`, `--project` |
85
80
  | `azdo upsert [id]` | Create or update a work item from markdown | `--content`, `--file`, `--type`, `--json`, `--org`, `--project` |
86
- | `azdo comments <subcommand>` | Read or add work item comments | `list`, `add`, `--json`, `--org`, `--project` |
87
81
  | `azdo get-md-field <id> <field>` | Get field as markdown | `--org`, `--project` |
88
82
  | `azdo set-md-field <id> <field> [content]` | Set markdown field | `--file`, `--json`, `--org`, `--project` |
89
83
  | `azdo list-fields <id>` | List all fields of a work item | `--json`, `--org`, `--project` |
@@ -193,38 +187,6 @@ azdo pr comments
193
187
  - Prints `Pull request #<id> has no active comments.` when the PR has no active comment threads
194
188
  - Fails instead of guessing when no active PR or multiple active PRs exist
195
189
 
196
- ### Work Item Comment Commands
197
-
198
- The `comments` command group works on a specific work item ID. It requires a PAT with `Work Items (read)` scope for listing comments and `Work Items (Read & Write)` to add a new comment.
199
-
200
- ```bash
201
- # Read the visible comment history for a work item
202
- azdo comments list 12345
203
-
204
- # Read the same history as JSON
205
- azdo comments list 12345 --json
206
-
207
- # Post a progress update
208
- azdo comments add 12345 "Investigation complete. Working on the fix next."
209
-
210
- # Post the update and return JSON
211
- azdo comments add 12345 "Queued validation run." --json
212
- ```
213
-
214
- `azdo comments list`
215
-
216
- - Resolves the target work item directly from the provided ID
217
- - Retrieves the full visible comment history and follows Azure DevOps pagination internally
218
- - Prints comments newest first with comment ID, author, timestamp, and body text
219
- - Prints `Work item #<id> has no comments.` when the work item has no visible comments
220
-
221
- `azdo comments add`
222
-
223
- - Requires a non-empty `<text>` positional argument
224
- - Preserves the supplied comment text as the submitted body
225
- - Prints `Added comment #<commentId> to work item #<id>` on success
226
- - Fails locally before any API call when the text is empty or whitespace-only
227
-
228
190
  ## azdo upsert
229
191
 
230
192
  `azdo upsert` accepts a single markdown work-item document and either creates a new Azure DevOps work item or updates an existing one. Omit `[id]` to create; pass `[id]` to update that work item in place. Create mode defaults to `Task`, and `--type <work item type>` lets you create `Bug`, `User Story`, `Feature`, `Epic`, and other Azure DevOps work item types.
@@ -350,7 +312,6 @@ These commands support `--json` for machine-readable output:
350
312
  - `set-field`
351
313
  - `set-md-field`
352
314
  - `upsert`
353
- - `comments list|add`
354
315
  - `pr status|open|comments`
355
316
  - `config set|get|list|unset`
356
317
 
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { Command as Command13 } from "commander";
4
+ import { Command as Command12 } from "commander";
5
5
 
6
6
  // src/version.ts
7
7
  import { readFileSync } from "fs";
@@ -96,42 +96,6 @@ function writeHeaders(pat) {
96
96
  "Content-Type": "application/json-patch+json"
97
97
  };
98
98
  }
99
- function buildWorkItemCommentsListUrl(context, id, continuationToken) {
100
- const url = new URL(
101
- `https://dev.azure.com/${encodeURIComponent(context.org)}/${encodeURIComponent(context.project)}/_apis/wit/workItems/${id}/comments`
102
- );
103
- url.searchParams.set("api-version", "7.1-preview.4");
104
- url.searchParams.set("order", "desc");
105
- if (continuationToken) {
106
- url.searchParams.set("continuationToken", continuationToken);
107
- }
108
- return url;
109
- }
110
- function buildWorkItemCommentsUrl(context, id) {
111
- const url = new URL(
112
- `https://dev.azure.com/${encodeURIComponent(context.org)}/${encodeURIComponent(context.project)}/_apis/wit/workItems/${id}/comments`
113
- );
114
- url.searchParams.set("api-version", "7.1-preview.4");
115
- return url;
116
- }
117
- function mapWorkItemComment(comment, fallbackWorkItemId) {
118
- return {
119
- id: comment.id ?? comment.commentId ?? 0,
120
- workItemId: comment.workItemId ?? fallbackWorkItemId,
121
- text: typeof comment.text === "string" ? comment.text : "",
122
- author: comment.createdBy?.displayName ?? null,
123
- createdAt: comment.createdDate ?? null,
124
- modifiedAt: comment.modifiedDate ?? null,
125
- isDeleted: comment.isDeleted === true
126
- };
127
- }
128
- function readContinuationToken(response, data) {
129
- if (typeof data.continuationToken === "string" && data.continuationToken.trim() !== "") {
130
- return data.continuationToken;
131
- }
132
- const headerToken = response.headers?.get("x-ms-continuationtoken") ?? response.headers?.get("continuationtoken") ?? null;
133
- return headerToken && headerToken.trim() !== "" ? headerToken : null;
134
- }
135
99
  async function readWriteResponse(response, errorCode) {
136
100
  if (response.status === 400) {
137
101
  const serverMessage = await readResponseMessage(response) ?? "Unknown error";
@@ -240,55 +204,6 @@ async function getWorkItemFieldValue(context, id, pat, fieldName) {
240
204
  }
241
205
  return stringifyFieldValue(value);
242
206
  }
243
- async function listWorkItemComments(context, id, pat) {
244
- const comments = [];
245
- let continuationToken = null;
246
- do {
247
- const response = await fetchWithErrors(
248
- buildWorkItemCommentsListUrl(context, id, continuationToken ?? void 0).toString(),
249
- { headers: authHeaders(pat) }
250
- );
251
- if (!response.ok) {
252
- throw new Error(`HTTP_${response.status}`);
253
- }
254
- const data = await response.json();
255
- comments.push(
256
- ...(data.comments ?? []).map((comment) => mapWorkItemComment(comment, id)).filter((comment) => !comment.isDeleted)
257
- );
258
- continuationToken = readContinuationToken(response, data);
259
- } while (continuationToken !== null);
260
- return {
261
- workItemId: id,
262
- count: comments.length,
263
- comments
264
- };
265
- }
266
- async function addWorkItemComment(context, id, pat, text) {
267
- const response = await fetchWithErrors(buildWorkItemCommentsUrl(context, id).toString(), {
268
- method: "POST",
269
- headers: {
270
- ...authHeaders(pat),
271
- "Content-Type": "application/json"
272
- },
273
- body: JSON.stringify({ text })
274
- });
275
- if (response.status === 400) {
276
- const serverMessage = await readResponseMessage(response) ?? "Unknown error";
277
- throw new Error(`BAD_REQUEST: ${serverMessage}`);
278
- }
279
- if (!response.ok) {
280
- throw new Error(`HTTP_${response.status}`);
281
- }
282
- const data = await response.json();
283
- return {
284
- workItemId: data.workItemId ?? id,
285
- commentId: data.commentId ?? data.id ?? 0,
286
- text: typeof data.text === "string" ? data.text : text,
287
- author: data.createdBy?.displayName ?? null,
288
- createdAt: data.createdDate ?? null,
289
- url: data.url ?? null
290
- };
291
- }
292
207
  async function updateWorkItem(context, id, pat, fieldName, operations) {
293
208
  const result = await applyWorkItemPatch(context, id, pat, operations);
294
209
  const title = result.fields["System.Title"];
@@ -1965,89 +1880,8 @@ function createPrCommand() {
1965
1880
  return command;
1966
1881
  }
1967
1882
 
1968
- // src/commands/comments.ts
1969
- import { Command as Command12 } from "commander";
1970
- function writeError2(message) {
1971
- process.stderr.write(`Error: ${message}
1972
- `);
1973
- process.exit(1);
1974
- }
1975
- function formatCommentHeader(comment) {
1976
- const author = comment.author ?? "Unknown";
1977
- const timestamp = comment.modifiedAt ?? comment.createdAt ?? "Unknown time";
1978
- return `Comment #${comment.id} by ${author} at ${timestamp}`;
1979
- }
1980
- function formatComments(result) {
1981
- const lines = [`Comments for work item #${result.workItemId}`];
1982
- for (const comment of result.comments) {
1983
- lines.push("", formatCommentHeader(comment), comment.text);
1984
- }
1985
- return lines.join("\n");
1986
- }
1987
- function createCommentsListCommand() {
1988
- const command = new Command12("list");
1989
- command.description("List visible comments for a work item").argument("<id>", "work item ID").option("--org <org>", "Azure DevOps organization").option("--project <project>", "Azure DevOps project").option("--json", "output JSON").action(async (idStr, options) => {
1990
- validateOrgProjectPair(options);
1991
- const id = parseWorkItemId(idStr);
1992
- let context;
1993
- try {
1994
- context = resolveContext(options);
1995
- const credential = await resolvePat();
1996
- const result = await listWorkItemComments(context, id, credential.pat);
1997
- if (options.json) {
1998
- process.stdout.write(`${JSON.stringify(result, null, 2)}
1999
- `);
2000
- return;
2001
- }
2002
- if (result.comments.length === 0) {
2003
- process.stdout.write(`Work item #${id} has no comments.
2004
- `);
2005
- return;
2006
- }
2007
- process.stdout.write(`${formatComments(result)}
2008
- `);
2009
- } catch (err) {
2010
- handleCommandError(err, id, context, "read");
2011
- }
2012
- });
2013
- return command;
2014
- }
2015
- function createCommentsAddCommand() {
2016
- const command = new Command12("add");
2017
- command.description("Add a comment to a work item").argument("<id>", "work item ID").argument("<text>", "comment text").option("--org <org>", "Azure DevOps organization").option("--project <project>", "Azure DevOps project").option("--json", "output JSON").action(async (idStr, text, options) => {
2018
- validateOrgProjectPair(options);
2019
- const id = parseWorkItemId(idStr);
2020
- if (text.trim() === "") {
2021
- writeError2("Comment text must be a non-empty string.");
2022
- }
2023
- let context;
2024
- try {
2025
- context = resolveContext(options);
2026
- const credential = await resolvePat();
2027
- const result = await addWorkItemComment(context, id, credential.pat, text);
2028
- if (options.json) {
2029
- process.stdout.write(`${JSON.stringify(result, null, 2)}
2030
- `);
2031
- return;
2032
- }
2033
- process.stdout.write(`Added comment #${result.commentId} to work item #${result.workItemId}
2034
- `);
2035
- } catch (err) {
2036
- handleCommandError(err, id, context, "write");
2037
- }
2038
- });
2039
- return command;
2040
- }
2041
- function createCommentsCommand() {
2042
- const command = new Command12("comments");
2043
- command.description("Manage Azure DevOps work item comments");
2044
- command.addCommand(createCommentsListCommand());
2045
- command.addCommand(createCommentsAddCommand());
2046
- return command;
2047
- }
2048
-
2049
1883
  // src/index.ts
2050
- var program = new Command13();
1884
+ var program = new Command12();
2051
1885
  program.name("azdo").description("Azure DevOps CLI tool").version(version, "-v, --version");
2052
1886
  program.addCommand(createGetItemCommand());
2053
1887
  program.addCommand(createClearPatCommand());
@@ -2060,7 +1894,6 @@ program.addCommand(createSetMdFieldCommand());
2060
1894
  program.addCommand(createUpsertCommand());
2061
1895
  program.addCommand(createListFieldsCommand());
2062
1896
  program.addCommand(createPrCommand());
2063
- program.addCommand(createCommentsCommand());
2064
1897
  program.showHelpAfterError();
2065
1898
  program.parse();
2066
1899
  if (process.argv.length <= 2) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "azdo-cli",
3
- "version": "0.5.0-010-work-item-comments.149",
3
+ "version": "0.5.0-develop.148",
4
4
  "description": "Azure DevOps CLI tool",
5
5
  "type": "module",
6
6
  "bin": {