Skip to content

Commit 6fe9bc8

Browse files
first commit
0 parents  commit 6fe9bc8

File tree

8 files changed

+352
-0
lines changed

8 files changed

+352
-0
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* simone.gaffurini@regestaitalia.it

.github/workflows/abapUnitTests.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: ABAP Unit tests (ADASH)
2+
on:
3+
push:
4+
branches-ignore:
5+
- 'main'
6+
jobs:
7+
runUnitTests:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- uses: actions/checkout@v4
11+
- uses: dorny/paths-filter@v2
12+
id: changes
13+
with:
14+
filters: |
15+
src:
16+
- 'src/**'
17+
- name: Install ADASH
18+
if: ${{ steps.changes.outputs.src == 'true' }}
19+
run: npm install adash-cli -g
20+
- name: Get system address
21+
if: ${{ steps.changes.outputs.src == 'true' }}
22+
id: getSystemAddress
23+
uses: simonegaffurini/nuveplatform-get-instance@main
24+
with:
25+
email: ${{ secrets.NUVE_EMAIL }}
26+
password: ${{ secrets.NUVE_PASSWORD }}
27+
instanceName: ${{ vars.NUVE_INSTANCE_NAME }}
28+
- name: Run ABAP Unit tests
29+
if: ${{ steps.changes.outputs.src == 'true' }}
30+
run: adash testp ${{ vars.DEVCLASS }} -u ${{ secrets.A4H_USER }} -p ${{ secrets.A4H_PASSWORD }} -h ${{ steps.getSystemAddress.outputs.webDomain }} -c 001 -i
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: Create TRM release
2+
on:
3+
release:
4+
types: [published]
5+
jobs:
6+
createTrmRelease:
7+
runs-on: [self-hosted, Windows, RegRunner]
8+
steps:
9+
- name: Checkout
10+
uses: actions/checkout@v4
11+
- name: Get system address
12+
id: getSystemAddress
13+
uses: simonegaffurini/nuveplatform-get-instance@main
14+
with:
15+
email: ${{ secrets.NUVE_EMAIL }}
16+
password: ${{ secrets.NUVE_PASSWORD }}
17+
instanceName: ${{ vars.NUVE_INSTANCE_NAME }}
18+
- name: TRM Publish
19+
uses: RegestaItalia/trm-action-publish@2.1.3
20+
with:
21+
dest: A4H
22+
systemAsHost: ${{ steps.getSystemAddress.outputs.externalIp }}
23+
systemSysnr: '00'
24+
systemClient: '001'
25+
systemUser: ${{ secrets.A4H_USER }}
26+
systemPassword: ${{ secrets.A4H_PASSWORD }}
27+
systemLang: EN
28+
devclass: ${{ vars.DEVCLASS }}
29+
target: TRM
30+
registryAuth: ${{ secrets.TRM_REGISTRY_AUTH }}
31+
packageName: abapcicd
32+
description: Example of ABAP CI/CD on S4/ECC
33+
private: false
34+
git: https://github.com/RegestaItalia/abapcicd.git
35+
website: https://www.trmregistry.com/
36+
license: MIT
37+
authors: Simone Gaffurini <gaffu@trmregistry.com>
38+
keywords: example, cicd
39+
readme: /README.md
40+
- name: Stop SAP instance
41+
uses: simonegaffurini/nuveplatform-stop-instance@main
42+
with:
43+
email: ${{ secrets.NUVE_EMAIL }}
44+
password: ${{ secrets.NUVE_PASSWORD }}
45+
instanceName: ${{ vars.NUVE_INSTANCE_NAME }}
46+
runDistributeReleaseWkf:
47+
name: Run distribute release workflow
48+
needs: [createTrmRelease]
49+
uses: ./.github/workflows/distributeTrmRelease.yml
50+
with:
51+
packageVersion: ${{ github.event.release.tag_name }}
52+
secrets: inherit
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Distribute TRM release
2+
on:
3+
workflow_call:
4+
inputs:
5+
packageVersion:
6+
required: true
7+
type: string
8+
jobs:
9+
installTrmRelease:
10+
runs-on: [self-hosted, Windows, RegRunner]
11+
steps:
12+
- name: Start new instance
13+
id: targetInstance
14+
uses: simonegaffurini/nuveplatform-start-backup@main
15+
with:
16+
email: ${{ secrets.NUVE_EMAIL }}
17+
password: ${{ secrets.NUVE_PASSWORD }}
18+
backup: ${{ vars.NUVE_NEW_INSTANCE_BACKUP_NAME }}
19+
instanceName: ${{ vars.NUVE_NEW_INSTANCE_NAME }}
20+
instanceProject: trm-samples
21+
- name: TRM Install
22+
uses: RegestaItalia/trm-action-install@2.0.1
23+
with:
24+
dest: A4H
25+
systemAsHost: ${{ steps.targetInstance.outputs.externalIp }}
26+
systemSysnr: '00'
27+
systemClient: '001'
28+
systemUser: ${{ secrets.A4H_USER }}
29+
systemPassword: ${{ secrets.A4H_PASSWORD }}
30+
systemLang: EN
31+
packageName: abapcicd
32+
packageVersion: ${{ inputs.packageVersion }}
33+
registryAuth: ${{ secrets.TRM_REGISTRY_AUTH }}
34+
- name: Stop SAP instance
35+
uses: simonegaffurini/nuveplatform-stop-instance@main
36+
with:
37+
email: ${{ secrets.NUVE_EMAIL }}
38+
password: ${{ secrets.NUVE_PASSWORD }}
39+
instanceName: ${{ vars.NUVE_NEW_INSTANCE_NAME }}

