Differences
This shows you the differences between two versions of the page.
ibm_i_and_continuous_integration [2017/03/18 11:15] |
ibm_i_and_continuous_integration [2021/04/05 11:23] (current) |
||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== IBM i and Continuous Integeration ====== | ||
+ | |||
+ | ===== What is Continuous Integration ? ===== | ||
+ | I won't go into details here what Continuous Integration (CI) is because there are many people who can do that better than me. So [[https:// | ||
+ | |||
+ | ==== Why CI even if you are a single developer in your shop?==== | ||
+ | |||
+ | Having a build server can be handy for many reasons: | ||
+ | |||
+ | * Build server can be setup to have the same environment as the production environment. The development environment often differs from the production environment. | ||
+ | * Every build is done in exactly the same way. | ||
+ | * Builds can be triggered regardless of the developer machine. | ||
+ | * Release builds | ||
+ | * ... and there are many many more | ||
+ | |||
+ | Here some quotes from the net: | ||
+ | |||
+ | < | ||
+ | The CI build can also be thought of as your " | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | Likewise, if you are building libs that are used by multiple projects then CI will make sure they work with ALL of the projects rather than just the one that you're working with right now... | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | ===== Build Server ===== | ||
+ | Jenkins is used as a build and CI server. It supports master and slave nodes. | ||
+ | |||
+ | If Jenkins is run on the system where all the builds should be executed it can be run as a master which is also the default. | ||
+ | |||
+ | If Jenkins is run on another platform and builds should be executed on an IBM i server Jenkins can be normally run as master node and slaves nodes need to be configured so that builds can be delegated to slave nodes. | ||
+ | |||
+ | |||
+ | ==== Installation ==== | ||
+ | Jenkins can be downloaded [[http:// | ||
+ | |||
+ | The installation is pretty straight forward. Jenkins is packaged as a war file but also supports executing the file as a normal Java application. It needs at least a Java Runtime Environment 1.7. You can check this with | ||
+ | |||
+ | java -jar version | ||
+ | |||
+ | It should output something like this: | ||
+ | |||
+ | java version " | ||
+ | OpenJDK Runtime Environment (IcedTea 2.6.8) (7u121-2.6.8-2~deb7u1) | ||
+ | OpenJDK 64-Bit Server VM (build 24.121-b00, mixed mode) | ||
+ | |||
+ | Jenkins can be started with | ||
+ | |||
+ | java -jar jenkins.war | ||
+ | |||
+ | The Jenkins project has an extensive documentation. The wiki provides a page [[https:// | ||
+ | found in the project [[https:// | ||
+ | |||
+ | All the data will be stored in the '' | ||
+ | |||
+ | === Jenkins and Screen === | ||
+ | screen is a handy tool on linux systems to run programs interactively but in the background. | ||
+ | |||
+ | screen -dmS jenkins bash -c "java -jar / | ||
+ | |||
+ | To detach from a screen session enter '' | ||
+ | |||
+ | '' | ||
+ | |||
+ | To attach to a running screen session enter | ||
+ | |||
+ | screen -r jenkins | ||
+ | |||
+ | |||
+ | ==== Configuration ==== | ||
+ | In most cases the build server runs on a dedicated machine (either real or virtual). To execute compiles on architectures other than the one where the build server is running the concept of master and slave nodes needs to be installed. | ||
+ | |||
+ | The normal installation is always acting like a master node. | ||
+ | |||
+ | See [[https:// | ||
+ | |||
+ | To communicate with the slave node system the SSH Jenkins plugin needs to be installed, see Main Page ⇒ Manage Jenkins ⇒ Manage Plugins. | ||
+ | |||
+ | === Slave Node === | ||
+ | We need to configure a slave node for the IBM i server so that we can compile and test ILE code, like RPG and CL. | ||
+ | |||
+ | Slave nodes can be configured in Jenkins in the Main Menu ⇒ Manage Jenkins ⇒ Manage Nodes ⇒ New Node , select " | ||
+ | |||
+ | As there need to be some files and programs on the slave node to execute the build job we need to create a directory in the IFS, f. e. ''/ | ||
+ | |||
+ | Set " | ||
+ | |||
+ | Set the labels to use in the job configuration, | ||
+ | |||
+ | < | ||
+ | |||
+ | === Job === | ||
+ | A Build Job defines what is build where and when. It defines the build environment. | ||
+ | |||
+ | Build Jobs can be configured in Jenkins in the Main Menu ⇒ New Item. Configure the job as a " | ||
+ | |||
+ | The label determines where the job is run. This can be set on the "// | ||
+ | |||
+ | |||
+ | == Build Steps == | ||
+ | git clone git@bitbucket.org: | ||
+ | | ||
+ | cd $WORKSPACE | ||
+ | $WORKSPACE/ | ||
+ | |||
+ | The source code is fetched from a git repository and the compile commands are in the '' | ||
+ | |||
+ | < | ||
+ | |||
+ | To make the setup script more flexible you can specify the target library via an environment variable. Install the EnvInject plugin for that and configure '' | ||
+ | |||
+ | {{: | ||
+ | |||
+ | |||
+ | == Example Setup Script == | ||
+ | <sxh> | ||
+ | # | ||
+ | export PWD=$(pwd) | ||
+ | |||
+ | if [ -e / | ||
+ | system -kpieb " | ||
+ | fi | ||
+ | system -kpieb " | ||
+ | system -kpieb " | ||
+ | |||
+ | if [ -e / | ||
+ | system -kpieb " | ||
+ | fi | ||
+ | if [ -e / | ||
+ | system -kpieb " | ||
+ | fi | ||
+ | |||
+ | system -kpieb " | ||
+ | system -kpieb " | ||
+ | |||
+ | if [ -e / | ||
+ | system -kpieb " | ||
+ | fi | ||
+ | system -kpieb " | ||
+ | |||
+ | # cleanup | ||
+ | system -kpieb " | ||
+ | system -kpieb " | ||
+ | system -kpieb " | ||
+ | |||
+ | if [ ! -e / | ||
+ | exit 1 | ||
+ | fi | ||
+ | </ | ||
+ | |||
+ | |||
+ | == Tagging Build Objects == | ||
+ | To identify from which source code revision the objects has been build we need to tag the objects with an identifier. The identifier could be the source code revision which can be retrieved from a git repository with the following line | ||
+ | |||
+ | git show -s --format=%h | ||
+ | |||
+ | Output: '' | ||
+ | |||
+ | To make sure that we only get the first 7 characters regardless of the output of the git command we can pipe the output to the '' | ||
+ | |||
+ | git show -s --format=%h | head -c 7 | ||
+ | |||
+ | QSYS objects can only store user information in two attributes: | ||
+ | |||
+ | * object description | ||
+ | * user-defined attribute | ||
+ | |||
+ | We will use the user-defined attribute though it can only hold 10 characters of information. | ||
+ | |||
+ | The program // | ||
+ | |||
+ | * library name of the object | ||
+ | * object name | ||
+ | * object type (f. e. *PGM) | ||
+ | * tag / user defined information (max. 10 characters) | ||
+ | |||
+ | CALL UPDUSRATTR PARM(' | ||
+ | |||
+ | In the '' | ||
+ | |||
+ | GIT_COMMIT_HASH=GIT$(git show -s --format=%h | head -c 7) | ||
+ | system -kpieb "CALL MSCHMIDT1/ | ||
+ | |||
+ | |||
+ | == Unit Testing == | ||
+ | I used ILEUnit for unit testing builds. There is also the RPGUnit framework but that doesn' | ||
+ | |||
+ | The unit tests are service programs which must be build like the rest. There is a '' | ||
+ | |||
+ | cd $WORKSPACE/ | ||
+ | $WORKSPACE/ | ||
+ | |||
+ | The execution of the unit test is also covered in the '' | ||
+ | |||
+ | system -kpieb " | ||
+ | if [ ! -e $WORKSPACE/ | ||
+ | exit 1 | ||
+ | fi | ||
+ | |||
+ | <note important> | ||
+ | |||
+ | |||
+ | == Create Unit Test Report == | ||
+ | In the previous step we run the unit test and create the xml stream files in the '' | ||
+ | |||
+ | Now we need to say Jenkins where to find the files. | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | |||
+ | == Open Tasks == | ||
+ | Jenkins provides a rich set of plugins. One of those plugins is the [[https:// | ||
+ | |||
+ | First we need to configure the keywords and the files to be scanned (in this case TODO and FIX ME as keywords and all files with the suffix //rpgle//). | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | The result of the scan looks like this: | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | |||
+ | == Lint == | ||
+ | In almost any programming languages exists a lint module which does some generic code checking. Of course there is no such thing for RPG but one could do some checking with a simple text search using regex. | ||
+ | |||
+ | An example would be if there shouldn' | ||
+ | |||
+ | .*[dD][sS][pP][lL][yY].* | ||
+ | |||
+ | There is the Text Finder plugin which can be configured with any regex and the option to mark the build '' | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | |||
+ | ===== Ideas ===== | ||
+ | * building documenation (ILEDocs) | ||
+ | * making save file from compiled objects | ||
+ | * ftp save file to archive | ||
+ | |||
+ | ===== Links ===== | ||
+ | * [[https:// | ||
+ | * [[http:// | ||
+ | |||
+ | {{tag> | ||