azdo-cli 0.10.0-develop.467 → 0.10.0-develop.479

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
@@ -58,7 +58,7 @@ azdo pr comments # active-branch PR
58
58
  azdo pr comments --pr-number 64 # any PR by number (skips branch lookup)
59
59
  azdo pr comments --pr-number 64 --hide-resolved # or --exclude-resolved (alias)
60
60
  azdo pr comments --code-related-only # only file/line-anchored threads
61
- azdo pr status # PR checks (status + branch policies) + code-comment counts
61
+ azdo pr status # PR checks (status + branch policies + pipeline builds) + code-comment counts
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
 
package/dist/index.js CHANGED
@@ -2907,6 +2907,16 @@ function buildPolicyEvaluationsUrl(context, projectId, prId) {
2907
2907
  url.searchParams.set("artifactId", `vstfs:///CodeReview/CodeReviewId/${projectId}/${prId}`);
2908
2908
  return url;
2909
2909
  }
2910
+ function buildPullRequestBuildsUrl(context, prId) {
2911
+ const url = new URL(
2912
+ `https://dev.azure.com/${encodeURIComponent(context.org)}/${encodeURIComponent(context.project)}/_apis/build/builds`
2913
+ );
2914
+ url.searchParams.set("branchName", `refs/pull/${prId}/merge`);
2915
+ url.searchParams.set("queryOrder", "queueTimeDescending");
2916
+ url.searchParams.set("$top", "50");
2917
+ url.searchParams.set("api-version", "7.1");
2918
+ return url;
2919
+ }
2910
2920
  function mapPullRequest(repo, pullRequest) {
2911
2921
  return {
2912
2922
  id: pullRequest.pullRequestId,
@@ -2966,6 +2976,22 @@ function mapPolicyEvaluationState(status2) {
2966
2976
  return status2;
2967
2977
  }
2968
2978
  }
2979
+ function mapBuildToCheckState(build) {
2980
+ if (build.status !== "completed") {
2981
+ return "pending";
2982
+ }
2983
+ switch (build.result) {
2984
+ case "succeeded":
2985
+ case "partiallySucceeded":
2986
+ return "succeeded";
2987
+ case "failed":
2988
+ return "failed";
2989
+ case "canceled":
2990
+ return "error";
2991
+ default:
2992
+ return "pending";
2993
+ }
2994
+ }
2969
2995
  function mapPolicyEvaluationName(evaluation) {
2970
2996
  const display = evaluation.configuration?.settings?.displayName?.trim() || evaluation.configuration?.type?.displayName?.trim();
2971
2997
  if (display) {
@@ -2987,7 +3013,8 @@ function mapPolicyEvaluationCheck(evaluation) {
2987
3013
  createdBy: null,
2988
3014
  createdAt: null,
2989
3015
  updatedAt: null,
2990
- source: "policy"
3016
+ source: "policy",
3017
+ isBlocking: evaluation.configuration?.isBlocking ?? null
2991
3018
  };
2992
3019
  }
2993
3020
  function mapComment(comment) {
@@ -3009,7 +3036,7 @@ function mapThread(thread) {
3009
3036
  }
3010
3037
  return {
3011
3038
  id: thread.id,
3012
- status: thread.status,
3039
+ status: thread.status ?? "unknown",
3013
3040
  threadContext: thread.threadContext?.filePath ?? null,
3014
3041
  comments
3015
3042
  };
@@ -3017,7 +3044,7 @@ function mapThread(thread) {
3017
3044
  function toActiveCommentThread(thread) {
3018
3045
  return {
3019
3046
  id: thread.id,
3020
- status: thread.status,
3047
+ status: thread.status ?? "unknown",
3021
3048
  threadContext: thread.threadContext?.filePath ?? null,
3022
3049
  comments: thread.comments.map(mapComment).filter((comment) => comment !== null)
3023
3050
  };
@@ -3088,6 +3115,24 @@ async function getPullRequestPolicyEvaluations(context, cred, projectId, prId) {
3088
3115
  const data = await readJsonResponse(response);
3089
3116
  return data.value.map(mapPolicyEvaluationCheck).filter((check) => check !== null);
3090
3117
  }
3118
+ async function getPullRequestBuilds(context, cred, prId) {
3119
+ const response = await fetchWithErrors(buildPullRequestBuildsUrl(context, prId).toString(), {
3120
+ headers: authHeaders(cred)
3121
+ });
3122
+ const data = await readJsonResponse(response);
3123
+ return data.value.map((build) => ({
3124
+ id: build.id,
3125
+ state: mapBuildToCheckState(build),
3126
+ name: build.definition?.name ?? `Build #${build.id}`,
3127
+ description: null,
3128
+ targetUrl: build._links?.web?.href ?? null,
3129
+ createdBy: null,
3130
+ createdAt: build.queueTime ?? null,
3131
+ updatedAt: build.finishTime ?? null,
3132
+ source: "build",
3133
+ isBlocking: null
3134
+ }));
3135
+ }
3091
3136
  async function openPullRequest(context, repo, cred, sourceBranch, title, description) {
3092
3137
  const existing = await listPullRequests(context, repo, cred, sourceBranch, {
3093
3138
  status: "active",
@@ -3205,7 +3250,8 @@ function formatPullRequestChecks(checks, checksError) {
3205
3250
  }
3206
3251
  const lines = ["Checks:"];
3207
3252
  for (const check of checks) {
3208
- lines.push(`- [${check.state}] ${check.name}`);
3253
+ const optionalTag = check.isBlocking === false ? " [optional]" : "";
3254
+ lines.push(`- [${check.state}] ${check.name}${optionalTag}`);
3209
3255
  if ((check.state === "failed" || check.state === "error") && check.description) {
3210
3256
  lines.push(` Detail: ${check.description}`);
3211
3257
  }
@@ -3258,6 +3304,13 @@ async function buildPullRequestStatusEntry(context, repo, cred, pullRequest, pro
3258
3304
  policyOk = false;
3259
3305
  }
3260
3306
  }
3307
+ let buildChecks = [];
3308
+ let buildsOk = true;
3309
+ try {
3310
+ buildChecks = await getPullRequestBuilds(context, cred, pullRequest.id);
3311
+ } catch {
3312
+ buildsOk = false;
3313
+ }
3261
3314
  let codeCommentCounts;
3262
3315
  try {
3263
3316
  const threads = await getPullRequestThreads(context, repo, cred, pullRequest.id);
@@ -3265,8 +3318,8 @@ async function buildPullRequestStatusEntry(context, repo, cred, pullRequest, pro
3265
3318
  } catch {
3266
3319
  codeCommentCounts = { open: 0, closed: 0 };
3267
3320
  }
3268
- const checks = [...statusChecks, ...policyChecks];
3269
- const checksError = checks.length === 0 && (!statusOk || !policyOk) ? "Azure DevOps request failed" : null;
3321
+ const checks = [...statusChecks, ...policyChecks, ...buildChecks];
3322
+ const checksError = checks.length === 0 && (!statusOk || !policyOk || !buildsOk) ? "Azure DevOps request failed" : null;
3270
3323
  return {
3271
3324
  ...pullRequest,
3272
3325
  checks,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "azdo-cli",
3
- "version": "0.10.0-develop.467",
3
+ "version": "0.10.0-develop.479",
4
4
  "description": "Azure DevOps CLI tool",
5
5
  "type": "module",
6
6
  "bin": {