Being at QA person on the project is not only checking developments done. The main question is always how safe to transport certain transport requests (usually a bundle) to a certain system and ensure there are no collisions. The task is usually to check each object from a bundle and check its versions. Task is becoming more complex when there could be collisions between partial objects, for example somebody transporting entire class but there are changes for certain methods or sections only. All of those could lead to wrong queue and differences of the object versions through the landscape. That is why there was an idea to automate this check and below is how it was build. The expected result a report receiving a list of transport requests and a target system at start.
At the first step, we would need to build a list of objects to check from the list provided. The easiest way to read it directly from E071 table and remove duplicates. Then we would check each request for each object for collisions. In order to ensure transport consistency before the system specified I decided to add each system check. To do so we would need to read target system of each TR we are checking and get it's configuration with function TR_GET_LIST_OF_TARGETS. Target system of request and its last change time could be found in E070 table.
Next step is to read object versions. After a little debugging, table VRSD has been discovered. The goal is to find the previous version transport request and ensure it has been transported to target system. This could be done simply by reading a version with a time and date lower that release time of current request we are checking. Therefore, after obtaining of TR we would need to read its transport history. I found that function STRF_READ_COFILE fits well for that. Function returns all actions performed with TR in each system. I guess function = "I" (import) as fact of request import. Report will check each TR like this, it should be transported or to be in a current bundle to avoid errors.
However, this is unfortunately not the only check to be done. We need to ensure that newer versions of objects have not transported yet to avoid overwriting by older ones. Actually, we already got everything to do it. Just check the history of TRs with higher version if its transported or not. If it is, the error should be shown.
The final question is how to handle partial objects. I attempted to do it via function TRINT_GET_PART_OBJECTS call to partial components of each object report checking. The idea is simply to check all this function returns or if it returns nothing to check the initial object itself.
Here is a report listing. Maybe it will be helpful.
report bundle_test.
tables: e070, vrsd.
**********************************
* use only in DEVELOPMENT system *
**********************************
selection-screen begin of block main with frame title text-t00.
select-options s_trkorr for e070-trkorr.
parameters p_target type sy-sysid obligatory.
parameters p_fnc like tstrfcofil-function default 'I' modif id 100.
selection-screen end of block main.
at selection-screen output.
loop at screen.
check screen-group1 = 100.
screen-input = 0.
modify screen.
endloop.
start-of-selection.
types: begin of ts_obj
, pgmid type e071-pgmid
, object type e071-object
, obj_name type e071-obj_name
, end of ts_obj.
types: begin of ts_cons
, tr_target type sysname
, targets type trsysclis
, end of ts_cons
.
data: lt_list type table of e071
, lt_objs type table of ts_obj
, lt_vers type table of vrsd
, ls_e070 type e070 " request of the particular object
, lt_e070 type table of e070
, lt_cons type hashed table of ts_cons with unique key tr_target
, lt_cofi type tr_cofilines
, lt_part type trwb1_t_object
, lv_err type abap_bool
.
" get obj list
select trkorr pgmid object obj_name
from e071
into corresponding fields of table lt_list
where trkorr in s_trkorr.
if sy-subrc ne 0.
message s001(00) with 'Nothing found.' display like 'E'.
stop.
endif.
lt_objs = value #( for <ob> in lt_list ( pgmid = <ob>-pgmid
object = <ob>-object
obj_name = <ob>-obj_name ) ).
sort lt_objs. delete adjacent duplicates from lt_objs comparing all fields.
sort lt_list by pgmid object obj_name trkorr.
data(lv_total) = lines( lt_objs ).
loop at lt_objs assigning field-symbol(<obj>).
call function 'PROGRESS_INDICATOR'
exporting
i_msgid = 'ZBC'
i_msgno = '000'
i_msgv1 = <obj>-pgmid
i_msgv2 = <obj>-object
i_msgv3 = <obj>-obj_name
i_processed = sy-tabix
i_total = lv_total.
" are there object parts?
refresh lt_part.
call function 'TRINT_GET_PART_OBJECTS'
exporting
iv_hpgmid = <obj>-pgmid
iv_hobject = <obj>-object
iv_hobjname = <obj>-obj_name
iv_hobjname_as_structure = abap_false
tables
et_part_objects = lt_part
exceptions
no_part_objects_possible = 1
syntax_table_entry_without_len = 2
header_object_name_too_short = 3
header_object_name_too_long = 4
hobjname_parameter_wrong = 5.
if sy-subrc ne 0.
insert value #( pgmid = <obj>-pgmid
object = <obj>-object
obj_struct = value #( ( substtype = 'CON'
value = <obj>-obj_name ) ) ) into table lt_part.
endif.
" check request by request for mentioned object
clear lv_err.
write: / 'Checking object', <obj>-pgmid, <obj>-object, <obj>-obj_name.
loop at lt_list assigning field-symbol(<list>) where pgmid = <obj>-pgmid
and object = <obj>-object
and obj_name = <obj>-obj_name.
" get the request of the particular object
select single * from e070 into ls_e070 where trkorr = <list>-trkorr.
check sy-subrc eq 0.
" read tms configuration
read table lt_cons assigning field-symbol(<tms>) with key tr_target = ls_e070-tarsystem.
if sy-subrc ne 0.
insert value #( tr_target = ls_e070-tarsystem ) into table lt_cons assigning <tms>.
call function 'TR_GET_LIST_OF_TARGETS'
exporting
iv_cons_target = ls_e070-tarsystem
importing
et_targets = <tms>-targets
exceptions
tce_config_error = 1.
endif.
" process all the partial objects
loop at lt_part assigning field-symbol(<part>).
loop at <part>-obj_struct assigning field-symbol(<str>) where substtype = 'CON'.
" read versions of the object
refresh lt_vers.
select * from vrsd
into table lt_vers
where objtype = <part>-object
and objname = <str>-value.
check sy-subrc eq 0.
sort lt_vers by datum descending zeit descending.
" get previous version
data lv_prev_version type sy-tabix. clear lv_prev_version.
loop at lt_vers assigning field-symbol(<prev_vers>) where korrnum ne ls_e070-trkorr
and korrnum is not initial
and ( datum lt ls_e070-as4date or
datum eq ls_e070-as4date and
zeit lt ls_e070-as4time ).
lv_prev_version = sy-tabix.
" read request log
refresh lt_cofi.
call function 'STRF_READ_COFILE'
exporting
iv_trkorr = <prev_vers>-korrnum
tables
tt_cofi_lines = lt_cofi
exceptions
wrong_call = 1
no_info_found = 2
others = 3.
if sy-subrc ne 0.
write: / icon_yellow_light as icon, 'cant get history for the predecessor', <prev_vers>-korrnum.
lv_err = abap_undefined.
else.
" check all the systems until requested
loop at <tms>-targets assigning field-symbol(<target>).
loop at lt_cofi assigning field-symbol(<cofi>) where tarsystem = <target>-sysname
and tarclient = <target>-client
and function = p_fnc.
exit.
endloop.
if sy-subrc ne 0.
" ok not imported yet, but may be in current bundle?
read table lt_list transporting no fields with key trkorr = <prev_vers>-korrnum.
if sy-subrc ne 0.
write: / icon_red_light as icon, 'predecessor', <prev_vers>-korrnum, 'hasnt been imported into', <target>-sysname.
lv_err = abap_true.
endif.
endif.
if <target>-sysname = p_target.
exit.
endif.
endloop.
endif.
exit.
endloop.
" now check if successors are transported
if lv_err is initial.
loop at lt_vers assigning field-symbol(<next_vers>) from 1 to ( lv_prev_version - 1 ).
" if it's in bundle - then on
read table lt_list transporting no fields with key trkorr = <next_vers>-korrnum.
check sy-subrc ne 0.
" read request log
refresh lt_cofi.
call function 'STRF_READ_COFILE'
exporting
iv_trkorr = <next_vers>-korrnum
tables
tt_cofi_lines = lt_cofi
exceptions
wrong_call = 1
no_info_found = 2
others = 3.
if sy-subrc ne 0. " no logs -> good, not transported yet
else.
loop at <tms>-targets assigning <target>.
loop at lt_cofi assigning <cofi> where tarsystem = <target>-sysname
and tarclient = <target>-client
and function = p_fnc.
exit.
endloop.
if sy-subrc eq 0.
" newer version already transported!!!
write: / icon_red_light as icon, 'successor', <next_vers>-korrnum, 'has been already imported into', <target>-sysname.
lv_err = abap_true.
endif.
if <target>-sysname = p_target.
exit.
endif.
endloop.
endif.
endloop.
endif.
endloop.
endloop.
endloop.
if lv_err eq abap_false.
write: / icon_green_light as icon, 'seems to be ok'.
endif.
write: / sy-uline.
endloop.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
8 | |
8 | |
7 | |
6 | |
5 | |
4 | |
4 | |
4 | |
3 | |
3 |