feat: abapGit roundtrip - export, deploy, and structure support#89
feat: abapGit roundtrip - export, deploy, and structure support#89ThePlenkov wants to merge 19 commits intomainfrom
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Add end-to-end abapGit roundtrip capability: export ABAP objects from SAP to abapGit-format files, then deploy them back. Includes new DDIC object handlers (DOMA, DTEL, TABL, TTYP), structure (TABL/DS) support, and the roundtrip/activate CLI commands. Key changes: ADK (adk): - Registry: add resolveType() with full-type-first fallback for subtypes - Registry: add getMainType() helper and getObjectUri() using resolveType - Model: add crudContract-based load/save, lock/unlock, activate lifecycle - ObjectSet: add deploy() with two-phase save+activate, BulkSaveResult - TABL: add AdkTable and AdkStructure models with source support - DOMA/DTEL/TTYP: add ADK models with CRUD contract endpoints - DEVC: preserve full ADT type (TABL/DS) instead of stripping subtypes - CLAS/INTF/PROG/FUGR: add save lifecycle (savePendingSources, checkUnchanged) - Export getMainType, resolveType, getObjectUri from index abapGit plugin (adt-plugin-abapgit): - XSD: reorder DD02V/DD03P fields to match abapGit output ordering - XSD: add DD04V fields (DDLANGUAGE, DDTEXT, DOMNAME, etc.) - Codegen: regenerate all schemas and types from updated XSDs - Handlers: add DOMA handler with domain-specific value serialization - Handlers: add DTEL handler with data element metadata serialization - Handlers: add TABL handler (tables) and structure handler (TABL/DS) - Handlers: add TTYP handler for table types - Handlers: add cds-to-abapgit.ts converter for CDS-sourced tables - Base: use getMainType() for file extension (TABL/DS -> .tabl) - Deserializer: use payload.type for correct subtype resolution - Tests: add DTEL and TABL handler tests CLI (adt-cli): - Commands: add check, unlock, import object commands - Import service: add single-object import by name - Import service: preserve full ADT type in object type filter - Plugin loader: support format plugins with import/export capabilities Export plugin (adt-export): - Commands: add roundtrip command (export -> deploy cycle) - Commands: add activate command for bulk activation - Export: enhanced FileTree with directory walking and file operations - Package.json: add @abapify/adk dependency Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <noreply@cognition.ai>
0760591 to
0da189a
Compare
|
View your CI Pipeline Execution ↗ for commit d7578d3
☁️ Nx Cloud last updated this comment at |
New package @abapify/adt-diff with command that compares local abapGit XML files against remote SAP objects. Uses projection-based XML normalization to eliminate false positives from formatting and field ordering differences. Key fixes in CDS-to-abapGit serializer: - Fix REFFIELD: strip table prefix from annotation value (e.g. ZAGE_STRUCTURE.CURRENCY_CODE -> CURRENCY_CODE) - Fix CUKY/UNIT default lengths (cuky=5, unit=3) so INTLEN and LENG are correctly emitted - Fix include serialization: plain include -> .INCLUDE only, include with suffix -> .INCLU-<SUFFIX> only (was emitting both) - Fix projectOnto array projection to use union of all element keys instead of just the first element's keys CDS parser (acds) enhancements: - Support 'include <name> with suffix <suffix>' syntax - Add Suffix keyword token, AST node, and visitor support Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <noreply@cognition.ai>
Add runtime type resolution to the TABL/structure abapGit serializer. Named type references (data elements, structures) are now resolved via ADT REST endpoints to determine: - COMPTYPE: 'E' (data element) vs 'S' (structure) - SHLPORIGIN: 'D' when data element has a search help - DATATYPE/MASK: 'STRU'/'STRUS' for structure references - DDTEXT: description text for include entries Implementation: - Add fetchText() utility to AdkObject base class for generic ADT GET - Add TypeResolver interface and wire it through buildDD03P (now async) - Add createAdtTypeResolver() factory that probes dataelements then structures endpoints with caching - Fix HTTP 406 by not sending Accept header (let server choose) Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <noreply@cognition.ai>
- Add --format ddl option to adt diff command for DDL-level comparison - Fix CUKY type to omit length (SAP convention: cuky has implicit length 5) - Fix .INCLU-<SUFFIX> handling: emit 'include <name> with suffix <sfx>;' - Add blank lines after opening brace and before closing brace - Add trailing newline to generated DDL output Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <noreply@cognition.ai>
… source These DD02V/DD03P fields are database values that abapGit reads from SAP. They cannot be reliably determined from CDS DDL source alone: - LANGDEP: language dependency flag (varies per table) - CLIDEP: client dependency flag (varies per table) - POSITION: field ordinal position (assigned by SAP runtime) Removing these eliminates false diffs in roundtrip comparison, where our serializer was emitting fields that the remote XML may or may not contain depending on actual SAP metadata. Generated with Devin Co-Authored-By: Devin <noreply@cognition.ai>
SAP ABAP File Formats uses .acds for CDS source code files, not .ddl. Updated the diff display label accordingly. Generated with Devin Co-Authored-By: Devin <noreply@cognition.ai>
LANGDEP=X is set by SAP DDIC when a structure/table contains a language-typed field (data element SPRAS or builtin type abap.lang). This is detectable from CDS source by checking if any member field references spras (named type) or uses abap.lang (builtin type). Fixes the roundtrip diff for zage_structure which has language : spras. Generated with Devin Co-Authored-By: Devin <noreply@cognition.ai>
Reorder field assignments in buildFieldDD03P to match the canonical DD03P structure definition order used by SAP/abapGit: FIELDNAME, KEYFLAG, ROLLNAME, ADMINFIELD, INTTYPE, INTLEN, NOTNULL, DATATYPE, LENG, DECIMALS, SHLPORIGIN, MASK, COMPTYPE, REFTABLE, REFFIELD Previously REFTABLE/REFFIELD were emitted before DATATYPE, and MASK was emitted after REFTABLE/REFFIELD. This caused field ordering diffs in roundtrip comparison even though the data was identical. Generated with Devin Co-Authored-By: Devin <noreply@cognition.ai>
This reverts commit 20a4ac7.
Switch DD02V and DD03P XSD definitions from all to sequence so field order is preserved for TABL serialization and roundtrip compatibility with SAP/abapGit output. Regenerate the derived schema and type files to match the updated XSD definitions and ignore generated schema output in Prettier.
There was a problem hiding this comment.
Nx Cloud is proposing a fix for your failed CI:
We address three ESLint errors introduced by this PR across check.ts, unlock.ts, and cds-to-abapgit.ts. Redundant : string type annotations on default-valued parameters are removed to satisfy @typescript-eslint/no-inferrable-types, and the re-thrown error in unlock.ts now passes { cause: unlockError } to satisfy the preserve-caught-error rule.
Tip
✅ We verified this fix by re-running adt-plugin-abapgit:lint.
Suggested Fix changes
diff --git a/packages/adt-cli/src/lib/commands/check.ts b/packages/adt-cli/src/lib/commands/check.ts
index 0e2577e..4d954e9 100644
--- a/packages/adt-cli/src/lib/commands/check.ts
+++ b/packages/adt-cli/src/lib/commands/check.ts
@@ -157,7 +157,7 @@ async function resolvePackageObjects(
*/
function buildCheckObjectListXml(
objects: Array<{ uri: string }>,
- version: string = 'active',
+ version = 'active',
): string {
const checkObjects = objects
.map(
diff --git a/packages/adt-cli/src/lib/commands/unlock.ts b/packages/adt-cli/src/lib/commands/unlock.ts
index 8dafcb3..777ca13 100644
--- a/packages/adt-cli/src/lib/commands/unlock.ts
+++ b/packages/adt-cli/src/lib/commands/unlock.ts
@@ -102,7 +102,9 @@ async function performUnlock(
if (msg.includes('not locked') || msg.includes('not enqueued')) {
console.log(`ℹ️ ${objectName} is not locked`);
} else {
- throw new Error(`Unlock failed for ${objectName}: ${msg}`);
+ throw new Error(`Unlock failed for ${objectName}: ${msg}`, {
+ cause: unlockError,
+ });
}
}
}
diff --git a/packages/adt-plugin-abapgit/src/lib/handlers/cds-to-abapgit.ts b/packages/adt-plugin-abapgit/src/lib/handlers/cds-to-abapgit.ts
index 5de3338..cc18148 100644
--- a/packages/adt-plugin-abapgit/src/lib/handlers/cds-to-abapgit.ts
+++ b/packages/adt-plugin-abapgit/src/lib/handlers/cds-to-abapgit.ts
@@ -415,7 +415,7 @@ async function buildFieldDD03P(
*/
export async function buildDD03P(
members: TableMember[],
- tableName: string = '',
+ tableName = '',
resolver?: TypeResolver,
): Promise<DD03PData[]> {
const entries: DD03PData[] = [];
diff --git a/packages/adt-plugin-abapgit/tests/handlers/dtel-e2e.test.ts b/packages/adt-plugin-abapgit/tests/handlers/dtel-e2e.test.ts
index 458d390..145455a 100644
--- a/packages/adt-plugin-abapgit/tests/handlers/dtel-e2e.test.ts
+++ b/packages/adt-plugin-abapgit/tests/handlers/dtel-e2e.test.ts
@@ -13,11 +13,16 @@ import assert from 'node:assert';
import { parseXml, type Schema } from '@abapify/ts-xsd';
-// Import the raw schema literals (these are the generated schema JS objects)
+// Import typed schemas and extract the raw schema literals via .schema
// The dataelementWrapper imports adtcore + dataelements schemas
-import dataelementWrapperSchema from '../../../adt-schemas/src/schemas/generated/schemas/custom/dataelementWrapper.ts';
-import adtcoreSchema from '../../../adt-schemas/src/schemas/generated/schemas/sap/adtcore.ts';
-import dataelementsSchema from '../../../adt-schemas/src/schemas/generated/schemas/sap/dataelements.ts';
+import {
+ dataelementWrapper,
+ adtcore,
+ dataelements,
+} from '@abapify/adt-schemas';
+const dataelementWrapperSchema = dataelementWrapper.schema;
+const adtcoreSchema = adtcore.schema;
+const dataelementsSchema = dataelements.schema;
// Import handler to trigger registration
import '../../src/lib/handlers/objects/dtel.ts';
Or Apply changes locally with:
npx nx-cloud apply-locally wGVs-khrH
Apply fix locally with your editor ↗ View interactive diff ↗
🎓 Learn more about Self-Healing CI on nx.dev
Tables with a key field of type CLNT (abap.clnt) or data element MANDT are client-dependent. Set CLIDEP=X in DD02V when detected. Adds 4 tests for CLIDEP detection covering: - key field with mandt data element - key field with abap.clnt builtin - structures (no key fields → no CLIDEP) - non-key mandt field (not client-dependent) Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <noreply@cognition.ai>
Change diff argument from single required <file> to variadic [files...] with glob expansion. Enables usage like: adt diff *.tabl.xml adt diff zage_tabl.tabl.xml zage_value_table.tabl.xml Multi-file mode shows per-object headers and aggregate summary. Single-file mode preserves the original detailed output. Exit code 1 if any differences found. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <noreply@cognition.ai>
Fixture only has 1 key field (CLIENT), tests expected 2 key fields and a 'key_field' that doesn't exist in the current fixture. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <noreply@cognition.ai>
Move 5 rules from .windsurf/rules/ into .agents/rules/ organized by domain (development/, planning/, git/). Both .windsurf/rules/ and .cognition/rules/ are now symlinks to .agents/rules/, keeping all AI tools (Windsurf, Devin, Claude) in sync from a single source. Added git/no-auto-commit.md: require explicit user approval before any git commit or push. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <noreply@cognition.ai>
- bundler-imports: fix glob *.ts -> **/*.ts (recursive) - package-versions: add trigger: model_decision - nx-circular-dependencies: add trigger: model_decision - nx-monorepo-setup: add trigger: model_decision - project-planning-memory: add description to frontmatter Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <noreply@cognition.ai>
Delete 4 agent rule files (nx-circular-dependencies, nx-monorepo-setup, project-planning-memory, spec-first-then-code) and merge their content into AGENTS.md as a single source of truth. AGENTS.md now covers: - Nx monorepo workflow (build/test/lint commands) - Package layout and dependency graph - Type flow architecture (XSD → schemas → contracts → client) - Plugin system and ADK object handlers - Save lifecycle and source comparison
Add cross-references between related rules (coding-conventions ↔ bundler-imports, project-planning-memory ↔ spec-first-then-code, no-auto-commit ↔ monitor-ci exception). Update skills to reference verification/after-changes checklist and relevant rules (xsd-best-practices, file-lifecycle, adt-ddic-mapping, adk-save-logic, tmp-folder-testing). Replace npx/pnpm with bunx in skills (add-endpoint, add-object-type, nx-generate
… for CDS comparison Rename `--format ddl` to `--source` flag (boolean) for clarity. When comparing CDS source, filter remote annotations to match local's annotation set — prevents spurious diffs from fields present in remote XML but absent in local (e.g. MATEFLAG). Also add MATEFLAG support in cds-to-abapgit (maps AbapCatalog.dataMaintenance annotation) and strengthen after-changes rule to require agents verify builds/tests
|


Summary
End-to-end abapGit roundtrip capability: export ABAP objects from SAP to abapGit-format XML/ABAP files, then deploy them back to the system. This PR adds new DDIC object handlers, structure (TABL/DS) support, and the roundtrip/activate CLI commands.
ADK (packages/adk)
abapGit Plugin (packages/adt-plugin-abapgit)
ABAP CDS Parser (packages/acds) — NEW PACKAGE
MCP (packages/adt-mcp)
CLI (packages/adt-cli)
Export Plugin (packages/adt-export)
Verified Roundtrip Scenarios
Key Bug Fixes
Remaining Work
Test plan
Submodules
Generated with Devin