@aspruyt/xfg 1.2.0 → 1.3.1

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.
@@ -68,7 +68,7 @@ export class AzurePRStrategy extends BasePRStrategy {
68
68
  return false;
69
69
  }
70
70
  // Abandon the PR (Azure DevOps equivalent of closing)
71
- const abandonCommand = `az repos pr update --id ${escapeShellArg(prInfo.prId)} --status abandoned --org ${escapeShellArg(orgUrl)} --project ${escapeShellArg(prInfo.project)}`;
71
+ const abandonCommand = `az repos pr update --id ${escapeShellArg(prInfo.prId)} --status abandoned --org ${escapeShellArg(orgUrl)}`;
72
72
  try {
73
73
  await withRetry(() => this.executor.exec(abandonCommand, workDir), {
74
74
  retries,
@@ -79,12 +79,15 @@ export class AzurePRStrategy extends BasePRStrategy {
79
79
  logger.info(`Warning: Failed to abandon PR #${prInfo.prId}: ${message}`);
80
80
  return false;
81
81
  }
82
- // Delete the source branch
83
- const deleteBranchCommand = `az repos ref delete --name refs/heads/${escapeShellArg(branchName)} --repository ${escapeShellArg(azureRepoInfo.repo)} --org ${escapeShellArg(orgUrl)} --project ${escapeShellArg(azureRepoInfo.project)}`;
82
+ // Delete the source branch - need to get object_id first
84
83
  try {
85
- await withRetry(() => this.executor.exec(deleteBranchCommand, workDir), {
86
- retries,
87
- });
84
+ // Get the branch's object_id
85
+ const getRefCommand = `az repos ref list --repository ${escapeShellArg(azureRepoInfo.repo)} --org ${escapeShellArg(orgUrl)} --project ${escapeShellArg(azureRepoInfo.project)} --filter heads/${escapeShellArg(branchName)} --query "[0].objectId" -o tsv`;
86
+ const objectId = await withRetry(() => this.executor.exec(getRefCommand, workDir), { retries });
87
+ if (objectId) {
88
+ const deleteBranchCommand = `az repos ref delete --name refs/heads/${escapeShellArg(branchName)} --repository ${escapeShellArg(azureRepoInfo.repo)} --org ${escapeShellArg(orgUrl)} --project ${escapeShellArg(azureRepoInfo.project)} --object-id ${escapeShellArg(objectId)}`;
89
+ await withRetry(() => this.executor.exec(deleteBranchCommand, workDir), { retries });
90
+ }
88
91
  }
89
92
  catch (error) {
90
93
  // Branch deletion failure is not critical - PR is already abandoned
@@ -168,7 +171,7 @@ export class AzurePRStrategy extends BasePRStrategy {
168
171
  : "";
169
172
  if (config.mode === "auto") {
170
173
  // Enable auto-complete (no pre-check needed - always available in Azure DevOps)
171
- const command = `az repos pr update --id ${escapeShellArg(prInfo.prId)} --auto-complete true ${squashFlag} ${deleteBranchFlag} --org ${escapeShellArg(orgUrl)} --project ${escapeShellArg(prInfo.project)}`.trim();
174
+ const command = `az repos pr update --id ${escapeShellArg(prInfo.prId)} --auto-complete true ${squashFlag} ${deleteBranchFlag} --org ${escapeShellArg(orgUrl)}`.trim();
172
175
  try {
173
176
  await withRetry(() => this.executor.exec(command, workDir), {
174
177
  retries,
@@ -192,7 +195,7 @@ export class AzurePRStrategy extends BasePRStrategy {
192
195
  if (config.mode === "force") {
193
196
  // Bypass policies and complete the PR
194
197
  const bypassReason = config.bypassReason ?? "Automated config sync via xfg";
195
- const command = `az repos pr update --id ${escapeShellArg(prInfo.prId)} --bypass-policy true --bypass-policy-reason ${escapeShellArg(bypassReason)} --status completed ${squashFlag} ${deleteBranchFlag} --org ${escapeShellArg(orgUrl)} --project ${escapeShellArg(prInfo.project)}`.trim();
198
+ const command = `az repos pr update --id ${escapeShellArg(prInfo.prId)} --bypass-policy true --bypass-policy-reason ${escapeShellArg(bypassReason)} --status completed ${squashFlag} ${deleteBranchFlag} --org ${escapeShellArg(orgUrl)}`.trim();
196
199
  try {
197
200
  await withRetry(() => this.executor.exec(command, workDir), {
198
201
  retries,
@@ -66,7 +66,8 @@ export class GitLabPRStrategy extends BasePRStrategy {
66
66
  }
67
67
  const repoFlag = this.getRepoFlag(repoInfo);
68
68
  // Use glab mr list with JSON output for reliable parsing
69
- const command = `glab mr list --source-branch ${escapeShellArg(branchName)} --state opened -R ${escapeShellArg(repoFlag)} -F json`;
69
+ // Note: glab mr list returns open MRs by default (use -c for closed, -M for merged)
70
+ const command = `glab mr list --source-branch ${escapeShellArg(branchName)} -R ${escapeShellArg(repoFlag)} -F json`;
70
71
  try {
71
72
  const result = await withRetry(() => this.executor.exec(command, workDir), { retries });
72
73
  if (!result || result.trim() === "" || result.trim() === "[]") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aspruyt/xfg",
3
- "version": "1.2.0",
3
+ "version": "1.3.1",
4
4
  "description": "CLI tool to sync JSON or YAML configuration files across multiple GitHub, Azure DevOps, and GitLab repositories",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -27,7 +27,9 @@
27
27
  "start": "node dist/index.js",
28
28
  "dev": "ts-node src/index.ts",
29
29
  "test": "node --import tsx --test src/config.test.ts src/merge.test.ts src/env.test.ts src/repo-detector.test.ts src/pr-creator.test.ts src/git-ops.test.ts src/logger.test.ts src/workspace-utils.test.ts src/strategies/pr-strategy.test.ts src/strategies/github-pr-strategy.test.ts src/strategies/azure-pr-strategy.test.ts src/strategies/gitlab-pr-strategy.test.ts src/repository-processor.test.ts src/retry-utils.test.ts src/command-executor.test.ts src/shell-utils.test.ts src/index.test.ts src/config-formatter.test.ts src/config-validator.test.ts src/config-normalizer.test.ts src/diff-utils.test.ts",
30
- "test:integration": "npm run build && node --import tsx --test src/integration.test.ts",
30
+ "test:integration:github": "npm run build && node --import tsx --test src/integration-github.test.ts",
31
+ "test:integration:ado": "npm run build && node --import tsx --test src/integration-ado.test.ts",
32
+ "test:integration:gitlab": "npm run build && node --import tsx --test src/integration-gitlab.test.ts",
31
33
  "prepublishOnly": "npm run build"
32
34
  },
33
35
  "keywords": [