abapgit-agent 1.8.1 → 1.8.3
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/abap/CLAUDE.md +312 -34
- package/abap/guidelines/03_testing.md +45 -6
- package/abap/guidelines/04_cds.md +113 -5
- package/package.json +2 -1
- package/src/commands/init.js +81 -20
- package/src/commands/ref.js +1 -1
- package/src/config.js +16 -1
- package/src/utils/git-utils.js +49 -1
package/abap/CLAUDE.md
CHANGED
|
@@ -73,30 +73,38 @@ The folder is configured in `.abapGitAgent` (property: `folder`):
|
|
|
73
73
|
|
|
74
74
|
**Each ABAP object requires an XML metadata file for abapGit to understand how to handle it.**
|
|
75
75
|
|
|
76
|
-
| Object Type | ABAP File (if folder=/src/) | XML File |
|
|
77
|
-
|
|
78
|
-
| Class | `src/zcl_*.clas.abap` | `src/zcl_*.clas.xml` |
|
|
79
|
-
| Interface | `src/zif_*.intf.abap` | `src/zif_*.intf.xml` |
|
|
80
|
-
| Program | `src/z*.prog.abap` | `src/z*.prog.xml` |
|
|
81
|
-
| Table | `src/z*.tabl.abap` | `src/z*.tabl.xml` |
|
|
82
|
-
| CDS View | `src/zc_*.ddls.asddls` | `src/zc_*.ddls.xml` |
|
|
76
|
+
| Object Type | ABAP File (if folder=/src/) | XML File | Details |
|
|
77
|
+
|-------------|------------------------------|----------|---------|
|
|
78
|
+
| Class | `src/zcl_*.clas.abap` | `src/zcl_*.clas.xml` | See `guidelines/08_abapgit.md` |
|
|
79
|
+
| Interface | `src/zif_*.intf.abap` | `src/zif_*.intf.xml` | See `guidelines/08_abapgit.md` |
|
|
80
|
+
| Program | `src/z*.prog.abap` | `src/z*.prog.xml` | See `guidelines/08_abapgit.md` |
|
|
81
|
+
| Table | `src/z*.tabl.abap` | `src/z*.tabl.xml` | See `guidelines/08_abapgit.md` |
|
|
82
|
+
| **CDS View Entity** | `src/zc_*.ddls.asddls` | `src/zc_*.ddls.xml` | **Use by default** - See `guidelines/04_cds.md` |
|
|
83
|
+
| CDS View (legacy) | `src/zc_*.ddls.asddls` | `src/zc_*.ddls.xml` | Only if explicitly requested - See `guidelines/04_cds.md` |
|
|
83
84
|
|
|
84
|
-
**
|
|
85
|
+
**IMPORTANT: When user says "create CDS view", create CDS View Entity by default.**
|
|
86
|
+
|
|
87
|
+
**Why:** Modern S/4HANA standard, simpler (no SQL view), no namespace conflicts.
|
|
88
|
+
|
|
89
|
+
**For complete XML templates, DDL examples, and detailed comparison:**
|
|
90
|
+
- **CDS Views**: `guidelines/04_cds.md`
|
|
91
|
+
- **XML templates**: `guidelines/08_abapgit.md`
|
|
85
92
|
|
|
86
93
|
---
|
|
87
94
|
|
|
88
|
-
### 4. Use Syntax Command Before Commit (for CLAS, INTF, PROG)
|
|
95
|
+
### 4. Use Syntax Command Before Commit (for CLAS, INTF, PROG, DDLS)
|
|
89
96
|
|
|
90
97
|
```
|
|
91
98
|
❌ WRONG: Make changes → Commit → Push → Pull → Find errors → Fix → Repeat
|
|
92
99
|
✅ CORRECT: Make changes → Run syntax → Fix locally → Commit → Push → Pull → Done
|
|
93
100
|
```
|
|
94
101
|
|
|
95
|
-
**For CLAS, INTF, PROG files**: Run `syntax` command BEFORE commit to catch errors early.
|
|
102
|
+
**For CLAS, INTF, PROG, DDLS files**: Run `syntax` command BEFORE commit to catch errors early.
|
|
96
103
|
|
|
97
104
|
```bash
|
|
98
105
|
# Check syntax of local code (no commit/push needed)
|
|
99
106
|
abapgit-agent syntax --files src/zcl_my_class.clas.abap
|
|
107
|
+
abapgit-agent syntax --files src/zc_my_view.ddls.asddls
|
|
100
108
|
|
|
101
109
|
# Check multiple INDEPENDENT files
|
|
102
110
|
abapgit-agent syntax --files src/zcl_utils.clas.abap,src/zcl_logger.clas.abap
|
|
@@ -250,8 +258,189 @@ abapgit-agent unit --files src/zcl_test1.clas.testclasses.abap,src/zcl_test2.cla
|
|
|
250
258
|
|
|
251
259
|
## Development Workflow
|
|
252
260
|
|
|
261
|
+
This project's workflow mode is configured in `.abapGitAgent` under `workflow.mode`.
|
|
262
|
+
|
|
263
|
+
### Workflow Modes
|
|
264
|
+
|
|
265
|
+
| Mode | Branch Strategy | Rebase Before Pull | Create PR |
|
|
266
|
+
|------|----------------|-------------------|-----------|
|
|
267
|
+
| `"branch"` | Feature branches | ✓ Always | ✓ Yes (squash merge) |
|
|
268
|
+
| `"trunk"` | Direct to default branch | ✗ No | ✗ No |
|
|
269
|
+
| (not set) | Direct to default branch | ✗ No | ✗ No |
|
|
270
|
+
|
|
271
|
+
**Default branch** (main/master/develop) is **auto-detected** from your git repository.
|
|
272
|
+
|
|
273
|
+
### Branch Workflow (`"mode": "branch"`)
|
|
274
|
+
|
|
275
|
+
**IMPORTANT**: Always work on feature branches, never commit directly to the default branch.
|
|
276
|
+
|
|
277
|
+
#### Starting a New Feature
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
# 1. Create and switch to feature branch from default branch
|
|
281
|
+
git checkout main # or master/develop (auto-detected)
|
|
282
|
+
git pull origin main
|
|
283
|
+
git checkout -b feature/user-authentication
|
|
284
|
+
|
|
285
|
+
# 2. Make your changes
|
|
286
|
+
edit src/zcl_auth_handler.clas.abap
|
|
287
|
+
|
|
288
|
+
# 3. Check syntax (CLAS/INTF/PROG/DDLS only, if independent)
|
|
289
|
+
abapgit-agent syntax --files src/zcl_auth_handler.clas.abap
|
|
290
|
+
|
|
291
|
+
# 4. Commit
|
|
292
|
+
git add src/zcl_auth_handler.clas.abap
|
|
293
|
+
git commit -m "feat: add authentication handler"
|
|
294
|
+
|
|
295
|
+
# 5. Push feature branch
|
|
296
|
+
git push origin feature/user-authentication
|
|
297
|
+
|
|
298
|
+
# 6. **CRITICAL**: Rebase before pull
|
|
299
|
+
git fetch origin main
|
|
300
|
+
git rebase origin/main
|
|
301
|
+
git push origin feature/user-authentication --force-with-lease
|
|
302
|
+
|
|
303
|
+
# 7. Pull to ABAP system
|
|
304
|
+
abapgit-agent pull --files src/zcl_auth_handler.clas.abap
|
|
253
305
|
```
|
|
254
|
-
|
|
306
|
+
|
|
307
|
+
#### During Development: Always Rebase Before Pull
|
|
308
|
+
|
|
309
|
+
**CRITICAL**: Before every `pull` command, rebase to default branch to avoid activating outdated code.
|
|
310
|
+
|
|
311
|
+
```bash
|
|
312
|
+
# Before EVERY pull, always do this:
|
|
313
|
+
git fetch origin main # main/master/develop (auto-detected)
|
|
314
|
+
git rebase origin/main
|
|
315
|
+
|
|
316
|
+
# If no conflicts:
|
|
317
|
+
git push origin feature/user-authentication --force-with-lease
|
|
318
|
+
abapgit-agent pull --files src/zcl_auth_handler.clas.abap
|
|
319
|
+
|
|
320
|
+
# If conflicts:
|
|
321
|
+
# 1. Fix conflicts in files
|
|
322
|
+
# 2. git add <resolved-files>
|
|
323
|
+
# 3. git rebase --continue
|
|
324
|
+
# 4. git push origin feature/user-authentication --force-with-lease
|
|
325
|
+
# 5. abapgit-agent pull --files ...
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
#### Completing the Feature
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
# 1. Final rebase and push
|
|
332
|
+
git fetch origin main
|
|
333
|
+
git rebase origin/main
|
|
334
|
+
git push origin feature/user-authentication --force-with-lease
|
|
335
|
+
|
|
336
|
+
# 2. Final activation and test
|
|
337
|
+
abapgit-agent pull --files src/zcl_auth_handler.clas.abap
|
|
338
|
+
abapgit-agent unit --files src/zcl_auth_handler.clas.testclasses.abap
|
|
339
|
+
|
|
340
|
+
# 3. Create PR (squash merge enabled on GitHub/GitLab)
|
|
341
|
+
# Go to GitHub and create PR from feature/user-authentication to main
|
|
342
|
+
# Select "Squash and merge" option to combine all commits into one
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
#### Why Rebase Before Pull?
|
|
346
|
+
|
|
347
|
+
ABAP is a **centralized system**. Multiple developers may modify the same files:
|
|
348
|
+
|
|
349
|
+
| Without Rebase | With Rebase |
|
|
350
|
+
|----------------|-------------|
|
|
351
|
+
| ✗ Your branch is based on old main | ✓ Your branch includes latest changes |
|
|
352
|
+
| ✗ Activate outdated code in ABAP | ✓ Activate current code |
|
|
353
|
+
| ✗ May overwrite others' work | ✓ Conflicts caught before activation |
|
|
354
|
+
| ✗ Hard to debug issues | ✓ Clear what changed |
|
|
355
|
+
|
|
356
|
+
**Example Scenario:**
|
|
357
|
+
|
|
358
|
+
```
|
|
359
|
+
Situation:
|
|
360
|
+
- You: working on feature/auth (based on main commit A)
|
|
361
|
+
- Colleague: pushed to main (now at commit B)
|
|
362
|
+
- Both modified: src/zcl_auth_handler.clas.abap
|
|
363
|
+
|
|
364
|
+
Without rebase:
|
|
365
|
+
feature/auth pull → activates version from commit A ✗
|
|
366
|
+
|
|
367
|
+
With rebase:
|
|
368
|
+
git rebase origin/main → either:
|
|
369
|
+
- No conflict: includes colleague's changes ✓
|
|
370
|
+
- Conflict: you see it and resolve ✓
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
#### Complete Example Workflow (Branch Mode)
|
|
374
|
+
|
|
375
|
+
```bash
|
|
376
|
+
# Day 1: Start feature
|
|
377
|
+
git checkout main && git pull origin main
|
|
378
|
+
git checkout -b feature/user-authentication
|
|
379
|
+
edit src/zcl_auth_handler.clas.abap
|
|
380
|
+
abapgit-agent syntax --files src/zcl_auth_handler.clas.abap
|
|
381
|
+
git add . && git commit -m "wip: add basic auth logic"
|
|
382
|
+
git push origin feature/user-authentication
|
|
383
|
+
git fetch origin main && git rebase origin/main
|
|
384
|
+
git push origin feature/user-authentication --force-with-lease
|
|
385
|
+
abapgit-agent pull --files src/zcl_auth_handler.clas.abap
|
|
386
|
+
|
|
387
|
+
# Day 2: Continue (colleague pushed to main overnight)
|
|
388
|
+
git fetch origin main && git rebase origin/main
|
|
389
|
+
# If conflicts: resolve, git add, git rebase --continue
|
|
390
|
+
git push origin feature/user-authentication --force-with-lease
|
|
391
|
+
edit src/zcl_auth_handler.clas.abap
|
|
392
|
+
git add . && git commit -m "feat: complete auth logic"
|
|
393
|
+
git push origin feature/user-authentication
|
|
394
|
+
git fetch origin main && git rebase origin/main
|
|
395
|
+
git push origin feature/user-authentication --force-with-lease
|
|
396
|
+
abapgit-agent pull --files src/zcl_auth_handler.clas.abap
|
|
397
|
+
|
|
398
|
+
# Day 3: Finish feature
|
|
399
|
+
abapgit-agent unit --files src/zcl_auth_handler.clas.testclasses.abap
|
|
400
|
+
git fetch origin main && git rebase origin/main
|
|
401
|
+
git push origin feature/user-authentication --force-with-lease
|
|
402
|
+
# Create PR on GitHub/GitLab (squash 3 commits into 1)
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### Trunk Workflow (`"mode": "trunk"`)
|
|
406
|
+
|
|
407
|
+
If workflow mode is `"trunk"` or not set, commit directly to the default branch:
|
|
408
|
+
|
|
409
|
+
```bash
|
|
410
|
+
git checkout main # or master/develop (auto-detected)
|
|
411
|
+
git pull origin main
|
|
412
|
+
edit src/zcl_auth_handler.clas.abap
|
|
413
|
+
abapgit-agent syntax --files src/zcl_auth_handler.clas.abap
|
|
414
|
+
git add . && git commit -m "feat: add authentication handler"
|
|
415
|
+
git push origin main
|
|
416
|
+
abapgit-agent pull --files src/zcl_auth_handler.clas.abap
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### AI Tool Guidelines
|
|
420
|
+
|
|
421
|
+
**Read `.abapGitAgent` to determine workflow mode:**
|
|
422
|
+
|
|
423
|
+
**When `workflow.mode = "branch"`:**
|
|
424
|
+
1. ✓ Auto-detect default branch (main/master/develop)
|
|
425
|
+
2. ✓ Create feature branches (naming: `feature/description`)
|
|
426
|
+
3. ✓ Always `git fetch origin <default> && git rebase origin/<default>` before `pull` command
|
|
427
|
+
4. ✓ Use `--force-with-lease` after rebase (never `--force`)
|
|
428
|
+
5. ✓ Create PR with squash merge when feature complete
|
|
429
|
+
6. ✗ Never commit directly to default branch
|
|
430
|
+
7. ✗ Never use `git push --force` (always use `--force-with-lease`)
|
|
431
|
+
|
|
432
|
+
**When `workflow.mode = "trunk"` or not set:**
|
|
433
|
+
1. ✓ Commit directly to default branch
|
|
434
|
+
2. ✓ Keep commits clean and atomic
|
|
435
|
+
3. ✓ `git pull origin <default>` before push
|
|
436
|
+
4. ✗ Don't create feature branches
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
|
|
440
|
+
## Development Workflow (Detailed)
|
|
441
|
+
|
|
442
|
+
```
|
|
443
|
+
1. Read .abapGitAgent → get folder value AND workflow.mode
|
|
255
444
|
│
|
|
256
445
|
▼
|
|
257
446
|
2. Research → use ref command for unfamiliar topics
|
|
@@ -260,15 +449,15 @@ abapgit-agent unit --files src/zcl_test1.clas.testclasses.abap,src/zcl_test2.cla
|
|
|
260
449
|
3. Write code → place in correct folder (e.g., src/zcl_*.clas.abap)
|
|
261
450
|
│
|
|
262
451
|
▼
|
|
263
|
-
4. Syntax check (for CLAS, INTF, PROG only)
|
|
452
|
+
4. Syntax check (for CLAS, INTF, PROG, DDLS only)
|
|
264
453
|
│
|
|
265
|
-
├─► CLAS/INTF/PROG → abapgit-agent syntax --files <file>
|
|
454
|
+
├─► CLAS/INTF/PROG/DDLS → abapgit-agent syntax --files <file>
|
|
266
455
|
│ │
|
|
267
456
|
│ ├─► Errors? → Fix locally (no commit needed), re-run syntax
|
|
268
457
|
│ │
|
|
269
458
|
│ └─► Clean ✅ → Proceed to commit
|
|
270
459
|
│
|
|
271
|
-
└─► Other types (
|
|
460
|
+
└─► Other types (FUGR, TABL, etc.) → Skip syntax, go to commit
|
|
272
461
|
│
|
|
273
462
|
▼
|
|
274
463
|
5. Commit and push → git add . && git commit && git push
|
|
@@ -301,34 +490,88 @@ abapgit-agent unit --files src/zcl_test1.clas.testclasses.abap,src/zcl_test2.cla
|
|
|
301
490
|
|
|
302
491
|
**IMPORTANT**:
|
|
303
492
|
- **Use `syntax` BEFORE commit** for CLAS/INTF/PROG/DDLS - catches errors early, no git pollution
|
|
304
|
-
- **Syntax checks files INDEPENDENTLY** -
|
|
305
|
-
- **For dependent files** (interface + class
|
|
493
|
+
- **Syntax checks files INDEPENDENTLY** - syntax checker doesn't have access to uncommitted files
|
|
494
|
+
- **For dependent files** (interface + class): Create/activate underlying object FIRST, then dependent object (see workflow below)
|
|
306
495
|
- **DDLS requires proper annotations** - CDS views need `@AbapCatalog.sqlViewName`, view entities don't
|
|
307
496
|
- **ALWAYS push to git BEFORE running pull** - abapGit reads from git
|
|
308
497
|
- **Use `inspect` AFTER pull** for unsupported types or if pull fails
|
|
309
498
|
|
|
499
|
+
**Working with dependent objects (RECOMMENDED APPROACH):**
|
|
500
|
+
|
|
501
|
+
When creating objects with dependencies (e.g., interface → class), create and activate the underlying object FIRST:
|
|
502
|
+
|
|
503
|
+
```bash
|
|
504
|
+
# Step 1: Create interface, syntax check, commit, activate
|
|
505
|
+
vim src/zif_my_interface.intf.abap
|
|
506
|
+
abapgit-agent syntax --files src/zif_my_interface.intf.abap # ✅ Works (no dependencies)
|
|
507
|
+
git add src/zif_my_interface.intf.abap src/zif_my_interface.intf.xml
|
|
508
|
+
git commit -m "feat: add interface"
|
|
509
|
+
git push
|
|
510
|
+
abapgit-agent pull --files src/zif_my_interface.intf.abap # Interface now activated
|
|
511
|
+
|
|
512
|
+
# Step 2: Create class, syntax check, commit, activate
|
|
513
|
+
vim src/zcl_my_class.clas.abap
|
|
514
|
+
abapgit-agent syntax --files src/zcl_my_class.clas.abap # ✅ Works (interface already activated)
|
|
515
|
+
git add src/zcl_my_class.clas.abap src/zcl_my_class.clas.xml
|
|
516
|
+
git commit -m "feat: add class implementing interface"
|
|
517
|
+
git push
|
|
518
|
+
abapgit-agent pull --files src/zcl_my_class.clas.abap
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
**Benefits:**
|
|
522
|
+
- ✅ Syntax checking works for both objects
|
|
523
|
+
- ✅ Each step is validated independently
|
|
524
|
+
- ✅ Easier to debug if something fails
|
|
525
|
+
- ✅ Cleaner workflow
|
|
526
|
+
|
|
527
|
+
**Alternative approach (when interface design is uncertain):**
|
|
528
|
+
|
|
529
|
+
If the interface might need changes while implementing the class, commit both together:
|
|
530
|
+
|
|
531
|
+
```bash
|
|
532
|
+
# Create both files
|
|
533
|
+
vim src/zif_my_interface.intf.abap
|
|
534
|
+
vim src/zcl_my_class.clas.abap
|
|
535
|
+
|
|
536
|
+
# Skip syntax (files depend on each other), commit together
|
|
537
|
+
git add src/zif_my_interface.intf.abap src/zif_my_interface.intf.xml
|
|
538
|
+
git add src/zcl_my_class.clas.abap src/zcl_my_class.clas.xml
|
|
539
|
+
git commit -m "feat: add interface and implementing class"
|
|
540
|
+
git push
|
|
541
|
+
|
|
542
|
+
# Pull both together
|
|
543
|
+
abapgit-agent pull --files src/zif_my_interface.intf.abap,src/zcl_my_class.clas.abap
|
|
544
|
+
|
|
545
|
+
# Use inspect if errors occur
|
|
546
|
+
abapgit-agent inspect --files src/zcl_my_class.clas.abap
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
**Use this approach when:**
|
|
550
|
+
- ❌ Interface design is still evolving
|
|
551
|
+
- ❌ Multiple iterations expected
|
|
552
|
+
|
|
310
553
|
**Working with mixed file types:**
|
|
311
554
|
When modifying multiple files of different types (e.g., 1 class + 1 CDS view):
|
|
312
|
-
1. Run `syntax` on supported files
|
|
555
|
+
1. Run `syntax` on independent supported files (CLAS, INTF, PROG, DDLS)
|
|
313
556
|
2. Commit ALL files together (including unsupported types)
|
|
314
557
|
3. Push and pull ALL files together
|
|
315
558
|
|
|
316
559
|
Example:
|
|
317
560
|
```bash
|
|
318
|
-
# Check syntax on independent
|
|
319
|
-
abapgit-agent syntax --files src/zcl_my_class.clas.abap,src/
|
|
561
|
+
# Check syntax on independent files only
|
|
562
|
+
abapgit-agent syntax --files src/zcl_my_class.clas.abap,src/zc_my_view.ddls.asddls
|
|
320
563
|
|
|
321
|
-
# Commit and push all files
|
|
322
|
-
git add src/zcl_my_class.clas.abap src/
|
|
323
|
-
git commit -m "feat: add class
|
|
564
|
+
# Commit and push all files
|
|
565
|
+
git add src/zcl_my_class.clas.abap src/zc_my_view.ddls.asddls
|
|
566
|
+
git commit -m "feat: add class and CDS view"
|
|
324
567
|
git push
|
|
325
568
|
|
|
326
569
|
# Pull all files together
|
|
327
|
-
abapgit-agent pull --files src/zcl_my_class.clas.abap,src/
|
|
570
|
+
abapgit-agent pull --files src/zcl_my_class.clas.abap,src/zc_my_view.ddls.asddls
|
|
328
571
|
```
|
|
329
572
|
|
|
330
573
|
**When to use syntax vs inspect vs view**:
|
|
331
|
-
- **syntax**: Check LOCAL code BEFORE commit (CLAS, INTF, PROG
|
|
574
|
+
- **syntax**: Check LOCAL code BEFORE commit (CLAS, INTF, PROG, DDLS)
|
|
332
575
|
- **inspect**: Check ACTIVATED code AFTER pull (all types, runs Code Inspector)
|
|
333
576
|
- **view**: Understand object STRUCTURE (not for debugging errors)
|
|
334
577
|
|
|
@@ -338,21 +581,29 @@ abapgit-agent pull --files src/zcl_my_class.clas.abap,src/zif_my_intf.intf.abap,
|
|
|
338
581
|
|
|
339
582
|
```
|
|
340
583
|
1. Identify file extension(s) AND dependencies
|
|
341
|
-
├─ .clas.abap or .clas.testclasses.abap → CLAS ✅ syntax supported
|
|
342
|
-
├─ .intf.abap → INTF ✅ syntax supported
|
|
584
|
+
├─ .clas.abap or .clas.testclasses.abap → CLAS ✅ syntax supported
|
|
585
|
+
├─ .intf.abap → INTF ✅ syntax supported
|
|
343
586
|
├─ .prog.abap → PROG ✅ syntax supported
|
|
344
587
|
├─ .ddls.asddls → DDLS ✅ syntax supported (requires proper annotations)
|
|
345
588
|
└─ All other extensions → ❌ syntax not supported
|
|
346
589
|
|
|
347
590
|
2. Check for dependencies:
|
|
348
|
-
├─ Interface + implementing class? →
|
|
349
|
-
├─ Class A uses class B? →
|
|
350
|
-
├─
|
|
351
|
-
└─ Unrelated bug fixes across files? →
|
|
591
|
+
├─ Interface + implementing class? → DEPENDENT (interface is underlying)
|
|
592
|
+
├─ Class A uses class B? → DEPENDENT (class B is underlying)
|
|
593
|
+
├─ CDS view uses table? → INDEPENDENT (table already exists)
|
|
594
|
+
└─ Unrelated bug fixes across files? → INDEPENDENT
|
|
352
595
|
|
|
353
596
|
3. For SUPPORTED types (CLAS/INTF/PROG/DDLS):
|
|
354
|
-
├─
|
|
355
|
-
|
|
597
|
+
├─ INDEPENDENT files → Run syntax → Fix errors → Commit → Push → Pull
|
|
598
|
+
│
|
|
599
|
+
└─ DEPENDENT files (NEW objects):
|
|
600
|
+
├─ RECOMMENDED: Create underlying object first (interface, base class, etc.)
|
|
601
|
+
│ 1. Create underlying object → Syntax → Commit → Push → Pull
|
|
602
|
+
│ 2. Create dependent object → Syntax (works!) → Commit → Push → Pull
|
|
603
|
+
│ ✅ Benefits: Both syntax checks work, cleaner workflow
|
|
604
|
+
│
|
|
605
|
+
└─ ALTERNATIVE: If interface design uncertain, commit both together
|
|
606
|
+
→ Skip syntax → Commit both → Push → Pull → (if errors: inspect)
|
|
356
607
|
|
|
357
608
|
4. For UNSUPPORTED types (FUGR, TABL, etc.):
|
|
358
609
|
Write code → Skip syntax → Commit → Push → Pull → (if errors: inspect)
|
|
@@ -361,6 +612,32 @@ abapgit-agent pull --files src/zcl_my_class.clas.abap,src/zif_my_intf.intf.abap,
|
|
|
361
612
|
Write all code → Run syntax on independent supported files ONLY → Commit ALL → Push → Pull ALL
|
|
362
613
|
```
|
|
363
614
|
|
|
615
|
+
**Example workflows:**
|
|
616
|
+
|
|
617
|
+
**Scenario 1: Interface + Class (RECOMMENDED)**
|
|
618
|
+
```bash
|
|
619
|
+
# Step 1: Interface first
|
|
620
|
+
vim src/zif_calculator.intf.abap
|
|
621
|
+
abapgit-agent syntax --files src/zif_calculator.intf.abap # ✅ Works
|
|
622
|
+
git commit -am "feat: add calculator interface" && git push
|
|
623
|
+
abapgit-agent pull --files src/zif_calculator.intf.abap # Interface activated
|
|
624
|
+
|
|
625
|
+
# Step 2: Class next
|
|
626
|
+
vim src/zcl_calculator.clas.abap
|
|
627
|
+
abapgit-agent syntax --files src/zcl_calculator.clas.abap # ✅ Works (interface exists!)
|
|
628
|
+
git commit -am "feat: implement calculator" && git push
|
|
629
|
+
abapgit-agent pull --files src/zcl_calculator.clas.abap
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
**Scenario 2: Multiple independent classes**
|
|
633
|
+
```bash
|
|
634
|
+
# All syntax checks work (no dependencies)
|
|
635
|
+
vim src/zcl_class1.clas.abap src/zcl_class2.clas.abap
|
|
636
|
+
abapgit-agent syntax --files src/zcl_class1.clas.abap,src/zcl_class2.clas.abap
|
|
637
|
+
git commit -am "feat: add utility classes" && git push
|
|
638
|
+
abapgit-agent pull --files src/zcl_class1.clas.abap,src/zcl_class2.clas.abap
|
|
639
|
+
```
|
|
640
|
+
|
|
364
641
|
**Error indicators after pull:**
|
|
365
642
|
- ❌ **"Error updating where-used list"** → SYNTAX ERROR - run `inspect` for details
|
|
366
643
|
- ❌ **Objects in "Failed Objects Log"** → SYNTAX ERROR - run `inspect`
|
|
@@ -370,9 +647,10 @@ abapgit-agent pull --files src/zcl_my_class.clas.abap,src/zif_my_intf.intf.abap,
|
|
|
370
647
|
### Commands
|
|
371
648
|
|
|
372
649
|
```bash
|
|
373
|
-
# 1. Syntax check LOCAL code BEFORE commit (CLAS, INTF, PROG
|
|
650
|
+
# 1. Syntax check LOCAL code BEFORE commit (CLAS, INTF, PROG, DDLS)
|
|
374
651
|
abapgit-agent syntax --files src/zcl_my_class.clas.abap
|
|
375
|
-
abapgit-agent syntax --files src/
|
|
652
|
+
abapgit-agent syntax --files src/zc_my_view.ddls.asddls
|
|
653
|
+
abapgit-agent syntax --files src/zcl_class1.clas.abap,src/zif_intf1.intf.abap,src/zc_view.ddls.asddls
|
|
376
654
|
|
|
377
655
|
# 2. Pull/activate AFTER pushing to git
|
|
378
656
|
abapgit-agent pull --files src/zcl_class1.clas.abap,src/zcl_class2.clas.abap
|
|
@@ -11,12 +11,13 @@ grand_parent: ABAP Development
|
|
|
11
11
|
**Searchable keywords**: unit test, AUnit, test class, cl_abap_unit_assert, FOR TESTING, setup, teardown, RISK LEVEL, DURATION, CDS test double, CL_CDS_TEST_ENVIRONMENT
|
|
12
12
|
|
|
13
13
|
## TOPICS IN THIS FILE
|
|
14
|
-
1. Local Test Classes - line
|
|
15
|
-
2. File Structure - line
|
|
16
|
-
3. Required Elements - line
|
|
17
|
-
4. Naming Conventions - line
|
|
18
|
-
5.
|
|
19
|
-
6. CDS
|
|
14
|
+
1. Local Test Classes - line 22
|
|
15
|
+
2. File Structure - line 24
|
|
16
|
+
3. Required Elements - line 35
|
|
17
|
+
4. Naming Conventions - line 67
|
|
18
|
+
5. Common Mistake: DDLS Testing - line 133
|
|
19
|
+
6. CDS Test Doubles - line 163
|
|
20
|
+
7. CDS with Aggregations - line 247
|
|
20
21
|
|
|
21
22
|
## Unit Testing with Local Test Classes
|
|
22
23
|
|
|
@@ -122,6 +123,44 @@ cl_abap_unit_assert=>assert_true( act = lv_bool msg = 'Should be true' ).
|
|
|
122
123
|
- ❌ Don't reference `<TESTCLASS>` in XML - abapGit auto-detects `.testclasses.abap`
|
|
123
124
|
- ❌ Don't use nested local classes inside the main class definition
|
|
124
125
|
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
### ⚠️ Common Mistake: CDS Views Don't Have `.testclasses.abap` Files
|
|
129
|
+
|
|
130
|
+
**WRONG - Creating test file for DDLS**:
|
|
131
|
+
```
|
|
132
|
+
zc_my_view.ddls.asddls
|
|
133
|
+
zc_my_view.ddls.testclasses.abap ❌ This doesn't work!
|
|
134
|
+
zc_my_view.ddls.xml
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**Error you'll see**:
|
|
138
|
+
```
|
|
139
|
+
The REPORT/PROGRAM statement is missing, or the program type is INCLUDE.
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**CORRECT - Test CDS views using separate CLAS test classes**:
|
|
143
|
+
```
|
|
144
|
+
zc_flight_revenue.ddls.asddls ← CDS view definition
|
|
145
|
+
zc_flight_revenue.ddls.xml ← CDS metadata
|
|
146
|
+
|
|
147
|
+
zcl_test_flight_revenue.clas.abap ← Test class definition
|
|
148
|
+
zcl_test_flight_revenue.clas.testclasses.abap ← Test implementation
|
|
149
|
+
zcl_test_flight_revenue.clas.xml ← Class metadata (WITH_UNIT_TESTS=X)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**Why**: Each ABAP object type has its own testing pattern:
|
|
153
|
+
- **CLAS** (classes): Use `.clas.testclasses.abap` for the same class
|
|
154
|
+
- **DDLS** (CDS views): Use separate CLAS test class with CDS Test Double Framework
|
|
155
|
+
- **FUGR** (function groups): Use `.fugr.testclasses.abap`
|
|
156
|
+
- **PROG** (programs): Use `.prog.testclasses.abap`
|
|
157
|
+
|
|
158
|
+
**Don't assume patterns from one object type apply to another!**
|
|
159
|
+
|
|
160
|
+
See "Unit Testing CDS Views" section below for the correct CDS testing approach.
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
125
164
|
### Running Tests
|
|
126
165
|
|
|
127
166
|
In ABAP: SE24 → Test → Execute Unit Tests
|
|
@@ -11,11 +11,15 @@ grand_parent: ABAP Development
|
|
|
11
11
|
**Searchable keywords**: CDS, DDL, DDLS, CDS view, @AbapCatalog, @AccessControl, association, projection, consumption
|
|
12
12
|
|
|
13
13
|
## TOPICS IN THIS FILE
|
|
14
|
-
1. File Naming - line
|
|
15
|
-
2. DDL Source (.ddls.asddls) - line
|
|
16
|
-
3. Annotations - line
|
|
17
|
-
4. Associations - line
|
|
18
|
-
5. CDS
|
|
14
|
+
1. File Naming - line 96
|
|
15
|
+
2. DDL Source (.ddls.asddls) - line 107
|
|
16
|
+
3. Annotations - line 141
|
|
17
|
+
4. Associations - line 164
|
|
18
|
+
5. CDS Best Practices - line 194
|
|
19
|
+
- Key Field Ordering (STRICT RULE) - line 198
|
|
20
|
+
- Currency/Amount Field Aggregation - line 230
|
|
21
|
+
- Choosing Currency Fields for Aggregation - line 255
|
|
22
|
+
6. CDS Test Doubles - see 03_testing.md
|
|
19
23
|
|
|
20
24
|
## Creating CDS Views (DDLS)
|
|
21
25
|
|
|
@@ -188,6 +192,110 @@ where devclass not like '$%'
|
|
|
188
192
|
3. **Expose associations**: Add the association name at the end of the SELECT to expose it for OData navigation
|
|
189
193
|
4. **Activation warnings**: Search help warnings are informational and don't block activation
|
|
190
194
|
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## CDS Best Practices and Common Patterns
|
|
198
|
+
|
|
199
|
+
### Key Field Ordering (STRICT RULE)
|
|
200
|
+
|
|
201
|
+
CDS views enforce strict key field ordering that differs from regular SQL:
|
|
202
|
+
|
|
203
|
+
❌ **WRONG - Non-key field between keys**:
|
|
204
|
+
```abap
|
|
205
|
+
{
|
|
206
|
+
key Flight.carrid as Carrid,
|
|
207
|
+
Airline.carrname as Carrname, // ← breaks contiguity!
|
|
208
|
+
key Flight.connid as Connid,
|
|
209
|
+
key Flight.fldate as Fldate,
|
|
210
|
+
...
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
✅ **CORRECT - All keys first, then non-keys**:
|
|
215
|
+
```abap
|
|
216
|
+
{
|
|
217
|
+
key Flight.carrid as Carrid,
|
|
218
|
+
key Flight.connid as Connid,
|
|
219
|
+
key Flight.fldate as Fldate,
|
|
220
|
+
Airline.carrname as Carrname, // ← after all keys
|
|
221
|
+
...
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
**Rules:**
|
|
226
|
+
1. All key fields MUST be at the beginning of the field list
|
|
227
|
+
2. Key fields MUST be contiguous (no non-key fields in between)
|
|
228
|
+
3. Key fields must be declared before any non-key fields
|
|
229
|
+
|
|
230
|
+
**Error message**: "Key must be contiguous and start at the first position"
|
|
231
|
+
|
|
232
|
+
**Why this rule exists**: CDS views are not just SQL - they represent data models with strict structural requirements for consistency across the system.
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
### Currency/Amount Field Aggregation
|
|
237
|
+
|
|
238
|
+
When aggregating currency or amount fields in CDS views, use semantic annotations instead of complex casting:
|
|
239
|
+
|
|
240
|
+
❌ **WRONG - Complex casting (will fail)**:
|
|
241
|
+
```abap
|
|
242
|
+
cast(coalesce(sum(Booking.loccuram), 0) as abap.curr(15,2))
|
|
243
|
+
// Error: Data type CURR is not supported at this position
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
✅ **CORRECT - Semantic annotation + simple aggregation**:
|
|
247
|
+
```abap
|
|
248
|
+
@Semantics.amount.currencyCode: 'Currency'
|
|
249
|
+
sum(Booking.loccuram) as TotalRevenue,
|
|
250
|
+
currency as Currency
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
**Key points:**
|
|
254
|
+
- Use `@Semantics.amount.currencyCode` to link amount to currency field
|
|
255
|
+
- Let the framework handle data typing automatically
|
|
256
|
+
- Don't over-engineer with casts or type conversions
|
|
257
|
+
- Keep it simple: annotation + aggregation function
|
|
258
|
+
|
|
259
|
+
**Reference**:
|
|
260
|
+
```bash
|
|
261
|
+
abapgit-agent ref "CDS aggregation"
|
|
262
|
+
# Check: zdemo_abap_cds_ve_agg_exp.ddls.asddls for working examples
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
### Choosing Currency Fields for Aggregation
|
|
268
|
+
|
|
269
|
+
**Understand your data model before aggregating currency fields** - not all currency fields can be safely summed:
|
|
270
|
+
|
|
271
|
+
❌ **Dangerous - Foreign currency (different keys per row)**:
|
|
272
|
+
```abap
|
|
273
|
+
sum(Booking.forcuram) // FORCURAM has different FORCURKEY per booking!
|
|
274
|
+
// Problem: Can't safely sum USD + EUR + GBP without conversion
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
✅ **Safe - Local currency (shared key per group)**:
|
|
278
|
+
```abap
|
|
279
|
+
sum(Booking.loccuram) // LOCCURAM shares LOCCURKEY per airline
|
|
280
|
+
// Safe: All bookings for one airline use the same currency
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
**Data Model Example (SBOOK table)**:
|
|
284
|
+
```
|
|
285
|
+
FORCURAM + FORCURKEY = Payment currency (USD, EUR, GBP - different per booking)
|
|
286
|
+
LOCCURAM + LOCCURKEY = Airline currency (one currency per airline)
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
**Analysis Steps:**
|
|
290
|
+
1. Identify all currency fields in source tables
|
|
291
|
+
2. Check which currency code field each amount uses
|
|
292
|
+
3. Verify currency code is constant within your aggregation groups
|
|
293
|
+
4. Choose the field with consistent currency per group
|
|
294
|
+
|
|
295
|
+
**Rule**: Only aggregate amounts that share the same currency code within your grouping (GROUP BY).
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
191
299
|
## CDS Syntax Reference
|
|
192
300
|
|
|
193
301
|
When working with CDS view syntax (arithmetic, built-in functions, aggregations, etc.):
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "abapgit-agent",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.3",
|
|
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": [
|
|
@@ -34,6 +34,7 @@
|
|
|
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
36
|
"test:lifecycle": "node tests/run-all.js --lifecycle",
|
|
37
|
+
"test:pull": "node tests/run-all.js --pull",
|
|
37
38
|
"pull": "node bin/abapgit-agent",
|
|
38
39
|
"release": "node scripts/release.js",
|
|
39
40
|
"unrelease": "node scripts/unrelease.js"
|
package/src/commands/init.js
CHANGED
|
@@ -172,39 +172,100 @@ module.exports = {
|
|
|
172
172
|
}
|
|
173
173
|
console.log(`📌 Git remote: ${gitUrl}`);
|
|
174
174
|
|
|
175
|
-
// Check if .abapGitAgent already exists
|
|
175
|
+
// Check if .abapGitAgent already exists - merge if it does
|
|
176
176
|
const configPath = pathModule.join(process.cwd(), '.abapGitAgent');
|
|
177
|
+
let config = null;
|
|
178
|
+
let isUpdate = false;
|
|
179
|
+
|
|
177
180
|
if (fs.existsSync(configPath)) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
181
|
+
isUpdate = true;
|
|
182
|
+
try {
|
|
183
|
+
// Read existing configuration
|
|
184
|
+
const currentConfig = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
185
|
+
|
|
186
|
+
console.log('📝 Updating existing .abapGitAgent configuration');
|
|
187
|
+
console.log('');
|
|
188
|
+
console.log('Current values:');
|
|
189
|
+
console.log(` Package: ${currentConfig.package || '(not set)'}`);
|
|
190
|
+
console.log(` Folder: ${currentConfig.folder || '(not set)'}`);
|
|
191
|
+
console.log(` Host: ${currentConfig.host || '(not set)'}`);
|
|
192
|
+
console.log('');
|
|
193
|
+
|
|
194
|
+
// Merge: keep existing values, update package and folder
|
|
195
|
+
config = currentConfig;
|
|
196
|
+
|
|
197
|
+
// Track what changed
|
|
198
|
+
const changes = [];
|
|
199
|
+
|
|
200
|
+
if (packageName && packageName !== currentConfig.package) {
|
|
201
|
+
const oldValue = currentConfig.package || '(not set)';
|
|
202
|
+
config.package = packageName;
|
|
203
|
+
changes.push(`package: ${oldValue} → ${packageName}`);
|
|
204
|
+
}
|
|
182
205
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
206
|
+
if (folder && folder !== currentConfig.folder) {
|
|
207
|
+
const oldValue = currentConfig.folder || '(not set)';
|
|
208
|
+
config.folder = folder;
|
|
209
|
+
changes.push(`folder: ${oldValue} → ${folder}`);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (changes.length === 0) {
|
|
213
|
+
console.log('⚠️ No changes needed - package and folder are already set correctly');
|
|
214
|
+
console.log('');
|
|
215
|
+
console.log('To change other settings, edit .abapGitAgent manually');
|
|
216
|
+
// Don't exit - continue with other setup tasks (CLAUDE.md, guidelines, etc.)
|
|
217
|
+
} else {
|
|
218
|
+
console.log('Changes to be made:');
|
|
219
|
+
changes.forEach(change => console.log(` ${change}`));
|
|
220
|
+
console.log('');
|
|
221
|
+
console.log('✅ Keeping all other settings (host, credentials, workflow, etc.)');
|
|
222
|
+
console.log('');
|
|
223
|
+
}
|
|
224
|
+
} catch (error) {
|
|
225
|
+
console.error('Error: .abapGitAgent exists but could not read it:');
|
|
226
|
+
console.error(` ${error.message}`);
|
|
227
|
+
console.error('');
|
|
228
|
+
console.error('To fix:');
|
|
229
|
+
console.error(' 1. Check if .abapGitAgent contains valid JSON');
|
|
230
|
+
console.error(' 2. Or delete it: rm .abapGitAgent');
|
|
231
|
+
process.exit(1);
|
|
232
|
+
}
|
|
233
|
+
} else {
|
|
234
|
+
// Create new config from template
|
|
235
|
+
const samplePath = pathModule.join(__dirname, '..', '..', '.abapGitAgent.example');
|
|
236
|
+
if (!fs.existsSync(samplePath)) {
|
|
237
|
+
console.error('Error: .abapGitAgent.example not found.');
|
|
238
|
+
process.exit(1);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
try {
|
|
242
|
+
// Read sample and update with package/folder
|
|
243
|
+
const sampleContent = fs.readFileSync(samplePath, 'utf8');
|
|
244
|
+
config = JSON.parse(sampleContent);
|
|
245
|
+
config.package = packageName;
|
|
246
|
+
config.folder = folder;
|
|
247
|
+
} catch (error) {
|
|
248
|
+
console.error(`Error reading .abapGitAgent.example: ${error.message}`);
|
|
249
|
+
process.exit(1);
|
|
250
|
+
}
|
|
188
251
|
}
|
|
189
252
|
|
|
253
|
+
// Write the config (either new or updated)
|
|
190
254
|
try {
|
|
191
|
-
// Read sample and update with package/folder
|
|
192
|
-
const sampleContent = fs.readFileSync(samplePath, 'utf8');
|
|
193
|
-
const config = JSON.parse(sampleContent);
|
|
194
|
-
config.package = packageName;
|
|
195
|
-
config.folder = folder;
|
|
196
|
-
|
|
197
|
-
// Write updated config
|
|
198
255
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
|
|
199
|
-
|
|
256
|
+
if (isUpdate) {
|
|
257
|
+
console.log(`✅ Updated .abapGitAgent`);
|
|
258
|
+
} else {
|
|
259
|
+
console.log(`✅ Created .abapGitAgent`);
|
|
260
|
+
}
|
|
200
261
|
} catch (error) {
|
|
201
|
-
console.error(`Error
|
|
262
|
+
console.error(`Error writing .abapGitAgent: ${error.message}`);
|
|
202
263
|
process.exit(1);
|
|
203
264
|
}
|
|
204
265
|
|
|
205
266
|
// Update .gitignore
|
|
206
267
|
const gitignorePath = pathModule.join(process.cwd(), '.gitignore');
|
|
207
|
-
const ignoreEntries = ['.abapGitAgent'
|
|
268
|
+
const ignoreEntries = ['.abapGitAgent'];
|
|
208
269
|
let existingIgnore = '';
|
|
209
270
|
|
|
210
271
|
if (fs.existsSync(gitignorePath)) {
|
package/src/commands/ref.js
CHANGED
|
@@ -63,7 +63,7 @@ module.exports = {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
// Pattern search (default)
|
|
66
|
-
const patternIndex = args.findIndex(
|
|
66
|
+
const patternIndex = args.findIndex(arg => !arg.startsWith('--'));
|
|
67
67
|
if (patternIndex === -1) {
|
|
68
68
|
console.error('Error: No pattern specified');
|
|
69
69
|
console.error('');
|
package/src/config.js
CHANGED
|
@@ -74,10 +74,25 @@ function isAbapIntegrationEnabled() {
|
|
|
74
74
|
return fs.existsSync(repoConfigPath);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Get workflow configuration
|
|
79
|
+
* @returns {Object} Workflow config with mode ('branch' or 'trunk') and optional defaultBranch
|
|
80
|
+
*/
|
|
81
|
+
function getWorkflowConfig() {
|
|
82
|
+
const cfg = loadConfig();
|
|
83
|
+
|
|
84
|
+
// Default to trunk mode if not specified (backward compatible)
|
|
85
|
+
return {
|
|
86
|
+
mode: cfg.workflow?.mode || 'trunk',
|
|
87
|
+
defaultBranch: cfg.workflow?.defaultBranch || null // null means auto-detect
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
77
91
|
module.exports = {
|
|
78
92
|
loadConfig,
|
|
79
93
|
getAbapConfig,
|
|
80
94
|
getAgentConfig,
|
|
81
95
|
getTransport,
|
|
82
|
-
isAbapIntegrationEnabled
|
|
96
|
+
isAbapIntegrationEnabled,
|
|
97
|
+
getWorkflowConfig
|
|
83
98
|
};
|
package/src/utils/git-utils.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
const pathModule = require('path');
|
|
5
5
|
const fs = require('fs');
|
|
6
|
+
const { execSync } = require('child_process');
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Get git remote URL from .git/config
|
|
@@ -51,8 +52,55 @@ function isGitRepo() {
|
|
|
51
52
|
return fs.existsSync(gitPath);
|
|
52
53
|
}
|
|
53
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Get the default/trunk branch name (main, master, develop, etc.)
|
|
57
|
+
* @param {string|null} configuredBranch - Branch name from config (overrides auto-detection)
|
|
58
|
+
* @returns {string} Default branch name
|
|
59
|
+
*/
|
|
60
|
+
function getDefaultBranch(configuredBranch = null) {
|
|
61
|
+
// If explicitly configured, use that
|
|
62
|
+
if (configuredBranch) {
|
|
63
|
+
return configuredBranch;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Method 1: Check remote HEAD (most accurate)
|
|
67
|
+
try {
|
|
68
|
+
const result = execSync('git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null', {
|
|
69
|
+
cwd: process.cwd(),
|
|
70
|
+
encoding: 'utf8'
|
|
71
|
+
}).trim();
|
|
72
|
+
|
|
73
|
+
// Result looks like: refs/remotes/origin/main
|
|
74
|
+
const match = result.match(/refs\/remotes\/origin\/(.+)/);
|
|
75
|
+
if (match && match[1]) {
|
|
76
|
+
return match[1];
|
|
77
|
+
}
|
|
78
|
+
} catch (e) {
|
|
79
|
+
// Ignore error, try next method
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Method 2: Check common branch names in remote
|
|
83
|
+
try {
|
|
84
|
+
const branches = execSync('git branch -r 2>/dev/null', {
|
|
85
|
+
cwd: process.cwd(),
|
|
86
|
+
encoding: 'utf8'
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Check in order of preference: main > master > develop
|
|
90
|
+
if (branches.includes('origin/main')) return 'main';
|
|
91
|
+
if (branches.includes('origin/master')) return 'master';
|
|
92
|
+
if (branches.includes('origin/develop')) return 'develop';
|
|
93
|
+
} catch (e) {
|
|
94
|
+
// Ignore error, use fallback
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Method 3: Fallback to 'main' (modern default)
|
|
98
|
+
return 'main';
|
|
99
|
+
}
|
|
100
|
+
|
|
54
101
|
module.exports = {
|
|
55
102
|
getRemoteUrl,
|
|
56
103
|
getBranch,
|
|
57
|
-
isGitRepo
|
|
104
|
+
isGitRepo,
|
|
105
|
+
getDefaultBranch
|
|
58
106
|
};
|