ira-review 3.1.2 → 3.1.4

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/dist/cli.js CHANGED
@@ -14,9 +14,10 @@ import {
14
14
 
15
15
  // src/cli.ts
16
16
  import { Command } from "commander";
17
- import { existsSync as existsSync9 } from "fs";
17
+ import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
18
18
  import { readFile } from "fs/promises";
19
- import { resolve as resolve3, join as join7 } from "path";
19
+ import { resolve as resolve3, join as join7, dirname } from "path";
20
+ import { fileURLToPath } from "url";
20
21
  import { execSync as execSync5 } from "child_process";
21
22
 
22
23
  // src/core/sonarClient.ts
@@ -1633,17 +1634,23 @@ var CommentTracker = class {
1633
1634
  return keys;
1634
1635
  }
1635
1636
  async getBitbucketServerIraComments(pullRequestId) {
1637
+ const visit = (node, sink) => {
1638
+ if (!node) return;
1639
+ if (typeof node.text === "string" && isIraComment(node.text)) {
1640
+ const meta = node.text.match(IRA_META_RE);
1641
+ if (meta) sink.add(`${meta[1]}:${meta[2]}:${meta[3]}`);
1642
+ }
1643
+ if (Array.isArray(node.comments)) {
1644
+ for (const child of node.comments) visit(child, sink);
1645
+ }
1646
+ };
1636
1647
  const keys = /* @__PURE__ */ new Set();
1637
1648
  let start = 0;
1638
1649
  while (true) {
1639
- const url = `${this.baseUrl}/rest/api/1.0/projects/${this.project}/repos/${this.bbServerRepoSlug}/pull-requests/${pullRequestId}/comments?start=${start}&limit=100`;
1650
+ const url = `${this.baseUrl}/rest/api/1.0/projects/${this.project}/repos/${this.bbServerRepoSlug}/pull-requests/${pullRequestId}/activities?start=${start}&limit=100`;
1640
1651
  const data = await this.fetchBitbucketServerPage(url);
1641
- for (const comment of data.values) {
1642
- if (!isIraComment(comment.text)) continue;
1643
- const meta = comment.text.match(IRA_META_RE);
1644
- if (meta) {
1645
- keys.add(`${meta[1]}:${meta[2]}:${meta[3]}`);
1646
- }
1652
+ for (const activity of data.values) {
1653
+ if (activity.action === "COMMENTED") visit(activity.comment, keys);
1647
1654
  }
1648
1655
  if (data.isLastPage) break;
1649
1656
  start = data.nextPageStart ?? start + 100;
@@ -4078,8 +4085,18 @@ function logEnvironmentInfo(config) {
4078
4085
  step("\u{1F510}", `SSL_CERT_FILE: ${sslCert}`);
4079
4086
  }
4080
4087
  }
4088
+ function readPackageVersion() {
4089
+ try {
4090
+ const here = dirname(fileURLToPath(import.meta.url));
4091
+ const pkgPath = resolve3(here, "..", "package.json");
4092
+ const pkg = JSON.parse(readFileSync7(pkgPath, "utf-8"));
4093
+ if (pkg.version) return pkg.version;
4094
+ } catch {
4095
+ }
4096
+ return "unknown";
4097
+ }
4081
4098
  var program = new Command();
4082
- program.name("ira-review").description("AI-powered PR review tool with SonarQube + GitHub/Bitbucket integration").version("3.1.0");
4099
+ program.name("ira-review").description("AI-powered PR review tool with SonarQube + GitHub/Bitbucket integration").version(readPackageVersion());
4083
4100
  program.command("review").description("Run AI-powered review on a pull request").option("--sonar-url <url>", "SonarQube/SonarCloud base URL (or IRA_SONAR_URL)").option("--sonar-token <token>", "SonarQube API token (or IRA_SONAR_TOKEN)").option("--project-key <key>", "Sonar project key (or IRA_PROJECT_KEY)").option("--pr <id>", "Pull request ID (or IRA_PR)").option("--scm-provider <provider>", "SCM provider: bitbucket or github (or IRA_SCM_PROVIDER)").option("--bitbucket-token <token>", "Bitbucket API token (or IRA_BITBUCKET_TOKEN)").option("--repo <repo>", "Bitbucket workspace/repo-slug (Cloud) or PROJECT/repo-slug (Server) (or IRA_REPO)").option("--bitbucket-url <url>", "Bitbucket base URL (or IRA_BITBUCKET_URL)").option("--bitbucket-type <type>", "Bitbucket type: cloud or server (auto-detects from URL if omitted; or IRA_BITBUCKET_TYPE)").option("--github-token <token>", "GitHub API token (or IRA_GITHUB_TOKEN)").option("--github-repo <repo>", "GitHub owner/repo (or IRA_GITHUB_REPO)").option("--github-url <url>", "GitHub Enterprise URL (or IRA_GITHUB_URL)").option("--ai-provider <provider>", "AI provider").option("--ai-model <model>", "AI model to use").option("--dry-run", "Print comments to stdout instead of posting to SCM").option("--min-severity <level>", "Minimum severity to review (BLOCKER|CRITICAL|MAJOR|MINOR|INFO)").option("--jira-url <url>", "JIRA base URL (or IRA_JIRA_URL)").option("--jira-email <email>", "JIRA email (or IRA_JIRA_EMAIL)").option("--jira-token <token>", "JIRA API token (or IRA_JIRA_TOKEN)").option("--jira-type <type>", "JIRA type: cloud or server (auto-detects from URL if omitted)").option("--jira-ticket <key>", "JIRA ticket key (e.g. PROJ-123)").option("--jira-ac-field <field>", "Custom field ID for acceptance criteria").option("--jira-ac-source <source>", "Where to look for AC: customField, description, or both (default: customField)").option("--no-post-acs-to-jira", "Don't post AI-generated acceptance criteria back to the JIRA ticket when none exist; keep them in the PR summary only (or IRA_POST_ACS_TO_JIRA=false)").option("--slack-webhook <url>", "Slack webhook URL for notifications").option("--teams-webhook <url>", "Teams webhook URL for notifications").option("--notify-min-risk <level>", "Only notify when risk is at or above this level: low, medium, high, critical").option("--notify-on-ac-fail", "Send notification when JIRA acceptance criteria validation fails").option("--ai-base-url <url>", "AI provider base URL (Azure endpoint, Ollama URL)").option("--ai-api-key <key>", "AI API key (or IRA_AI_API_KEY / OPENAI_API_KEY)").option("--ai-api-version <version>", "Azure OpenAI API version").option("--ai-deployment <name>", "Azure OpenAI deployment name").option("--ai-model-critical <model>", "Stronger AI model for BLOCKER/CRITICAL issues").option("--generate-tests", "Generate test cases from JIRA acceptance criteria").option("--test-framework <framework>", "Test framework: jest, vitest, mocha, playwright, cypress, gherkin, pytest, junit (default: jest)").option("--config <path>", "Path to config file (default: auto-detect .irarc.json / ira.config.json)").option("--no-config-file", "Disable auto-loading config file from repo").option("--rules-url <url>", "Fetch .ira-rules.json from URL (raw HTTP) \u2014 useful when CI has no full checkout (or IRA_RULES_URL)").option("--comment-style <style>", "Comment formatter style: compact (default) or detailed (or IRA_COMMENT_STYLE)").action(async (opts) => {
4084
4101
  try {
4085
4102
  console.log(`
package/dist/index.cjs CHANGED
@@ -2429,17 +2429,23 @@ var CommentTracker = class {
2429
2429
  return keys;
2430
2430
  }
2431
2431
  async getBitbucketServerIraComments(pullRequestId) {
2432
+ const visit = (node, sink) => {
2433
+ if (!node) return;
2434
+ if (typeof node.text === "string" && isIraComment(node.text)) {
2435
+ const meta = node.text.match(IRA_META_RE);
2436
+ if (meta) sink.add(`${meta[1]}:${meta[2]}:${meta[3]}`);
2437
+ }
2438
+ if (Array.isArray(node.comments)) {
2439
+ for (const child of node.comments) visit(child, sink);
2440
+ }
2441
+ };
2432
2442
  const keys = /* @__PURE__ */ new Set();
2433
2443
  let start = 0;
2434
2444
  while (true) {
2435
- const url = `${this.baseUrl}/rest/api/1.0/projects/${this.project}/repos/${this.bbServerRepoSlug}/pull-requests/${pullRequestId}/comments?start=${start}&limit=100`;
2445
+ const url = `${this.baseUrl}/rest/api/1.0/projects/${this.project}/repos/${this.bbServerRepoSlug}/pull-requests/${pullRequestId}/activities?start=${start}&limit=100`;
2436
2446
  const data = await this.fetchBitbucketServerPage(url);
2437
- for (const comment of data.values) {
2438
- if (!isIraComment(comment.text)) continue;
2439
- const meta = comment.text.match(IRA_META_RE);
2440
- if (meta) {
2441
- keys.add(`${meta[1]}:${meta[2]}:${meta[3]}`);
2442
- }
2447
+ for (const activity of data.values) {
2448
+ if (activity.action === "COMMENTED") visit(activity.comment, keys);
2443
2449
  }
2444
2450
  if (data.isLastPage) break;
2445
2451
  start = data.nextPageStart ?? start + 100;