README.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# ABAP CI/CD
2+
3+
This repository contains an example of how a CI/CD approach can be achieved with an ABAP S4/ECC project.
4+
5+
# Tools used
6+
7+
- [abapGit](https://abapgit.org/): Serializing objects and having a git approach for ABAP developments
8+
- [abapLint](https://abaplint.org/): Syntax check based on a defined rule set
9+
- [ADASH](https://github.com/xinitrc86/adash-cli): Run ABAP unit tests
10+
- [TRM](https://trmregistry.com): Publish and distribute software ready for production environments
11+
12+
## SAP System
13+
14+
The source and target SAP systems are instances of ABAP Platform 1909 provided by [Nuve Platform](https://nuveplatform.com).
15+
16+
The source instance is where all the code changes are performed and committed to this repository; it's also where the TRM release will be generated.
17+
18+
When ready to distribute, a new ABAP Platform 1909 instance is generated but this time from a blank backup (a snapshot where this example package was never installed): this will simulate the first install of a TRM package.
19+
20+
# Branching strategy
21+
22+
The branching strategy of this repository is [trunk-based](https://trunkbaseddevelopment.com/):
23+
24+
the **main** branch is protected, only allowing merge from pull requests.
25+
26+
# Tests
27+
28+
Merges to main are prevented (by pull request rules) if something wrong with the tests is detected.
29+
30+
## abapLint
31+
32+
abapLint will check for syntax errors on each commit.
33+
34+
## ABAP Unit tests
35+
36+
Each commit to any branch other than main will trigger a workflow that checks all of the unit tests in the package (using ADASH).
37+
38+
# Release
39+
40+
Releases are generated with [Github Releases](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository#creating-a-release).
41+
42+
## TRM Release
43+
44+
When a Github Release is created, the TRM publish workflow will trigger.
45+
46+
# Distribute
47+
48+
As soon as the TRM release is completed, the TRM install workflow is triggered.
49+
50+
# Workflow
51+
52+
<p align="center">
53+
  <img src="/media/workflow.jpg" />
54+
</p>
55+
56+
Steps:
57+
58+
- All code is written in a central development system
59+
- Commits are done in a new branch
60+
- Trigger abapLint syntax check
61+
- Trigger ABAP Unit tests (ADASH executed on central development system)
62+
- When ready, pull request from branch -> main
63+
- If all checks ok, merge
64+
- When ready, manually create a new Github release
65+
- Trigger TRM Publish (from central development system)
66+
- TRM Release published
67+
- Trigger TRM Install (in this case, run and install on a new instance of ABAP Platform 1909 on Nuve Platform)

abaplint-app.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"noArtifactsOkay": true
3+
}

abaplint.json

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
{
2+
"global": {
3+
"files": "/src/**/*.*",
4+
"skipGeneratedGatewayClasses": true,
5+
"skipGeneratedPersistentClasses": true,
6+
"skipGeneratedFunctionGroups": true
7+
},
8+
"syntax": {
9+
"version": "v702",
10+
"errorNamespace": "",
11+
"globalConstants": [],
12+
"globalMacros": []
13+
},
14+
"rules": {
15+
"avoid_use": {
16+
"define": true,
17+
"endselect": true,
18+
"execSQL": true,
19+
"kernelCall": true,
20+
"communication": true,
21+
"statics": true,
22+
"systemCall": true,
23+
"break": true,
24+
"defaultKey": true
25+
},
26+
"commented_code": true,
27+
"constructor_visibility_public": true,
28+
"description_empty": true,
29+
"empty_statement": true,
30+
"empty_structure": {
31+
"loop": true,
32+
"if": true,
33+
"while": true,
34+
"case": true,
35+
"select": true,
36+
"do": true,
37+
"at": true,
38+
"try": true
39+
},
40+
"exporting": true,
41+
"functional_writing": {
42+
"ignoreExceptions": true
43+
},
44+
"identical_form_names": true,
45+
"if_in_if": true,
46+
"inline_data_old_versions": true,
47+
"line_length": {
48+
"length": 120
49+
},
50+
"max_one_statement": true,
51+
"message_exists": true,
52+
"method_length": {
53+
"statements": 25,
54+
"ignoreTestClasses": false,
55+
"errorWhenEmpty": false
56+
},
57+
"mix_returning": true,
58+
"msag_consistency": true,
59+
"nesting": {
60+
"depth": 5
61+
},
62+
"obsolete_statement": {
63+
"refresh": true,
64+
"compute": true,
65+
"add": true,
66+
"subtract": true,
67+
"multiply": true,
68+
"move": true,
69+
"divide": true,
70+
"requested": true,
71+
"occurs": true,
72+
"setExtended": true,
73+
"withHeaderLine": true,
74+
"fieldSymbolStructure": true
75+
},
76+
"parser_error": true,
77+
"preferred_compare_operator": {
78+
"badOperators": [
79+
"EQ",
80+
"NE",
81+
"GE",
82+
"GT",
83+
"LT",
84+
"LE"
85+
]
86+
},
87+
"short_case": {
88+
"length": 1,
89+
"allow": []
90+
},
91+
"superclass_final": true,
92+
"unreachable_code": true,
93+
"use_new": true,
94+
"when_others_last": true,
95+
"ambiguous_statement": true,
96+
"begin_end_names": true,
97+
"check_transformation_exists": true,
98+
"form_tables_obsolete": true,
99+
"tabl_enhancement_category": true,
100+
"implement_methods": true,
101+
"local_testclass_location": true,
102+
"space_before_dot": true,
103+
"rfc_error_handling": true,
104+
"indentation": {
105+
"alignTryCatch": false,
106+
"ignoreExceptions": false,
107+
"globalClassSkipFirst": false,
108+
"ignoreGlobalClassDefinition": false,
109+
"ignoreGlobalInterface": false
110+
},
111+
"sequential_blank": {
112+
"lines": 4
113+
},
114+
"empty_line_in_statement": {
115+
"allowChained": true
116+
},
117+
"check_abstract": true,
118+
"no_public_attributes": {
119+
"allowReadOnly": true
120+
},
121+
"prefer_returning_to_exporting": true,
122+
"keep_single_parameter_on_one_line": {
123+
"length": 120
124+
},
125+
"allowed_object_naming": true,
126+
"fully_type_constants": true,
127+
"check_comments": {
128+
"allowEndOfLine": true
129+
},
130+
"check_text_elements": true,
131+
"newline_between_methods": {
132+
"logic": "less",
133+
"count": 3
134+
},
135+
"check_include": true,
136+
"xml_consistency": true,
137+
"prefix_is_current_class": {
138+
"omitMeInstanceCalls": true
139+
},
140+
"check_no_handler_pragma": true,
141+
"line_break_multiple_parameters": true,
142+
"prefer_inline": true,
143+
"reduce_string_templates": true,
144+
"sicf_consistency": true,
145+
"sql_escape_host_variables": true,
146+
"try_without_catch": true,
147+
"names_no_dash": true,
148+
"unused_variables": true,
149+
"unused_types": true,
150+
"use_bool_expression": true,
151+
"use_line_exists": true,
152+
"check_subrc": true,
153+
"cyclomatic_complexity": {
154+
"max": 6
155+
},
156+
"parser_missing_space": true,
157+
"identical_conditions": true,
158+
"prefer_is_not": true
159+
}
160+
}

media/workflow.jpg

61.2 KB
Loading

0 commit comments

Comments
 (0)