abapgit-agent 1.8.5 → 1.8.7

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/bin/abapgit-agent CHANGED
@@ -24,7 +24,7 @@ const gitUtils = require('../src/utils/git-utils');
24
24
  const versionCheck = require('../src/utils/version-check');
25
25
  const validators = require('../src/utils/validators');
26
26
  const { AbapHttp } = require('../src/utils/abap-http');
27
- const { loadConfig, getTransport, isAbapIntegrationEnabled } = require('../src/config');
27
+ const { loadConfig, getTransport, isAbapIntegrationEnabled, getSafeguards } = require('../src/config');
28
28
 
29
29
  // Get terminal width for responsive table
30
30
  const getTermWidth = () => process.stdout.columns || 80;
@@ -52,7 +52,8 @@ async function main() {
52
52
  where: require('../src/commands/where'),
53
53
  ref: require('../src/commands/ref'),
54
54
  init: require('../src/commands/init'),
55
- pull: require('../src/commands/pull')
55
+ pull: require('../src/commands/pull'),
56
+ upgrade: require('../src/commands/upgrade')
56
57
  };
57
58
 
58
59
  // Check if this is a modular command
@@ -98,11 +99,17 @@ To enable integration:
98
99
  isAbapIntegrationEnabled,
99
100
  loadConfig,
100
101
  AbapHttp,
101
- getTransport
102
+ getTransport,
103
+ getSafeguards
102
104
  };
103
105
 
104
106
  // Execute command
105
107
  await cmd.execute(args.slice(1), context);
108
+
109
+ // Show new version reminder (non-blocking, cached daily)
110
+ if (command !== 'upgrade') {
111
+ await versionCheck.showNewVersionReminder();
112
+ }
106
113
  return;
107
114
  }
108
115
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "abapgit-agent",
3
- "version": "1.8.5",
3
+ "version": "1.8.7",
4
4
  "description": "ABAP Git Agent - Pull and activate ABAP code via abapGit from any git repository",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -33,6 +33,7 @@
33
33
  "test:cmd:view": "node tests/run-all.js --cmd --command=view",
34
34
  "test:cmd:preview": "node tests/run-all.js --cmd --command=preview",
35
35
  "test:cmd:tree": "node tests/run-all.js --cmd --command=tree",
36
+ "test:cmd:upgrade": "node tests/run-all.js --cmd --command=upgrade",
36
37
  "test:lifecycle": "node tests/run-all.js --lifecycle",
37
38
  "test:pull": "node tests/run-all.js --pull",
38
39
  "pull": "node bin/abapgit-agent",
@@ -2,6 +2,14 @@
2
2
  * Import command - Import existing objects from package to git repository
3
3
  */
4
4
 
