abapgit-agent 1.0.0

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.
Files changed (53) hide show
  1. package/.abapGitAgent.example +11 -0
  2. package/API.md +271 -0
  3. package/CLAUDE.md +445 -0
  4. package/CLAUDE_MEM.md +88 -0
  5. package/ERROR_HANDLING.md +30 -0
  6. package/INSTALL.md +160 -0
  7. package/README.md +127 -0
  8. package/abap/CLAUDE.md +492 -0
  9. package/abap/package.devc.xml +10 -0
  10. package/abap/zcl_abgagt_agent.clas.abap +769 -0
  11. package/abap/zcl_abgagt_agent.clas.xml +15 -0
  12. package/abap/zcl_abgagt_cmd_factory.clas.abap +43 -0
  13. package/abap/zcl_abgagt_cmd_factory.clas.xml +15 -0
  14. package/abap/zcl_abgagt_command_inspect.clas.abap +192 -0
  15. package/abap/zcl_abgagt_command_inspect.clas.testclasses.abap +121 -0
  16. package/abap/zcl_abgagt_command_inspect.clas.xml +16 -0
  17. package/abap/zcl_abgagt_command_pull.clas.abap +80 -0
  18. package/abap/zcl_abgagt_command_pull.clas.testclasses.abap +87 -0
  19. package/abap/zcl_abgagt_command_pull.clas.xml +16 -0
  20. package/abap/zcl_abgagt_command_unit.clas.abap +297 -0
  21. package/abap/zcl_abgagt_command_unit.clas.xml +15 -0
  22. package/abap/zcl_abgagt_resource_health.clas.abap +25 -0
  23. package/abap/zcl_abgagt_resource_health.clas.xml +15 -0
  24. package/abap/zcl_abgagt_resource_inspect.clas.abap +62 -0
  25. package/abap/zcl_abgagt_resource_inspect.clas.xml +15 -0
  26. package/abap/zcl_abgagt_resource_pull.clas.abap +71 -0
  27. package/abap/zcl_abgagt_resource_pull.clas.xml +15 -0
  28. package/abap/zcl_abgagt_resource_unit.clas.abap +64 -0
  29. package/abap/zcl_abgagt_resource_unit.clas.xml +15 -0
  30. package/abap/zcl_abgagt_rest_handler.clas.abap +27 -0
  31. package/abap/zcl_abgagt_rest_handler.clas.xml +15 -0
  32. package/abap/zcl_abgagt_util.clas.abap +93 -0
  33. package/abap/zcl_abgagt_util.clas.testclasses.abap +84 -0
  34. package/abap/zcl_abgagt_util.clas.xml +16 -0
  35. package/abap/zif_abgagt_agent.intf.abap +134 -0
  36. package/abap/zif_abgagt_agent.intf.xml +15 -0
  37. package/abap/zif_abgagt_cmd_factory.intf.abap +7 -0
  38. package/abap/zif_abgagt_cmd_factory.intf.xml +15 -0
  39. package/abap/zif_abgagt_command.intf.abap +21 -0
  40. package/abap/zif_abgagt_command.intf.xml +15 -0
  41. package/abap/zif_abgagt_util.intf.abap +28 -0
  42. package/abap/zif_abgagt_util.intf.xml +15 -0
  43. package/bin/abapgit-agent +902 -0
  44. package/img/claude.png +0 -0
  45. package/package.json +31 -0
  46. package/scripts/claude-integration.js +351 -0
  47. package/scripts/test-integration.js +139 -0
  48. package/src/abap-client.js +314 -0
  49. package/src/agent.js +119 -0
  50. package/src/config.js +66 -0
  51. package/src/index.js +48 -0
  52. package/src/logger.js +39 -0
  53. package/src/server.js +116 -0
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
3
+ <asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
4
+ <asx:values>
5
+ <VSEOCLASS>
6
+ <CLSNAME>ZCL_ABGAGT_AGENT</CLSNAME>
7
+ <LANGU>E</LANGU>
8
+ <DESCRIPT>ABAP Git Agent - Main Agent API</DESCRIPT>
9
+ <EXPOSURE>2</EXPOSURE>
10
+ <STATE>1</STATE>
11
+ <UNICODE>X</UNICODE>
12
+ </VSEOCLASS>
13
+ </asx:values>
14
+ </asx:abap>
15
+ </abapGit>
@@ -0,0 +1,43 @@
1
+ CLASS zcl_abgagt_cmd_factory DEFINITION PUBLIC CREATE PRIVATE.
2
+ PUBLIC SECTION.
3
+ INTERFACES zif_abgagt_cmd_factory.
4
+ CLASS-METHODS get_instance
5
+ RETURNING VALUE(ro_factory) TYPE REF TO zif_abgagt_cmd_factory.
6
+ PRIVATE SECTION.
7
+ METHODS constructor.
8
+ TYPES: BEGIN OF ty_command_map,
9
+ command TYPE string,
10
+ class_name TYPE string,
11
+ END OF ty_command_map.
12
+ DATA mt_command_map TYPE TABLE OF ty_command_map.
13
+ ENDCLASS.
14
+
15
+ CLASS zcl_abgagt_cmd_factory IMPLEMENTATION.
16
+ METHOD get_instance.
17
+ DATA lo_factory TYPE REF TO zcl_abgagt_cmd_factory.
18
+ CREATE OBJECT lo_factory.
19
+ ro_factory = lo_factory.
20
+ ENDMETHOD.
21
+
22
+ METHOD constructor.
23
+ " Build command to class name mapping
24
+ mt_command_map = VALUE #(
25
+ ( command = zif_abgagt_command=>gc_pull class_name = 'ZCL_ABGAGT_COMMAND_PULL' )
26
+ ( command = zif_abgagt_command=>gc_inspect class_name = 'ZCL_ABGAGT_COMMAND_INSPECT' )
27
+ ( command = zif_abgagt_command=>gc_unit class_name = 'ZCL_ABGAGT_COMMAND_UNIT' )
28
+ ).
29
+ ENDMETHOD.
30
+
31
+ METHOD zif_abgagt_cmd_factory~get_command.
32
+ " Find class name for command
33
+ READ TABLE mt_command_map WITH KEY command = iv_command
34
+ ASSIGNING FIELD-SYMBOL(<ls_map>).
35
+ IF sy-subrc <> 0.
36
+ RETURN.
37
+ ENDIF.
38
+
39
+ " Create command instance dynamically
40
+ CREATE OBJECT ro_command TYPE (<ls_map>-class_name).
41
+ ENDMETHOD.
42
+
43
+ ENDCLASS.
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
3
+ <asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
4
+ <asx:values>
5
+ <VSEOCLASS>
6
+ <CLSNAME>ZCL_ABGAGT_CMD_FACTORY</CLSNAME>
7
+ <LANGU>E</LANGU>
8
+ <DESCRIPT>Command Factory for ABAP Git Agent</DESCRIPT>
9
+ <EXPOSURE>2</EXPOSURE>
10
+ <STATE>1</STATE>
11
+ <UNICODE>X</UNICODE>
12
+ </VSEOCLASS>
13
+ </asx:values>
14
+ </asx:abap>
15
+ </abapGit>
@@ -0,0 +1,192 @@
1
+ *"*"use source
2
+ *"*"Local Interface:
3
+ *"**********************************************************************
4
+ " INSPECT command implementation - uses SCI/SCIC for syntax check
5
+ CLASS zcl_abgagt_command_inspect DEFINITION PUBLIC FINAL CREATE PUBLIC.
6
+ PUBLIC SECTION.
7
+ INTERFACES zif_abgagt_command.
8
+
9
+ TYPES: BEGIN OF ty_error,
10
+ line TYPE string,
11
+ column TYPE string,
12
+ text TYPE string,
13
+ word TYPE string,
14
+ END OF ty_error.
15
+
16
+ TYPES ty_errors TYPE STANDARD TABLE OF ty_error WITH NON-UNIQUE DEFAULT KEY.
17
+
18
+ TYPES: BEGIN OF ty_inspect_result,
19
+ success TYPE abap_bool,
20
+ error_count TYPE i,
21
+ errors TYPE ty_errors,
22
+ END OF ty_inspect_result.
23
+
24
+ TYPES: BEGIN OF ty_inspect_params,
25
+ files TYPE string_table,
26
+ END OF ty_inspect_params.
27
+
28
+ TYPES ty_object_keys TYPE TABLE OF scir_objs WITH NON-UNIQUE DEFAULT KEY.
29
+
30
+ METHODS run_syntax_check
31
+ IMPORTING it_objects TYPE ty_object_keys
32
+ RETURNING VALUE(rs_result) TYPE ty_inspect_result.
33
+
34
+ ENDCLASS.
35
+
36
+ CLASS zcl_abgagt_command_inspect IMPLEMENTATION.
37
+
38
+ METHOD zif_abgagt_command~get_name.
39
+ rv_name = zif_abgagt_command=>gc_inspect.
40
+ ENDMETHOD.
41
+
42
+ METHOD zif_abgagt_command~execute.
43
+ DATA: ls_params TYPE ty_inspect_params,
44
+ lv_file TYPE string,
45
+ lv_obj_type TYPE string,
46
+ lv_obj_name TYPE string,
47
+ lo_util TYPE REF TO zcl_abgagt_util,
48
+ ls_result TYPE ty_inspect_result,
49
+ lt_objects TYPE ty_object_keys,
50
+ ls_obj TYPE scir_objs.
51
+
52
+ " Parse parameters from is_param
53
+ IF is_param IS SUPPLIED.
54
+ ls_params = CORRESPONDING #( is_param ).
55
+ ENDIF.
56
+
57
+ IF ls_params-files IS INITIAL.
58
+ ls_result-success = abap_false.
59
+ ls_result-error_count = 1.
60
+ rv_result = /ui2/cl_json=>serialize( data = ls_result ).
61
+ RETURN.
62
+ ENDIF.
63
+
64
+ " Parse all files to objects
65
+ lo_util = zcl_abgagt_util=>get_instance( ).
66
+
67
+ LOOP AT ls_params-files INTO lv_file.
68
+ CLEAR: lv_obj_type, lv_obj_name.
69
+ lo_util->zif_abgagt_util~parse_file_to_object(
70
+ EXPORTING iv_file = lv_file
71
+ IMPORTING ev_obj_type = lv_obj_type
72
+ ev_obj_name = lv_obj_name ).
73
+
74
+ IF lv_obj_type IS NOT INITIAL AND lv_obj_name IS NOT INITIAL.
75
+ CLEAR ls_obj.
76
+ ls_obj-objtype = lv_obj_type.
77
+ ls_obj-objname = lv_obj_name.
78
+ APPEND ls_obj TO lt_objects.
79
+ ENDIF.
80
+ ENDLOOP.
81
+
82
+ IF lt_objects IS INITIAL.
83
+ ls_result-success = abap_false.
84
+ ls_result-error_count = 1.
85
+ rv_result = /ui2/cl_json=>serialize( data = ls_result ).
86
+ RETURN.
87
+ ENDIF.
88
+
89
+ " Run syntax check for all objects together
90
+ ls_result = run_syntax_check( lt_objects ).
91
+
92
+ rv_result = /ui2/cl_json=>serialize( data = ls_result ).
93
+ ENDMETHOD.
94
+
95
+ METHOD run_syntax_check.
96
+ DATA: lv_name TYPE sci_objs,
97
+ lo_objset TYPE REF TO cl_ci_objectset,
98
+ lo_variant TYPE REF TO cl_ci_checkvariant,
99
+ lo_inspection TYPE REF TO cl_ci_inspection,
100
+ lt_list TYPE scit_alvlist,
101
+ ls_error TYPE ty_error,
102
+ lx_error TYPE REF TO cx_root.
103
+
104
+ rs_result-success = abap_true.
105
+
106
+ TRY.
107
+ " Create unique name for inspection
108
+ CONCATENATE 'SYNT_' sy-uname sy-datum sy-uzeit INTO lv_name.
109
+
110
+ " Create object set
111
+ lo_objset = cl_ci_objectset=>save_from_list(
112
+ p_name = lv_name
113
+ p_objects = it_objects ).
114
+
115
+ " Get check variant for syntax check
116
+ lo_variant = cl_ci_checkvariant=>get_ref(
117
+ p_user = ''
118
+ p_name = 'SYNTAX_CHECK' ).
119
+
120
+ " Create inspection
121
+ cl_ci_inspection=>create(
122
+ EXPORTING
123
+ p_user = sy-uname
124
+ p_name = lv_name
125
+ RECEIVING
126
+ p_ref = lo_inspection ).
127
+
128
+ " Set inspection with object set and variant
129
+ lo_inspection->set(
130
+ EXPORTING
131
+ p_chkv = lo_variant
132
+ p_objs = lo_objset ).
133
+
134
+ " Save inspection
135
+ lo_inspection->save( ).
136
+
137
+ " Run inspection
138
+ lo_inspection->run(
139
+ EXPORTING
140
+ p_howtorun = 'R'
141
+ EXCEPTIONS
142
+ invalid_check_version = 1
143
+ OTHERS = 2 ).
144
+
145
+ " Get results
146
+ lo_inspection->plain_list( IMPORTING p_list = lt_list ).
147
+
148
+ " Parse results - aggregate all errors
149
+ LOOP AT lt_list INTO DATA(ls_list).
150
+ CLEAR ls_error.
151
+ ls_error-line = ls_list-line.
152
+ ls_error-column = ls_list-col.
153
+ ls_error-text = ls_list-text.
154
+ ls_error-word = ls_list-code.
155
+ APPEND ls_error TO rs_result-errors.
156
+ ENDLOOP.
157
+
158
+ " Cleanup
159
+ lo_inspection->delete(
160
+ EXCEPTIONS
161
+ locked = 1
162
+ error_in_enqueue = 2
163
+ not_authorized = 3
164
+ exceptn_appl_exists = 4
165
+ OTHERS = 5 ).
166
+
167
+ lo_objset->delete(
168
+ EXCEPTIONS
169
+ exists_in_insp = 1
170
+ locked = 2
171
+ error_in_enqueue = 3
172
+ not_authorized = 4
173
+ exists_in_objs = 5
174
+ OTHERS = 6 ).
175
+
176
+ rs_result-error_count = lines( rs_result-errors ).
177
+ IF rs_result-error_count > 0.
178
+ rs_result-success = abap_false.
179
+ ENDIF.
180
+
181
+ CATCH cx_root INTO lx_error.
182
+ rs_result-success = abap_false.
183
+ rs_result-error_count = 1.
184
+ ls_error-line = '1'.
185
+ ls_error-column = '1'.
186
+ ls_error-text = lx_error->get_text( ).
187
+ ls_error-word = ''.
188
+ APPEND ls_error TO rs_result-errors.
189
+ ENDTRY.
190
+ ENDMETHOD.
191
+
192
+ ENDCLASS.
@@ -0,0 +1,121 @@
1
+ *"* use this source file for your test class implementation
2
+ *"* local test class
3
+ CLASS ltcl_cmd_inspect DEFINITION FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
4
+ PRIVATE SECTION.
5
+ DATA mo_cut TYPE REF TO zcl_abgagt_command_inspect.
6
+
7
+ METHODS setup.
8
+ METHODS test_get_name FOR TESTING.
9
+ METHODS test_interface FOR TESTING.
10
+ METHODS test_exec_no_files FOR TESTING.
11
+ METHODS test_exec_single_file FOR TESTING.
12
+ METHODS test_exec_multi_files FOR TESTING.
13
+ ENDCLASS.
14
+
15
+ CLASS ltcl_cmd_inspect IMPLEMENTATION.
16
+
17
+ METHOD setup.
18
+ CREATE OBJECT mo_cut.
19
+ ENDMETHOD.
20
+
21
+ METHOD test_get_name.
22
+ " Test that get_name returns the correct command name
23
+ DATA(lv_name) = mo_cut->zif_abgagt_command~get_name( ).
24
+ cl_abap_unit_assert=>assert_equals(
25
+ act = lv_name
26
+ exp = zif_abgagt_command=>gc_inspect
27
+ msg = 'Command name should be INSPECT' ).
28
+ ENDMETHOD.
29
+
30
+ METHOD test_interface.
31
+ " Test that the class implements the command interface
32
+ DATA lo_interface TYPE REF TO zif_abgagt_command.
33
+ CREATE OBJECT mo_cut TYPE zcl_abgagt_command_inspect.
34
+ lo_interface = mo_cut.
35
+ cl_abap_unit_assert=>assert_bound(
36
+ act = lo_interface
37
+ msg = 'Object should implement zif_abgagt_command interface' ).
38
+ ENDMETHOD.
39
+
40
+ METHOD test_exec_no_files.
41
+ " Test execute with no files - should return error
42
+ DATA: BEGIN OF ls_param,
43
+ files TYPE string_table,
44
+ END OF ls_param.
45
+
46
+ DATA(lv_result) = mo_cut->zif_abgagt_command~execute( is_param = ls_param ).
47
+
48
+ cl_abap_unit_assert=>assert_not_initial(
49
+ act = lv_result
50
+ msg = 'Result should not be initial' ).
51
+
52
+ " Result should be valid JSON (starts with { and ends with })
53
+ cl_abap_unit_assert=>assert_char_cp(
54
+ act = lv_result
55
+ exp = '*{*'
56
+ msg = 'Result should be valid JSON object' ).
57
+
58
+ " Result should contain ERROR_COUNT or error_count
59
+ cl_abap_unit_assert=>assert_char_cp(
60
+ act = lv_result
61
+ exp = '*ERROR_COUNT*'
62
+ msg = 'Result should contain error_count field' ).
63
+ ENDMETHOD.
64
+
65
+ METHOD test_exec_single_file.
66
+ " Test execute with a single file
67
+ DATA: BEGIN OF ls_param,
68
+ files TYPE string_table,
69
+ END OF ls_param.
70
+
71
+ APPEND 'zcl_my_class.clas.abap' TO ls_param-files.
72
+
73
+ DATA(lv_result) = mo_cut->zif_abgagt_command~execute( is_param = ls_param ).
74
+
75
+ cl_abap_unit_assert=>assert_not_initial(
76
+ act = lv_result
77
+ msg = 'Result should not be initial' ).
78
+
79
+ " Result should be valid JSON
80
+ cl_abap_unit_assert=>assert_char_cp(
81
+ act = lv_result
82
+ exp = '*{*'
83
+ msg = 'Result should be valid JSON object' ).
84
+
85
+ " Result should contain SUCCESS or success field
86
+ cl_abap_unit_assert=>assert_char_cp(
87
+ act = lv_result
88
+ exp = '*SUCCESS*'
89
+ msg = 'Result should contain success field' ).
90
+ ENDMETHOD.
91
+
92
+ METHOD test_exec_multi_files.
93
+ " Test execute with multiple files
94
+ DATA: BEGIN OF ls_param,
95
+ files TYPE string_table,
96
+ END OF ls_param.
97
+
98
+ APPEND 'zcl_my_class.clas.abap' TO ls_param-files.
99
+ APPEND 'zif_my_intf.intf.abap' TO ls_param-files.
100
+ APPEND 'zcl_another.clas.abap' TO ls_param-files.
101
+
102
+ DATA(lv_result) = mo_cut->zif_abgagt_command~execute( is_param = ls_param ).
103
+
104
+ cl_abap_unit_assert=>assert_not_initial(
105
+ act = lv_result
106
+ msg = 'Result should not be initial' ).
107
+
108
+ " Result should be valid JSON
109
+ cl_abap_unit_assert=>assert_char_cp(
110
+ act = lv_result
111
+ exp = '*{*'
112
+ msg = 'Result should be valid JSON object' ).
113
+
114
+ " Result should contain ERROR_COUNT or error_count
115
+ cl_abap_unit_assert=>assert_char_cp(
116
+ act = lv_result
117
+ exp = '*ERROR_COUNT*'
118
+ msg = 'Result should contain error_count field' ).
119
+ ENDMETHOD.
120
+
121
+ ENDCLASS.
@@ -0,0 +1,16 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
3
+ <asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
4
+ <asx:values>
5
+ <VSEOCLASS>
6
+ <CLSNAME>ZCL_ABGAGT_COMMAND_INSPECT</CLSNAME>
7
+ <LANGU>E</LANGU>
8
+ <DESCRIPT>Inspect Command for ABAP Git Agent</DESCRIPT>
9
+ <EXPOSURE>2</EXPOSURE>
10
+ <STATE>1</STATE>
11
+ <UNICODE>X</UNICODE>
12
+ <WITH_UNIT_TESTS>X</WITH_UNIT_TESTS>
13
+ </VSEOCLASS>
14
+ </asx:values>
15
+ </asx:abap>
16
+ </abapGit>
@@ -0,0 +1,80 @@
1
+ *"*"use source
2
+ *"*"Local Interface:
3
+ *"**********************************************************************
4
+ CLASS zcl_abgagt_command_pull DEFINITION PUBLIC FINAL CREATE PUBLIC.
5
+ PUBLIC SECTION.
6
+ INTERFACES zif_abgagt_command.
7
+
8
+ TYPES: BEGIN OF ty_pull_params,
9
+ url TYPE string,
10
+ branch TYPE string,
11
+ username TYPE string,
12
+ password TYPE string,
13
+ transport_request TYPE string,
14
+ files TYPE string_table,
15
+ END OF ty_pull_params.
16
+
17
+ ENDCLASS.
18
+
19
+ CLASS zcl_abgagt_command_pull IMPLEMENTATION.
20
+
21
+ METHOD zif_abgagt_command~get_name.
22
+ rv_name = zif_abgagt_command=>gc_pull.
23
+ ENDMETHOD.
24
+
25
+ METHOD zif_abgagt_command~execute.
26
+ DATA: ls_params TYPE ty_pull_params,
27
+ lo_agent TYPE REF TO zcl_abgagt_agent,
28
+ ls_pull_result TYPE zif_abgagt_agent=>ty_result,
29
+ lx_error TYPE REF TO zcx_abapgit_exception.
30
+
31
+ " Parse parameters from is_param
32
+ IF is_param IS SUPPLIED.
33
+ ls_params = CORRESPONDING #( is_param ).
34
+ ENDIF.
35
+
36
+ " Get agent instance and execute pull
37
+ lo_agent = NEW zcl_abgagt_agent( ).
38
+
39
+ TRY.
40
+ ls_pull_result = lo_agent->zif_abgagt_agent~pull(
41
+ iv_url = ls_params-url
42
+ iv_branch = ls_params-branch
43
+ iv_username = ls_params-username
44
+ iv_password = ls_params-password
45
+ iv_transport_request = ls_params-transport_request
46
+ it_files = ls_params-files ).
47
+ CATCH zcx_abapgit_exception INTO lx_error.
48
+ ls_pull_result-success = abap_false.
49
+ ls_pull_result-message = lx_error->get_text( ).
50
+ ENDTRY.
51
+
52
+ " Convert result to JSON string using /ui2/cl_json
53
+ DATA: BEGIN OF ls_response,
54
+ success TYPE string,
55
+ job_id TYPE string,
56
+ message TYPE string,
57
+ error_detail TYPE string,
58
+ transport_request TYPE string,
59
+ activated_count TYPE i,
60
+ failed_count TYPE i,
61
+ log_messages TYPE zif_abgagt_agent=>ty_object_list,
62
+ activated_objects TYPE zif_abgagt_agent=>ty_object_list,
63
+ failed_objects TYPE zif_abgagt_agent=>ty_object_list,
64
+ END OF ls_response.
65
+
66
+ ls_response-success = COND string( WHEN ls_pull_result-success = abap_true THEN 'X' ELSE '' ).
67
+ ls_response-job_id = ls_pull_result-job_id.
68
+ ls_response-message = ls_pull_result-message.
69
+ ls_response-error_detail = ls_pull_result-error_detail.
70
+ ls_response-transport_request = ls_pull_result-transport_request.
71
+ ls_response-activated_count = ls_pull_result-activated_count.
72
+ ls_response-failed_count = ls_pull_result-failed_count.
73
+ ls_response-log_messages = ls_pull_result-log_messages.
74
+ ls_response-activated_objects = ls_pull_result-activated_objects.
75
+ ls_response-failed_objects = ls_pull_result-failed_objects.
76
+
77
+ rv_result = /ui2/cl_json=>serialize( data = ls_response ).
78
+ ENDMETHOD.
79
+
80
+ ENDCLASS.
@@ -0,0 +1,87 @@
1
+ *"* use this source file for your test class implementation
2
+ *"* local test class
3
+ CLASS ltcl_zcl_abgagt_command_pull DEFINITION FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
4
+ PRIVATE SECTION.
5
+ DATA mo_cut TYPE REF TO zcl_abgagt_command_pull.
6
+
7
+ METHODS setup.
8
+ METHODS test_get_name FOR TESTING.
9
+ METHODS test_exec_minimal FOR TESTING.
10
+ METHODS test_exec_files FOR TESTING.
11
+ METHODS test_interface FOR TESTING.
12
+ ENDCLASS.
13
+
14
+ CLASS ltcl_zcl_abgagt_command_pull IMPLEMENTATION.
15
+
16
+ METHOD setup.
17
+ CREATE OBJECT mo_cut.
18
+ ENDMETHOD.
19
+
20
+ METHOD test_get_name.
21
+ " Test that get_name returns the correct command name
22
+ DATA(lv_name) = mo_cut->zif_abgagt_command~get_name( ).
23
+ cl_abap_unit_assert=>assert_equals(
24
+ act = lv_name
25
+ exp = zif_abgagt_command=>gc_pull
26
+ msg = 'Command name should be PULL' ).
27
+ ENDMETHOD.
28
+
29
+ METHOD test_interface.
30
+ " Test that the class implements the command interface
31
+ DATA lo_interface TYPE REF TO zif_abgagt_command.
32
+ CREATE OBJECT mo_cut TYPE zcl_abgagt_command_pull.
33
+ lo_interface = mo_cut.
34
+ cl_abap_unit_assert=>assert_bound(
35
+ act = lo_interface
36
+ msg = 'Object should implement zif_abgagt_command interface' ).
37
+ ENDMETHOD.
38
+
39
+ METHOD test_exec_minimal.
40
+ " Test execute with minimal parameters (url only)
41
+ DATA: BEGIN OF ls_param,
42
+ url TYPE string,
43
+ END OF ls_param.
44
+
45
+ ls_param-url = 'https://github.test/repo.git'.
46
+
47
+ " Execute should return a JSON string
48
+ DATA(lv_result) = mo_cut->zif_abgagt_command~execute( is_param = ls_param ).
49
+
50
+ cl_abap_unit_assert=>assert_not_initial(
51
+ act = lv_result
52
+ msg = 'Result should not be initial' ).
53
+
54
+ " Result should be valid JSON (starts with { and ends with })
55
+ cl_abap_unit_assert=>assert_char_cp(
56
+ act = lv_result
57
+ exp = '*{*'
58
+ msg = 'Result should be valid JSON object' ).
59
+ ENDMETHOD.
60
+
61
+ METHOD test_exec_files.
62
+ " Test execute with files parameter
63
+ DATA: BEGIN OF ls_param,
64
+ url TYPE string,
65
+ files TYPE string_table,
66
+ END OF ls_param.
67
+
68
+ ls_param-url = 'https://github.test/repo.git'.
69
+ APPEND 'zcl_test.clas.abap' TO ls_param-files.
70
+ APPEND 'zif_test.intf.abap' TO ls_param-files.
71
+
72
+ DATA(lv_result) = mo_cut->zif_abgagt_command~execute( is_param = ls_param ).
73
+
74
+ cl_abap_unit_assert=>assert_not_initial(
75
+ act = lv_result
76
+ msg = 'Result should not be initial' ).
77
+
78
+ " Result should be valid JSON
79
+ DATA lv_json TYPE string.
80
+ lv_json = lv_result.
81
+ cl_abap_unit_assert=>assert_char_cp(
82
+ act = lv_json
83
+ exp = '*{"success"*' " JSON-like structure
84
+ msg = 'Result should be valid JSON' ).
85
+ ENDMETHOD.
86
+
87
+ ENDCLASS.
@@ -0,0 +1,16 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
3
+ <asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
4
+ <asx:values>
5
+ <VSEOCLASS>
6
+ <CLSNAME>ZCL_ABGAGT_COMMAND_PULL</CLSNAME>
7
+ <LANGU>E</LANGU>
8
+ <DESCRIPT>Pull Command for ABAP Git Agent</DESCRIPT>
9
+ <EXPOSURE>2</EXPOSURE>
10
+ <STATE>1</STATE>
11
+ <UNICODE>X</UNICODE>
12
+ <WITH_UNIT_TESTS>X</WITH_UNIT_TESTS>
13
+ </VSEOCLASS>
14
+ </asx:values>
15
+ </asx:abap>
16
+ </abapGit>