5
+ const {
6
+ startBackgroundJob,
7
+ pollForCompletion,
8
+ displayProgress,
9
+ formatTimestamp,
10
+ calculateTimeSpent
11
+ } = require('../utils/backgroundJobPoller');
12
+
5
13
  module.exports = {
6
14
  name: 'import',
7
15
  description: 'Import existing objects from package to git repository',
@@ -9,9 +17,10 @@ module.exports = {
9
17
  requiresVersionCheck: true,
10
18
 
11
19
  async execute(args, context) {
12
- const { loadConfig, gitUtils, AbapHttp } = context;
20
+ try {
21
+ const { loadConfig, gitUtils, AbapHttp } = context;
13
22
 
14
- // Show help if requested
23
+ // Show help if requested
15
24
  const helpIndex = args.findIndex(a => a === '--help' || a === '-h');
16
25
  if (helpIndex !== -1) {
17
26
  console.log(`
@@ -22,6 +31,9 @@ Description:
22
31
  Import existing objects from package to git repository.
23
32
  Uses the git remote URL to find the abapGit online repository.
24
33
 
34
+ This command runs asynchronously using a background job and displays
35
+ real-time progress updates.
36
+
25
37
  Prerequisites:
26
38
  - Run "abapgit-agent create" first or create repository in abapGit UI
27
39
  - Package must have objects to import
@@ -51,7 +63,7 @@ Examples:
51
63
  commitMessage = args[messageArgIndex + 1];
52
64
  }
53
65
 
54
- console.log(`\nšŸ“¦ Importing objects to git repository`);
66
+ console.log(`\nšŸ“¦ Starting import job`);
55
67
  console.log(` URL: ${repoUrl}`);
56
68
  if (commitMessage) {
57
69
  console.log(` Message: ${commitMessage}`);
@@ -76,23 +88,69 @@ Examples:
76
88
  data.password = config.gitPassword;
77
89
  }
78
90
 
79
- const result = await http.post('/sap/bc/z_abapgit_agent/import', data, { csrfToken });
91
+ // Step 1: Start the background job
92
+ const endpoint = '/sap/bc/z_abapgit_agent/import';
93
+ const jobInfo = await startBackgroundJob(http, endpoint, data, csrfToken);
80
94
 
81
- console.log('\n');
95
+ console.log(`āœ… Job started: ${jobInfo.jobNumber}`);
96
+ console.log('');
82
97
 
83
- // Handle uppercase keys from ABAP
84
- const success = result.SUCCESS || result.success;
85
- const filesStaged = result.FILES_STAGED || result.files_staged;
86
- const abapCommitMessage = result.COMMIT_MESSAGE || result.commit_message;
87
- const error = result.ERROR || result.error;
98
+ // Step 2: Poll for completion with progress updates
99
+ const finalResult = await pollForCompletion(http, endpoint, jobInfo.jobNumber, {
100
+ pollInterval: 2000,
101
+ maxAttempts: 300,
102
+ onProgress: (progress, message) => {
103
+ displayProgress(progress, message);
104
+ }
105
+ });
88
106
 
89
- if (success === 'X' || success === true) {
90
- console.log(`āœ… Objects imported successfully!`);
91
- console.log(` Files staged: ${filesStaged}`);
92
- console.log(` Commit: ${commitMessage || abapCommitMessage}`);
107
+ // Step 3: Show final result
108
+ console.log('\n');
109
+
110
+ if (finalResult.status === 'completed' && finalResult.result) {
111
+ // Parse result JSON string
112
+ let resultData;
113
+ try {
114
+ if (typeof finalResult.result === 'string') {
115
+ resultData = JSON.parse(finalResult.result);
116
+ } else {
117
+ resultData = finalResult.result;
118
+ }
119
+ } catch (e) {
120
+ resultData = { filesStaged: 'unknown', commitMessage: commitMessage };
121
+ }
122
+
123
+ console.log(`āœ… Import completed successfully!`);
124
+ console.log(` Files staged: ${resultData.filesStaged || resultData.FILES_STAGED || 'unknown'}`);
125
+ console.log(` Commit: ${resultData.commitMessage || resultData.COMMIT_MESSAGE || commitMessage || 'Initial import'}`);
126
+ console.log(``);
127
+
128
+ // Calculate time spent
129
+ if (finalResult.startedAt && finalResult.completedAt) {
130
+ const timeSpent = calculateTimeSpent(finalResult.startedAt, finalResult.completedAt);
131
+ console.log(`ā±ļø Time spent: ${timeSpent}`);
132
+ }
133
+
134
+ console.log(`šŸ“ˆ Stats:`);
135
+ console.log(` Job number: ${jobInfo.jobNumber}`);
136
+ if (finalResult.startedAt) {
137
+ console.log(` Started: ${formatTimestamp(finalResult.startedAt)}`);
138
+ }
139
+ if (finalResult.completedAt) {
140
+ console.log(` Completed: ${formatTimestamp(finalResult.completedAt)}`);
141
+ }
93
142
  } else {
94
143
  console.log(`āŒ Import failed`);
95
- console.log(` Error: ${error || 'Unknown error'}`);
144
+ console.log(` Status: ${finalResult.status}`);
145
+ process.exit(1);
146
+ }
147
+ } catch (error) {
148
+ console.error('\nāŒ Error during import:');
149
+ console.error(` ${error.message || error}`);
150
+ if (error.response) {
151
+ console.error(` HTTP Status: ${error.response.status}`);
152
+ console.error(` Response: ${JSON.stringify(error.response.data)}`);
153
+ }
96
154
  process.exit(1);
97
155
  }
98
156
  }
@@ -9,7 +9,21 @@ module.exports = {
9
9
  requiresVersionCheck: true,
10
10
 
11
11
  async execute(args, context) {
12
- const { loadConfig, AbapHttp, gitUtils, getTransport } = context;
12
+ const { loadConfig, AbapHttp, gitUtils, getTransport, getSafeguards } = context;
13
+
14
+ // Check project-level safeguards
15
+ const safeguards = getSafeguards();
16
+
17
+ // SAFEGUARD 1: Check if pull is completely disabled
18
+ if (safeguards.disablePull) {
19
+ console.error('āŒ Error: pull command is disabled for this project\n');
20
+ if (safeguards.reason) {
21
+ console.error(`Reason: ${safeguards.reason}\n`);
22
+ }
23
+ console.error('The pull command has been disabled in .abapgit-agent.json');
24
+ console.error('Please contact the project maintainer to enable it.');
25
+ process.exit(1);
26
+ }
13
27
 
14
28
  const urlArgIndex = args.indexOf('--url');
15
29
  const branchArgIndex = args.indexOf('--branch');
@@ -36,6 +50,18 @@ module.exports = {
36
50
  files = args[filesArgIndex + 1].split(',').map(f => f.trim());
37
51
  }
38
52
 
53
+ // SAFEGUARD 2: Check if files are required but not provided
54
+ if (safeguards.requireFilesForPull && !files) {
55
+ console.error('āŒ Error: --files parameter is required for this project\n');
56
+ if (safeguards.reason) {
57
+ console.error(`Reason: ${safeguards.reason}\n`);
58
+ }
59
+ console.error('Usage: abapgit-agent pull --files <file1>,<file2>\n');
60
+ console.error('This safeguard is configured in .abapgit-agent.json');
61
+ console.error('Contact the project maintainer if you need to change this setting.');
62
+ process.exit(1);
63
+ }
64
+
39
65
  if (!gitUrl) {
40
66
  gitUrl = gitUtils.getRemoteUrl();
41
67
  if (!gitUrl) {
@@ -0,0 +1,456 @@
1
+ /**
2
+ * Upgrade command - Upgrade CLI and/or ABAP backend to latest or specific version
3
+ */
4
+
5
+ const { execSync } = require('child_process');
6
+ const readline = require('readline');
7
+
8
+ module.exports = {
9
+ name: 'upgrade',
10
+ description: 'Upgrade CLI and/or ABAP backend to latest or specific version',
11
+ requiresAbapConfig: false, // Checked conditionally
12
+ requiresVersionCheck: false, // Does its own version checks
13
+
14
+ async execute(args, context) {
15
+ const { versionCheck, loadConfig, isAbapIntegrationEnabled } = context;
16
+
17
+ // Parse flags
18
+ const flags = this.parseFlags(args);
19
+
20
+ // Validate flag combinations
21
+ try {
22
+ this.validateFlags(flags);
23
+ } catch (error) {
24
+ console.error(`āŒ Error: ${error.message}`);
25
+ process.exit(1);
26
+ }
27
+
28
+ // Check if ABAP config is needed
29
+ const needsAbapConfig = !flags.cliOnly && !flags.checkOnly;
30
+ if (needsAbapConfig && !isAbapIntegrationEnabled()) {
31
+ console.error('āŒ Error: .abapGitAgent config file not found');
32
+ console.error(' ABAP upgrade requires configuration.');
33
+ console.error(' Run: abapgit-agent init');
34
+ console.error('');
35
+ console.error(' Or use --cli-only to upgrade CLI package only.');
36
+ process.exit(1);
37
+ }
38
+
39
+ // Get current versions
40
+ const cliVersion = versionCheck.getCliVersion();
41
+ let abapVersion = null;
42
+
43
+ if (needsAbapConfig) {
44
+ try {
45
+ const config = loadConfig();
46
+ const { apiVersion } = await versionCheck.checkCompatibility(config);
47
+ abapVersion = apiVersion;
48
+ } catch (e) {
49
+ console.error(`āš ļø Could not fetch ABAP version: ${e.message}`);
50
+ }
51
+ }
52
+
53
+ // Get latest version from npm
54
+ const latestVersion = await versionCheck.getLatestNpmVersion();
55
+ if (!latestVersion && !flags.version && !flags.match) {
56
+ console.error('āŒ Error: Could not fetch latest version from npm registry');
57
+ console.error(' Please check your internet connection or specify --version X.X.X');
58
+ process.exit(1);
59
+ }
60
+
61
+ // Validate specified version exists in npm registry
62
+ if (flags.version && !flags.abapOnly) {
63
+ const versionExists = await this.validateVersionExists(flags.version);
64
+ if (!versionExists) {
65
+ console.error(`āŒ Error: Version ${flags.version} not found in npm registry`);
66
+ console.error(' Please check available versions at: https://www.npmjs.com/package/abapgit-agent?activeTab=versions');
67
+ process.exit(1);
68
+ }
69
+ }
70
+
71
+ // Determine target versions
72
+ const targets = this.determineTargets(flags, cliVersion, abapVersion, latestVersion);
73
+
74
+ // Check-only mode
75
+ if (flags.checkOnly) {
76
+ this.showCheckReport(cliVersion, abapVersion, latestVersion);
77
+ return;
78
+ }
79
+
80
+ // Dry-run mode
81
+ if (flags.dryRun) {
82
+ this.showDryRunPlan(cliVersion, abapVersion, targets, flags);
83
+ return;
84
+ }
85
+
86
+ // Show upgrade plan
87
+ if (!flags.yes) {
88
+ const proceed = await this.confirmUpgrade(cliVersion, abapVersion, targets, flags);
89
+ if (!proceed) {
90
+ console.log('Upgrade cancelled.');
91
+ return;
92
+ }
93
+ }
94
+
95
+ // Execute upgrade
96
+ await this.performUpgrade(targets, flags, context);
97
+
98
+ // Verify upgrade
99
+ await this.verifyUpgrade(targets, flags, context);
100
+ },
101
+
102
+ /**
103
+ * Parse command-line flags
104
+ */
105
+ parseFlags(args) {
106
+ return {
107
+ checkOnly: args.includes('--check'),
108
+ cliOnly: args.includes('--cli-only'),
109
+ abapOnly: args.includes('--abap-only'),
110
+ match: args.includes('--match'),
111
+ version: this.getArgValue(args, '--version'),
112
+ latest: args.includes('--latest'),
113
+ yes: args.includes('--yes') || args.includes('-y'),
114
+ dryRun: args.includes('--dry-run'),
115
+ transport: this.getArgValue(args, '--transport')
116
+ };
117
+ },
118
+
119
+ /**
120
+ * Get argument value following a flag
121
+ */
122
+ getArgValue(args, flag) {
123
+ const index = args.indexOf(flag);
124
+ if (index !== -1 && index + 1 < args.length) {
125
+ return args[index + 1];
126
+ }
127
+ return null;
128
+ },
129
+
130
+ /**
131
+ * Validate flag combinations
132
+ */
133
+ validateFlags(flags) {
134
+ // Invalid combinations
135
+ if (flags.match && flags.version) {
136
+ throw new Error('Cannot use --match and --version together');
137
+ }
138
+
139
+ if (flags.match && flags.cliOnly) {
140
+ throw new Error('Cannot use --match with --cli-only. --match upgrades ABAP to match CLI version');
141
+ }
142
+
143
+ if (flags.cliOnly && flags.abapOnly) {
144
+ throw new Error('Cannot use --cli-only and --abap-only together');
145
+ }
146
+ },
147
+
148
+ /**
149
+ * Validate that a version exists in npm registry
150
+ */
151
+ async validateVersionExists(version) {
152
+ return new Promise((resolve) => {
153
+ const { execSync } = require('child_process');
154
+ try {
155
+ // Use npm view to check if version exists
156
+ const output = execSync(`npm view abapgit-agent@${version} version 2>/dev/null`, {
157
+ encoding: 'utf8',
158
+ stdio: ['pipe', 'pipe', 'ignore']
159
+ }).trim();
160
+
161
+ // If npm view returns the version, it exists
162
+ resolve(output === version);
163
+ } catch (e) {
164
+ // Version doesn't exist or npm command failed
165
+ resolve(false);
166
+ }
167
+ });
168
+ },
169
+
170
+ /**
171
+ * Determine target versions for CLI and ABAP
172
+ */
173
+ determineTargets(flags, cliVersion, abapVersion, latestVersion) {
174
+ let cliTarget = null;
175
+ let abapTarget = null;
176
+
177
+ if (flags.match) {
178
+ // Match ABAP to CLI version
179
+ abapTarget = cliVersion;
180
+ } else if (flags.version) {
181
+ // Specific version
182
+ cliTarget = flags.cliOnly ? flags.version : (flags.abapOnly ? null : flags.version);
183
+ abapTarget = flags.abapOnly ? flags.version : (flags.cliOnly ? null : flags.version);
184
+ } else {
185
+ // Latest version (default)
186
+ cliTarget = flags.abapOnly ? null : latestVersion;
187
+ abapTarget = flags.cliOnly ? null : latestVersion;
188
+ }
189
+
190
+ return { cliTarget, abapTarget };
191
+ },
192
+
193
+ /**
194
+ * Show check-only report
195
+ */
196
+ showCheckReport(cliVersion, abapVersion, latestVersion) {
197
+ console.log('');
198
+ console.log('Current versions:');
199
+ console.log(` CLI: v${cliVersion}`);
200
+ if (abapVersion) {
201
+ console.log(` ABAP: v${abapVersion}`);
202
+ }
203
+ console.log('');
204
+
205
+ if (latestVersion) {
206
+ console.log(`Latest available: v${latestVersion}`);
207
+ console.log('');
208
+ }
209
+
210
+ const needsCliUpgrade = latestVersion && cliVersion !== latestVersion;
211
+ const needsAbapUpgrade = abapVersion && latestVersion && abapVersion !== latestVersion;
212
+ const versionMismatch = abapVersion && cliVersion !== abapVersion;
213
+
214
+ if (versionMismatch) {
215
+ console.log('āš ļø Version mismatch detected');
216
+ console.log('');
217
+ } else if (!needsCliUpgrade && !needsAbapUpgrade) {
218
+ console.log('āœ… All components are up to date');
219
+ console.log('');
220
+ return;
221
+ }
222
+
223
+ console.log('To upgrade:');
224
+ console.log(' Both: abapgit-agent upgrade');
225
+ console.log(' CLI only: abapgit-agent upgrade --cli-only');
226
+ if (abapVersion) {
227
+ console.log(' ABAP only: abapgit-agent upgrade --abap-only');
228
+ console.log(' Match: abapgit-agent upgrade --match');
229
+ }
230
+ console.log('');
231
+ },
232
+
233
+ /**
234
+ * Show dry-run plan
235
+ */
236
+ showDryRunPlan(cliVersion, abapVersion, targets, flags) {
237
+ console.log('');
238
+ console.log('šŸ”¹ DRY RUN - No changes will be made');
239
+ console.log('');
240
+ console.log('Current versions:');
241
+ console.log(` CLI: v${cliVersion}`);
242
+ if (abapVersion) {
243
+ console.log(` ABAP: v${abapVersion}`);
244
+ }
245
+ console.log('');
246
+
247
+ console.log('Target versions:');
248
+ if (targets.cliTarget) {
249
+ console.log(` CLI: v${targets.cliTarget}`);
250
+ }
251
+ if (targets.abapTarget) {
252
+ console.log(` ABAP: v${targets.abapTarget}`);
253
+ }
254
+ console.log('');
255
+
256
+ console.log('Would execute:');
257
+ let step = 1;
258
+ if (targets.cliTarget) {
259
+ console.log(` ${step}. npm install -g abapgit-agent@${targets.cliTarget}`);
260
+ step++;
261
+ }
262
+ if (targets.abapTarget) {
263
+ console.log(` ${step}. abapgit-agent pull --branch v${targets.abapTarget}`);
264
+ console.log(' (via existing abapGit repository)');
265
+ step++;
266
+ }
267
+ console.log(` ${step}. Verify versions match`);
268
+ console.log('');
269
+ console.log('No changes made.');
270
+ console.log('');
271
+ },
272
+
273
+ /**
274
+ * Confirm upgrade with user
275
+ */
276
+ async confirmUpgrade(cliVersion, abapVersion, targets, flags) {
277
+ console.log('');
278
+ console.log('šŸ“¦ Upgrade Plan:');
279
+ console.log('');
280
+ console.log('Current versions:');
281
+ console.log(` CLI: v${cliVersion}`);
282
+ if (abapVersion) {
283
+ console.log(` ABAP: v${abapVersion}`);
284
+ }
285
+ console.log('');
286
+
287
+ console.log('Target versions:');
288
+ if (targets.cliTarget) {
289
+ console.log(` CLI: v${targets.cliTarget}`);
290
+ }
291
+ if (targets.abapTarget) {
292
+ console.log(` ABAP: v${targets.abapTarget}`);
293
+ }
294
+ console.log('');
295
+
296
+ console.log('This will:');
297
+ let step = 1;
298
+ if (targets.cliTarget) {
299
+ console.log(` ${step}. Upgrade npm package: abapgit-agent@${targets.cliTarget}`);
300
+ step++;
301
+ }
302
+ if (targets.abapTarget) {
303
+ console.log(` ${step}. Pull ABAP code from git tag v${targets.abapTarget}`);
304
+ step++;
305
+ console.log(` ${step}. Activate all backend components`);
306
+ step++;
307
+ }
308
+ console.log('');
309
+
310
+ return new Promise((resolve) => {
311
+ const rl = readline.createInterface({
312
+ input: process.stdin,
313
+ output: process.stdout
314
+ });
315
+
316
+ rl.question('Do you want to continue? [Y/n] ', (answer) => {
317
+ rl.close();
318
+ const normalized = answer.trim().toLowerCase();
319
+ resolve(normalized === '' || normalized === 'y' || normalized === 'yes');
320
+ });
321
+ });
322
+ },
323
+
324
+ /**
325
+ * Perform upgrade
326
+ */
327
+ async performUpgrade(targets, flags, context) {
328
+ console.log('');
329
+ console.log('šŸš€ Starting upgrade...');
330
+ console.log('');
331
+
332
+ // Upgrade CLI
333
+ if (targets.cliTarget) {
334
+ await this.upgradeCliPackage(targets.cliTarget);
335
+ }
336
+
337
+ // Upgrade ABAP
338
+ if (targets.abapTarget) {
339
+ await this.upgradeAbapBackend(targets.abapTarget, flags.transport, context);
340
+ }
341
+ },
342
+
343
+ /**
344
+ * Upgrade CLI package via npm
345
+ */
346
+ async upgradeCliPackage(version) {
347
+ console.log(`šŸ“¦ Upgrading CLI to v${version}...`);
348
+
349
+ try {
350
+ // Check if npm is available
351
+ try {
352
+ execSync('npm --version', { stdio: 'ignore' });
353
+ } catch (e) {
354
+ console.error('āŒ Error: npm is not installed or not in PATH');
355
+ console.error(' Please install Node.js and npm: https://nodejs.org/');
356
+ process.exit(1);
357
+ }
358
+
359
+ // Run npm install
360
+ const command = `npm install -g abapgit-agent@${version}`;
361
+ console.log(` Running: ${command}`);
362
+
363
+ execSync(command, {
364
+ stdio: 'inherit',
365
+ encoding: 'utf8'
366
+ });
367
+
368
+ console.log(`āœ… CLI upgraded to v${version}`);
369
+ console.log('');
370
+ } catch (error) {
371
+ console.error(`āŒ Failed to upgrade CLI: ${error.message}`);
372
+ console.error('');
373
+ console.error('This may be due to:');
374
+ console.error(' - Version not found in npm registry');
375
+ console.error(' - Permission issues (try with sudo)');
376
+ console.error(' - Network connectivity issues');
377
+ process.exit(1);
378
+ }
379
+ },
380
+
381
+ /**
382
+ * Upgrade ABAP backend via pull command
383
+ */
384
+ async upgradeAbapBackend(version, transport, context) {
385
+ console.log(`šŸ“¦ Upgrading ABAP backend to v${version}...`);
386
+ console.log(` Using git tag: v${version}`);
387
+ console.log('');
388
+
389
+ try {
390
+ // Build pull command args
391
+ const pullArgs = ['--branch', `v${version}`];
392
+ if (transport) {
393
+ pullArgs.push('--transport', transport);
394
+ }
395
+
396
+ // Execute pull command
397
+ const pullCommand = require('./pull');
398
+ await pullCommand.execute(pullArgs, context);
399
+
400
+ console.log('');
401
+ console.log(`āœ… ABAP backend upgraded to v${version}`);
402
+ console.log('');
403
+ } catch (error) {
404
+ console.error(`āŒ Failed to upgrade ABAP backend: ${error.message}`);
405
+ console.error('');
406
+ console.error('This may be due to:');
407
+ console.error(' - Git tag not found in repository');
408
+ console.error(' - ABAP activation errors');
409
+ console.error(' - Connection issues with ABAP system');
410
+ process.exit(1);
411
+ }
412
+ },
413
+
414
+ /**
415
+ * Verify upgrade success
416
+ */
417
+ async verifyUpgrade(targets, flags, context) {
418
+ console.log('šŸ” Verifying upgrade...');
419
+ console.log('');
420
+
421
+ const { versionCheck, loadConfig } = context;
422
+
423
+ // Check CLI version
424
+ let cliVersion = null;
425
+ if (targets.cliTarget) {
426
+ cliVersion = versionCheck.getCliVersion();
427
+ if (cliVersion === targets.cliTarget) {
428
+ console.log(`āœ… CLI version verified: v${cliVersion}`);
429
+ } else {
430
+ console.log(`āš ļø CLI version mismatch: expected v${targets.cliTarget}, got v${cliVersion}`);
431
+ console.log(' You may need to restart your terminal or reinstall globally');
432
+ }
433
+ }
434
+
435
+ // Check ABAP version
436
+ if (targets.abapTarget && !flags.cliOnly) {
437
+ try {
438
+ const config = loadConfig();
439
+ const { apiVersion: abapVersion } = await versionCheck.checkCompatibility(config);
440
+
441
+ if (abapVersion === targets.abapTarget) {
442
+ console.log(`āœ… ABAP version verified: v${abapVersion}`);
443
+ } else {
444
+ console.log(`āš ļø ABAP version mismatch: expected v${targets.abapTarget}, got v${abapVersion}`);
445
+ console.log(' Some components may have failed to activate');
446
+ }
447
+ } catch (e) {
448
+ console.log(`āš ļø Could not verify ABAP version: ${e.message}`);
449
+ }
450
+ }
451
+
452
+ console.log('');
453
+ console.log('āœ… Upgrade complete!');
454
+ console.log('');
455
+ }
456
+ };