From 0e39db0e359ab0f4b7ce0786f6ef42b5d65df57d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Mattm=C3=BCller?= Date: Tue, 18 Apr 2023 16:04:00 +0200 Subject: [PATCH] README,doc: added next-level-CI and NWL-CI documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit adapted README accordingly to build the documentation. Signed-off-by: Marc Mattmüller --- .gitignore | 1 + README.md | 48 +- doc/Makefile | 225 +++++++ doc/src/_static/theme_overwrites.css | 15 + doc/src/conf.py | 29 + doc/src/index.rst | 38 ++ doc/src/nextlevel-ci/next-level-ci.rst | 611 ++++++++++++++++++ .../setup/media/nwl-ci-jenkins-dashboard.png | Bin 0 -> 91929 bytes doc/src/setup/nwl-ci.rst | 478 ++++++++++++++ 9 files changed, 1436 insertions(+), 9 deletions(-) create mode 100644 .gitignore create mode 100644 doc/Makefile create mode 100644 doc/src/_static/theme_overwrites.css create mode 100644 doc/src/conf.py create mode 100644 doc/src/index.rst create mode 100644 doc/src/nextlevel-ci/next-level-ci.rst create mode 100644 doc/src/setup/media/nwl-ci-jenkins-dashboard.png create mode 100644 doc/src/setup/nwl-ci.rst diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96c541d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +doc/out diff --git a/README.md b/README.md index 3d1b46b..73986dd 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,53 @@ # NetModule Wireless Linux CI/CD Repository - This repository contains all necessary jobs for the CI/CD environment of the NetModule Wireless Linux (NWL). ## Content -This repository holds the jobs for the NWL as declarative pipelines -(multibranch). The directory ``jobs`` holds the main parts: +This repository holds the documentation for the CI environment and the jobs for +the NWL as declarative pipelines (multibranch): -* Jenkinsfile_Build +* doc - - a pipeline building a NWL yocto target + - the documentation of the work for the NWL CI environment -* Jenkinsfile_Common +* jobs - - a collection of commonly used functions, so that duplicated code can be - avoided + - Jenkinsfile_Build + + + a pipeline building a NWL yocto target + + - Jenkinsfile_Common + + + a collection of commonly used functions, so that duplicated code can be + avoided ## Marginal Notes - This repository does NOT cover the setup of the Jenkins instance. + + +## Building the Documentation +The documentation bases on sphinx and is written in reStructuredText format. To +build the documenation you need to install sphinx first: + +```bash +sudo apt install python3-sphinx +sudo pip3 install cloud-sptheme +``` + +Within the directory ``doc`` you can use make as follows: + +```bash +# entering doc: +cd doc + +# clean and build the documentation: +make clean +make html + +# open the generated documentation in the browser: +xdg-open out/html/index.html + +cd .. +``` diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..ea17e78 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,225 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = out + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) src +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) src + +.PHONY: help +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " epub3 to make an epub3" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + @echo " dummy to check syntax errors of document sources" + +.PHONY: clean +clean: + rm -rf $(BUILDDIR)/* + +.PHONY: html +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +.PHONY: dirhtml +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +.PHONY: singlehtml +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +.PHONY: pickle +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +.PHONY: json +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +.PHONY: htmlhelp +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +.PHONY: qthelp +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/NetModuleBeldenCoreOS.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/NetModuleBeldenCoreOS.qhc" + +.PHONY: applehelp +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +.PHONY: devhelp +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/NetModuleBeldenCoreOS" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/NetModuleBeldenCoreOS" + @echo "# devhelp" + +.PHONY: epub +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +.PHONY: epub3 +epub3: + $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3 + @echo + @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3." + +.PHONY: latex +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +.PHONY: latexpdf +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: latexpdfja +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: text +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +.PHONY: man +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +.PHONY: texinfo +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +.PHONY: info +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +.PHONY: gettext +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +.PHONY: changes +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +.PHONY: linkcheck +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +.PHONY: doctest +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +.PHONY: coverage +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +.PHONY: xml +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +.PHONY: pseudoxml +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." + +.PHONY: dummy +dummy: + $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy + @echo + @echo "Build finished. Dummy builder generates no files." diff --git a/doc/src/_static/theme_overwrites.css b/doc/src/_static/theme_overwrites.css new file mode 100644 index 0000000..181f2dd --- /dev/null +++ b/doc/src/_static/theme_overwrites.css @@ -0,0 +1,15 @@ +div.sphinxsidebar { + width: 3.5in; +} + +div.bodywrapper { + margin: 0 0 0 3.5in; +} + +div.document { + max-width: 18in; +} + +div.related { + max-width: 18in; +} diff --git a/doc/src/conf.py b/doc/src/conf.py new file mode 100644 index 0000000..0113a90 --- /dev/null +++ b/doc/src/conf.py @@ -0,0 +1,29 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = 'NetModule Wireless Linux CI/CD' +copyright = '2023, Marc Mattmüller' +author = 'Marc Mattmüller' +release = '0.1' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = ['sphinx.ext.autodoc','sphinx.ext.viewcode','sphinx.ext.todo'] + +templates_path = ['_templates'] +exclude_patterns = [] + + + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = 'cloud' +html_static_path = ['_static'] +html_css_files = ["theme_overwrites.css"] diff --git a/doc/src/index.rst b/doc/src/index.rst new file mode 100644 index 0000000..bf64204 --- /dev/null +++ b/doc/src/index.rst @@ -0,0 +1,38 @@ +.. NetModule Wireless Linux CI/CD documentation master file, created by + sphinx-quickstart on Tue Apr 18 13:04:26 2023. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to NetModule Wireless Linux CI/CD's documentation! +========================================================== + +This documentation provides an overview about the work of the CI/CD for the +NetModule Wireless Linux. + + +Content +******* + +.. toctree:: + :maxdepth: 2 + :caption: Next-Level CI + :glob: + + nextlevel-ci/* + + +.. toctree:: + :maxdepth: 2 + :caption: NWL CI Setup + :glob: + + setup/* + + + +Indices and tables +****************** + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/doc/src/nextlevel-ci/next-level-ci.rst b/doc/src/nextlevel-ci/next-level-ci.rst new file mode 100644 index 0000000..22a0fc6 --- /dev/null +++ b/doc/src/nextlevel-ci/next-level-ci.rst @@ -0,0 +1,611 @@ +.. _nextLevelCiCd: + +************************** +NetModule Next-Level CI/CD +************************** +Foreword +######## +The past half year collaborating with HAC, the NRSW- and OEM-team showed that some parts of the CI might be outdated for +the needs coming towards us. E.g. the single Jenkins Controller might be replaced with a multiple Jenkins Controller +using built-in nodes for each area like NRSW, OEM, etc. +Using a dockerized environment supports this approach. The first steps done for the CoreOS showed that there should be +an automatation to set up a new instance. Therefore a first brainstorming meeting was held the 7th of March 2023. The +output of it and its continuation is reflected in the sections below. + +Rough Overview of the discussion +################################ +Development Areas +***************** +The way development take place differs and can be split into these two groups: + +* Yocto + + - to build an image + - to build a SDK (software development kit) + - to build a package out of the image + - one repository including several submodules distributed over several SCMs + - recommended to build: + + + the base operating system, like CoreOS + + the final product software image + + - blackbox testing of the output + +* Application + + - to build an application running on the base operating system (in user space) + - needs: + + + the SDK + + a unit test framework + + rootfs set up (e.g. for library development) + + - one repository or including submodules but on same SCM + - white- and blackbox testing possible using the unit test framework + + +There are several ways for bringing an application into a release image: + +* yocto recipe populating a (pre-)built binary (or multiple binaries) into the rootfs + + - advantages: + + + less effort maintaining the recipe + + one binary can easily be picked and replaced on a target hardware (e.g. development/debugging) + + feedback on the CI is much faster as the unit tests can be used as pass/fail indicator + + a CI job builds the binary (leads to better overview where a failure is coming from) + + merge requests are made on application level using its unit tests (only mergeable when passing) + + * with this approach a lot of issues can be eliminated as only passing unit tests are merged and brought + into the continuous integration path + + + with this approach there is most likely a workflow for test driven development (TDD) available, this makes + debugging much faster and the design is more robust and better testable + + * a cool benefit with TDD, you can easily mock some layers and build an exhibition version to demonstrate + new features without installing a full blown infrastructure + + .. note:: + **Be aware of a conscious polarization** + + We count the year 2022/2023 and therefore it is a must to develop applications for an embedded Linux + test driven. If you try to find argument against TDD you may ask yourself about what you would expect + when you are buying a high-end product like the one we are selling? + + - disadvantages: + + + it is highly recommended that the SDK version matches with the target release + + the yocto recipe must pick the binary from somewhere on the infrastructure + + you need to take care about permission settings when picking and replacing a binary + + there are much more CI jobs to maintain + + - additional information: + + + when using NetModule's internal GitLab instance, the GitLab CI can be used for the unit tests and mergings. + With it no further Jenkins CI job is necessary. + +* yocto recipe (as currently used) building the application and puts it into the rootfs + + - advantages: + + + the application is built with the environment set up by yocto (e.g. versions); no need of a SDK + + the meta-layer, where the application recipe is in, is much more flexible to share (especially when outside + of the company/infrastructure) + + - disadvantages: + + + more effort maintinging the recipe (source code hashes, etc) + + additional step necessary to indicate the unit test results of the application + + yocto must be launched to build an application (CI perspective) + + longer latency at merge request to get the flag mergeable or not + + +.. important:: + Do not forget the CI environment when thinking of reproducible builds. + + When you build a release on your CI, then the CI has as well a specific state such as Jenkins version, plug-in + versions, certain set of security patches, etc. Over time those versions and the entire environment are changing. + Thus, the CI environment needs as well be tagged as you are tagging your release sources. + + + +Open questions +************** +Released Base Operating System, how further? +============================================ +Let's assume the CoreOS acts as base operating system and is now in a version X.Y.Z released. How do we go further? + +* Do we use eSDK to develop the application for the base operating system and to build the product images? +* Do we continue without Yocto, e.g. by just using the SDK? + +These questions are important as the sstate-cache, the downloads etc. can be shared for further usage. + +What about Visualization? +========================= +For the OEM Linux we used to use Grafana for the visualization. This is another instance in a CI/CD environment. There +are as well some questions about what is going on with the logs during the tests of a product. Shall those be +visualized, e.g. like using something like ELK-Stack? Good to know: GitLab provides visualization support. + +Which SCM Provider shall be used? +================================= +Currently it is unclear if Belden is following the Atlassian approach to use cloud based services, i.e. keeping +bitbucket but within the cloud. Right at the moment we have the following SCM providers: + +* gitea +* gitlab internal (NetModule) +* gitlab public +* bitbucket +* SVN (NetModule NRSW) + +The meanings differ a lot regarding SCM. Nevertheless, the OEM Linux team in CHBE decided as well to move to bitbucket. + +What if Atlassian is stopping the support for non-cloud based instances? This is an open question which influences as +well the CI infrastructure. Why that? Well, actually I have not seen îf the current bitbucket version provides a +built-in CI service. GitLab does and NetModule has an instance which is maintained. This built-in CI might be used in +the application development where unit tests can be run on the built-in CI for merge requests. This leads that on the +continuous integration path the unit tests are at least passing. You see, there is an influence of the SCM provider to +the CI environment. + + +Releasing a Software +******************** +When it comes to a software release then you must consider of tagging as well your CI environment. If you need to +reproduce a released version, you must make sure that you use the same CI environment as it was released. Until now this +was not the case. Just think about all the Jenkins updates, the plugin updates, server updates, etc. In the past we have +faced such an issue where a plugin was updated/changed. A former pipeline could not be built anymore because the used +command was removed. + +So when it comes to a next-level CI environment using docker, we can tag the environment as well and just re-start it in +the tagged version to rebuild an image. + + +Setup Using Docker +****************** +Each Jenkins controller instance might be set up as docker image stack like shown as follows: + +.. code-block:: + + ------------------------ + | Jenkins Controller |<----------------------------------------------------------- + ------------------------ | + | Git |<-- mounting a volume to clone the used repositories to ---- + ------------------------ + | Artifactory |<-- mounting a volume for content + ------------------------ + | Webserver |<-- mounting a volume for content (webserver (ngninx) as reverse proxy) + ------------------------ + | Base OS | + ------------------------ + +By using an Ansible Playbook this stack can be set up connected to the active directory and with all needed credentials +to fulfill the build jobs. + +With this container stack the access is clearly defined and each container is independent from the others. Each +container stack contains its own webserver and artifactory, meaning specific defined URL. Additionally there are no +interferiences between the different teams, e.g. let's assume the NRSW team needs to fix a security relevant bug and +needs to reproduce a specific version. In this case the NRSW needs to bring the CI environment into that state as it was +when the software of concern was released. With a single Jenkins controller mode this would affect the OEM Linux team as +well. + +For NetModule's point of view there would be finally two Jenkins container stacks available, one for the NRSW- and one +for the OEM Linux team. + + + +Setup of First Prototype +######################## +This section holds everything about the setup of the first prototype. + +Intended Setup Process +********************** +The following simplified diagram shows the intended process of setting up a jenkins instance: + +.. code-block:: + + +------------------------------+ +-----------------------------------+ + o-->| Start the Ansible Playbook |---->| Copy necessary Conent to Server | + +------------------------------+ +-----------------------------------+ + | + v + +--------------------------------------------+ + | Setup Volumes, directories & environment | + +--------------------------------------------+ + | + v + +--------------------------------------------+ + | Connect to the Server | + +--------------------------------------------+ + | + v + +--------------------------------------------+ + | Start using docker-compose | + +--------------------------------------------+ + | + o + + +.. note:: + The diagram above assumes that a server is already set up. + + +Intended docker-composition +*************************** +The following pseudo-code shows how the jenkins docker stack is composed: + +.. code-block:: + + version: '3.8' + services: + + jenkins: + image: repo.netmodule.com/core-os/ci-cd/jenkins-coreos:latest + container_name: jenkins + hostname: jenkins + extra_hosts: + - "host.docker.internal:192.168.1.70" + healthcheck: + test: ["CMD","bash","-c","curl --head http://localhost:8080 && exit 0 || exit 1"] + interval: 5s + timeout: 3s + retries: 3 + start_period: 2m + restart: unless-stopped + ports: + - 8080:8080 + - 50000:50000 + networks: + - jenkins_net + environment: + - TZ=Europe/Zurich + - COMPOSE_PROJECT_NAME=jenkins_controller + - CASC_JENKINS_CONFIG=/var/jenkins_conf/cicd.yaml + - A_SSH_PRIVATE_FILE_PATH=/var/jenkins_home/.ssh/ed25519-secrets + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - $PWD/jenkins_home:/var/jenkins_home + - $PWD/jcasc:/var/jenkins_conf + - $PWD/secrets/pw:/run/secrets + - $PWD/secrets/.ssh:/var/jenkins_home/.ssh + - $PWD/secrets/.cacerts:/var/jenkins_home/.cacerts + - $PWD/data:/var/jenkins_home/data + + nginx: + image: nginx:stable-alpine + container_name: nginx + hostname: nginx + extra_hosts: + - "host.docker.internal:192.168.1.70" + restart: unless-stopped + environment: + - TZ=Europe/Zurich + ports: + - 80:80 + - 443:443 + networks: + - jenkins_net + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - $PWD/nginx_html:/var/www/nginx/html + - $PWD/nginx_config/default.conf:/etc/nginx/conf.d/default.conf + # https mode: so far it does not work for self-signed cert + #- $PWD/nginx_config/nginx_example_local.conf:/etc/nginx/conf.d/default.conf + #- $PWD/certs:/etc/nginx/certs + #- $PWD/dhparams.pem:/etc/nginx/dhparams.pem + nexus3: + image: sonatype/nexus3:3.49.0 + container_name: nexus3 + extra_hosts: + - "host.docker.internal:192.168.1.70" + restart: unless-stopped + ports: + - 8081:8081 + networks: + - jenkins_net + environment: + - NEXUS_CONTEXT=nexus + - TZ=Europe/Zurich + volumes: + - $PWD/nexus-data/:/nexus-data/ + + secrets: + bindadpw: + file: $PWD/secrets/pw/bindadpw + sshkeypw: + file: $PWD/secrets/pw/sshkeypw + networks: + jenkins_net: + driver: bridge + + +And we rely on the jenkins service setup as done for the CoreOS: + +.. code-block:: + + jenkins: + systemMessage: "Jenkins Controller" + scmCheckoutRetryCount: 3 + mode: NORMAL + labelString: "jenkins-controller" + numExecutors: 8 + + securityRealm: + activeDirectory: + domains: + - name: "netmodule.intranet" + servers: "netmodule.intranet:3268" + site: "NTMCloudGIA" + bindName: "cn=svc-ldap-ci,ou=Service,ou=Users,ou=NetModule,dc=netmodule,dc=intranet" + bindPassword: "${bindadpw}" + tlsConfiguration: JDK_TRUSTSTORE + groupLookupStrategy: "AUTOMATIC" + removeIrrelevantGroups: false + customDomain: true + cache: + size: 500 + ttl: 600 + startTls: true + internalUsersDatabase: + jenkinsInternalUser: "jenkins" + # local: + # allowsSignup: false + # users: + # - id: admin + # password: ${adminpw:-passw0rd} + # securityRealm: + # local: + # allowsSignup: false + # users: + # - id: admin + # password: ${adminpw:-passw0rd} + # - id: developer + # password: ${developerpw:-builder} + authorizationStrategy: + globalMatrix: + permissions: + - "USER:Overall/Administer:admin" + - "GROUP:Overall/Read:authenticated" + - "GROUP:Agent/Build:authenticated" + - "GROUP:Job/Read:authenticated" + - "GROUP:Job/Build:authenticated" + - "GROUP:Job/Cancel:authenticated" + - "GROUP:Job/Workspace:authenticated" + - "GROUP:Run/Replay:authenticated" + - "GROUP:Run/Delete:authenticated" + + crumbIssuer: "standard" + + security: + GlobalJobDslSecurityConfiguration: + useScriptSecurity: true + queueItemAuthenticator: + authenticators: + - global: + strategy: + specificUsersAuthorizationStrategy: + userid: build_user + + credentials: + system: + domainCredentials: + - credentials: + - basicSSHUserPrivateKey: + scope: GLOBAL + id: git_credentials + # need to keep this username for the first run + username: build_user + usernameSecret: true + passphrase: "${sshkeypw}" + description: "SSH passphrase with private key file for git access" + privateKeySource: + directEntry: + privateKey: "${readFile:${A_SSH_PRIVATE_FILE_PATH}}" + - usernamePassword: + scope: GLOBAL + id: nexus_credentials + username: build_user + usernameSecret: true + password: "${somepw}" + description: "Username/Password Credentials for Nexus artifactory" + + unclassified: + location: + url: http://:8080 + adminAddress: Mr Jenkins + + tool: + git: + installations: + - name: Default + home: "git" + + jobs: + - script: > + multibranchPipelineJob('doc') { + displayName('10. Build Documentation') + description('Builds the Documentation of the CI/CD') + factory { + workflowBranchProjectFactory { + scriptPath('pipelines/Jenkinsfile_Documentation') + } + } + orphanedItemStrategy { + discardOldItems { + numToKeep(5) + } + } + branchSources { + git { + id('build-doc') + remote('git@gitlab.com:netmodule/core-os/cicd.git') + credentialsId('git_credentials') + includes('develop release*') + } + } + } + + +Comparison to the HAC CI +######################### +This section describes the differences of the concept above and the one at HAC after having a sync meeting with the +guardians. + +Situation at HAC +**************** +As already known the CI at HAC is constructed with docker containers. But how do they handle the infrastructure if it +comes to a use case where they need to reproduce an already release version. Find the situation at HAC as follows: + +* the CI infrastructure bases on the help of the IT department + + - new infrastructure like new physical machines and their setup is done by the IT department + - they restore parts from backups if necessary + +* dockerfiles describe the docker containers used for building software releases + + - AFAIK, the images are pushed to the HAC docker registry + +* some infrastructure parts refer directly to the images on docker hub without pushing them to the HAC docker registry +* they use self-created scripts to orchestrate build instances, e.g. creating and starting new instances +* depending on the age of the release to reproduce a bunch of manual steps are needed to rebuild it +* there is already a good state of tracking the versions of a software release and CI infrastructure + + - tickets are already open to optimize this version breakdown + +* no ansible playbook used + + +Differences between HAC CI and the Proposal +******************************************** +The following list shows the biggest difference of the proposal and the current HAC CI. + +* Bring-up of new instances: ansible playbook versus self-created scripts +* General usage of an ansible playbook + + - with a playbook the setup of the infrastructure is as well versionized (git repository which can be tagged) + - less dependencies to the IT department + +* one dedicated infrastructure part, e.g. web server, artifactory + + - all the different CI chains depend on this dedicated infrastructure part + - tracing all the dependencies when releasing a software increases very much over time + - replication on another network is more difficult as the dedicated infrastructure part needs to be realized too + - better encapsulation if the web server and artifactory is part of the instance compound + +* docker images pushed to company internal docker registry + + - for a proper tracking of versions and reproduction of an already released version, the sources need to be in the + companies network, i.e. all used docker images need to be available on the company internal docker registry + - with the availability of the images in the company docker registry the versioning is guaranteed as the the docker + files refer to an image residing in an accessbile registry and do not depend on the docker hub. + +.. note:: + Maybe there are some more differences but at the current point these are the most important ones. + + +Conclusion +*********** +After the discussion about the differences and due to the case that versioning is already in the focus of the HAC CI, we +decided to not build a docker compound as stated in the section `Setup of First Prototype`_. We try to bring up an +instance on the HAC CI but with an interface so that the CI jobs can be managed by the teams itself to not disturb the +heavily lodaded HAC CI team too much. + +So the further documentation is done in :ref:`nwlCiCd` + + +Sandbox Section ;-D +################### +some links: + +* https://www.howtoforge.com/how-to-setup-nginx-as-a-reverse-proxy-for-apache-on-debian-11/ +* https://www.supereasy.com/how-to-configure-nginx-as-a-https-reverse-proxy-easily/ +* https://xavier-pestel.medium.com/how-to-manage-docker-compose-with-ansible-c08933ba88a8 +* https://stackoverflow.com/questions/62452039/how-to-run-docker-compose-commands-with-ansible/62452959#62452959 +* https://plugins.jenkins.io/ansible/ +* https://www.ansible.com/blog +* https://k3s.io/ +* https://www.dev-insider.de/kubernetes-cluster-mit-einem-klick-einrichten-a-1069489/ +* https://adamtheautomator.com/ansible-kubernetes/ +* http://web.archive.org/web/20190723112236/https://wiki.jenkins.io/display/JENKINS/Jenkins+behind+an+NGinX+reverse+proxy + + +a docker-compose file as look-up example: + +.. code-block:: + + services: + postgres: + image: 'postgres:latest' + redis: + image: 'redis:latest' + nginx: + restart: always + build: + dockerfile: Dockerfile.dev + context: ./nginx + ports: + - '3050:80' + api: + build: + dockerfile: Dockerfile.dev + context: ./server + volumes: + - /app/node_modules + - ./server:/app + environment: + - REDIS_HOST=redis + - REDIS_PORT=6379 + - PGUSER=postgres + - PGHOST=postgres + - PGDATABASE=postgres + - PGPASSWORD=postgres_password + - PGPORT=5432 + client: + build: + dockerfile: Dockerfile.dev + context: ./client + volumes: + - /app/node_modules + - ./client:/app + worker: + build: + dockerfile: Dockerfile.dev + context: ./worker + environment: + - REDIS_HOST=redis + - REDIS_PORT=6379 + volumes: + - /app/node_modules + - ./worker:/app + + + FROM nginx + COPY ./default.conf /etc/nginx/conf.d/default.conf + + + upstream client { + server client:3000; + } + + upstream api { + server api:5000; + } + + server { + listen 80; + + location / { + proxy_pass http://client; + } + + location /sockjs-node { + proxy_pass http://client; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + } + + location /api { + rewrite /api/(.*) /$1 break; + proxy_pass http://api; + } + + } diff --git a/doc/src/setup/media/nwl-ci-jenkins-dashboard.png b/doc/src/setup/media/nwl-ci-jenkins-dashboard.png new file mode 100644 index 0000000000000000000000000000000000000000..29e85aa64bd459bedbc5ca664c310670a6e2c8a0 GIT binary patch literal 91929 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

2P$n-zSv+!Svzekdw`vm_>=0lmx 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

BpBZN_pO92V?|Lz8(Q*oZS|1^= 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 + + # using the created aliases + echo "Test" | mail root + + +The VM acting as CI/CD server is accessible as follows: + +* IP = ``10.115.101.98`` +* Users (ask me or Tobias Hess for the passwords): + + - root + - user + + +Overview +******** +There are several repositories involved in this CI infrastructure, please find here the most important ones: + +* `build-admin `_ + + - contains configuration items in xml format + - keys and certificates for signing and service access + - scripts like the manage script for creating/starting/stopping an instance: + + .. code-block:: bash + + # example for the hilcos platform: + ./manage.sh --image=ci.gad.local:5000/env-ci-hilcos:latest --branch=release/hilcos/10/12-exotec \ + --name=hilcos_10_12 --platform=hilcos \ + --config=/home/administrator/work/ci/instances/hilcos/release/hilcos/10/12-exotec/config/config.xml \ + --revision=10.12.5000 -maintainer=TeamFlamingo create + +* `build-docker `_ + + - **NOTE:** This repository is over 12GB because some toolchain tarballs are included + - contains the files for the docker images + - scripts to build the docker images + - holds jenkins scripts seeding jobs + +* `build-pipeline `_ + + - contains the build pipeline in the HAC CI system + +* `build-env `_ + + - contains class objects for the scripted pipelines + - sets up a Jenkins Library + + +Workflow Understood by mma +========================== +As far as I understood the dependencies in the CI of HAC, the workflow looks as follows: + +#. Manually set up a physical or virtual server + + - installing basic tools like docker as the most important one + - add the needed users and its used credentials for the CI environment + - preparing the server itself in a manner to be ready for hooking it in the HAC environment + +#. Manually preparation of the CI instance + + - preparing the server with the structure needed for hooking the instance in the HAC CI system, e.g. + + + credentials for the docker instance(s) + + etc. + + - preparing the CI instance properties + + + checking out the right branches (build-docker, evtl. build-admin) + + database and its environment + + etc. + +#. Unless available build the docker compound in the desired composition +#. Calling the manage script with create (repository: build-admin) +#. Bringing the instance up with the manage script + + +With this workflow and the seen dependencies I see two potential ways to step in for the NWL: + +#. within *build-admin* in the configuration file + + - create a branch for NWL + - adding another repository than build-pipeline + +#. within *build-docker* in the jenkins seed job + + - create a branch from *feature/ci/core_os* for NWL, e.g. *feature/ci/nwl* + - adapt the seee.groovy script with the needed multibranch pipelines + +The next section descibes the proposed and chosen way. + + +Proposed Hook to Step In +************************ +Branching the *build-admin* project to bring declarative pipelines into the HAC CI infrastructure (which then are +maintained by the developer team) seems **not** to be the best way because this is the common base for all CI projects. +In addition thinking into the future where potentially all CI projects might be integrated into one Belden CI +infrastructure this way neither seems to be right. Thus, I propose the second way: + +#. Implement a hook in the Jenkins CI seed job residing in the repository **build-docker** + + #) branching from *feature/ci/core_os* for the NWL, e.g. *feature/ci/nwl* + #) adapt the *seed.groovy* script with the needed multibranch pipelines + +#. The seed job points to a multibranch pipeline in a NWL CI repository: + + - `Repository `_ + - Clone with Git: ``git clone ssh://git@bitbucket.gad.local:7999/nm-nsp/nwl-ci.git`` + + +Implementation of Proposed Hook +******************************* +An adpation in the Jenkins CI seed job points to a multibranch pipeline for the NWL instead of the usual build pipeline. +Additionally a draft pipeline for the NWL is committed. + +There was an open question if there is a docker image for the CoreOS instance in the HAC docker registry. The sync +meeting between HAC and NM regarding CoreOS clarified this question with the statement "no currently there is not as it +is still not final and the docker registry is moved to another instance". This means we need to create a docker image +locally on the server and start with this one. + +Well, let's create and start a NWL Jenkins instance... + +On `build-docker `_ we fork the branch +*feature/ci/core_os* and name the new branch **feature/ci/nwl**. All changes for the NWL CI are made on this branch. See +the following sections. + + +Brining Up the Instance +======================= +Before we can start the instance we need to create a docker image so that it is available locally on the physical +server. + +.. note:: + The docker registry is currently moved to another location and thus it is not recommended to push this first trial + to the registry. + + +Building the CI Docker Image +---------------------------- +The Guardians recommend to use a user **without** root priviledges. Thus, we need to add our user to the docker group: + +.. code-block:: bash + + # Log into the server as root + ssh root@10.115.101.98 + usermod -a -G docker user + # Log out + + +.. note:: + Several question could be clarified after a short meeting with Arne Kaufmann. + + We build the docker image with user *user*. But as the jenkins-ci image layer uses the *nofmauth* repository it was + not possible to build it on the server itself. The reason seems to be that the SSH key of user@netmodule-03 has no + access to the *nofmauth* repo but is somehow added to bitbucket. Arne is trying to find the location where the + user's SSH key is added. + + Arne recommended to build the docker image locally on the developer machine and then transfer it to the server. + + +Building locally did not work out of the box. There was an issue with the DNS when building the docker image: + +.. code-block:: bash + + => ERROR [stage-0 6/10] RUN --mount=type=ssh mkdir -p /var/lib/ci/libs && cd /var/lib/ci/libs && mkdir -p -m 0700 ~/.ssh && ss 0.3s + ------ + > [stage-0 6/10] RUN --mount=type=ssh mkdir -p /var/lib/ci/libs && + cd /var/lib/ci/libs && mkdir -p -m 0700 ~/.ssh && + ssh-keyscan -p 7999 bitbucket.gad.local >> ~/.ssh/known_hosts && + git clone ssh://git@bitbucket.gad.local:7999/inet-ci/nofmauth.git && + rm ~/.ssh/known_hosts && nofmauth/lib && ./buildLib.sh && mkdir -p WEB-INF/lib && mv nofmauth.jar WEB-INF/lib && + jar --update --file /usr/share/jenkins/jenkins.war WEB-INF/lib/nofmauth.jar && cd /var/lib/ci && rm -rf libs: + #0 0.240 getaddrinfo bitbucket.gad.local: Name or service not known + #0 0.244 getaddrinfo bitbucket.gad.local: Name or service not known + #0 0.247 getaddrinfo bitbucket.gad.local: Name or service not known + #0 0.251 getaddrinfo bitbucket.gad.local: Name or service not known + #0 0.255 getaddrinfo bitbucket.gad.local: Name or service not known + +Thus, the the build.sh got a new docker build argument according commit +`fb26e9 `_. + +.. note:: + The master or stable branch holds the newly changed jenkins plugin installation solution. If there are any issues + the branch needs to be rebased with the master/stable. + + +Let's build the NWL docker images locally on our machine assuming that the repository *build-docker* is cloned, the +branch *feature/ci/nwl* checked out and available: + +.. code-block:: bash + + # Enter the build-docker directory: + cd ~/belden/build-docker + + # Enable the ssh-agent with your private SSH key which should only be used to clone the nofmauth repo and + # should not go into the docker image. Finally check if the key is loaded: + eval `ssh-agent` + ssh-add ~/.ssh/id_rsa + ssh-add -L + ssh-rsa ******************************** + + # Build the docker image: + DOCKER_BUILDKIT=1 ./build.sh nwl 0.1.0 + ********************************************************** + ** Building basic-os image + ********************************************************** + [+] Building 1.4s (18/18) FINISHED + ... + => => naming to docker.io/library/basic-os + ********************************************************** + ** Building nwl image + ********************************************************** + [+] Building 0.0s (6/6) FINISHED + ... + => => naming to docker.io/library/nwl + ********************************************************** + ** Building jenkins image + ********************************************************** + ... + [+] Building 0.1s (19/19) FINISHED + ... + => => naming to docker.io/library/nwl-jenkins + ********************************************************** + ** Building jenkins-ci image + ********************************************************** + [+] Building 1.3s (17/17) FINISHED + ... + => => naming to docker.io/library/nwl-jenkins-ci + ********************************************************** + ** Building env-ci image + ********************************************************** + [+] Building 0.0s (6/6) FINISHED + ... + => => naming to docker.io/library/nwl-env-ci + ********************************************************** + ** Building klocwork image + ********************************************************** + [+] Building 0.0s (18/18) FINISHED + ... + => => naming to docker.io/library/nwl-klocwork + Done! + + # Overview of the created images: + docker image ls + REPOSITORY TAG IMAGE ID CREATED SIZE + nwl-klocwork latest 17e59d7f36fd 2 hours ago 7.18GB + nwl-env-ci latest 0d053988863b 2 hours ago 1.99GB + nwl-jenkins-ci latest c4298f02759e 2 hours ago 1.99GB + nwl-jenkins latest d6d06c06c790 3 hours ago 1.72GB + nwl latest 924de047f0bf 3 hours ago 1.6GB + basic-os latest d20d08843c00 3 hours ago 739MB + + +For completeness we transfer all those images to the server by using two potential ways: + +#. Using pipes directly: + + .. code-block:: bash + + docker save : | bzip2 | pv | ssh @ docker load + +#. Using multiple steps when there are issues with the VPN: + + .. code-block:: bash + + docker save -o : + rsync -avzP -e ssh @<10.115.101.98>:/home/user/ + docker load -i /home/user/ + + +After transferring the docker images to the server we check if they are listed: + +.. code-block:: bash + + user@netmodule-03:~/build-docker$ docker image ls + REPOSITORY TAG IMAGE ID CREATED SIZE + nwl-klocwork latest 17e59d7f36fd 2 hours ago 7.18GB + nwl-env-ci latest 0d053988863b 2 hours ago 1.99GB + nwl-jenkins-ci latest c4298f02759e 2 hours ago 1.99GB + nwl-jenkins latest d6d06c06c790 3 hours ago 1.72GB + nwl latest 924de047f0bf 3 hours ago 1.6GB + basic-os latest d20d08843c00 3 hours ago 739MB + + +.. _basicoswarning: + +Switching to Debian as Basic OS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. note:: + After running a first pipeline in this instance, after the work documented in `Starting the CI Instance`_ I detected + the yocto warning ``WARNING: Host distribution "ubuntu-20.04" ...``. As in NetModule the servers and developer + machines base on Debian, I created new images based on Debian 11. Additionally I tagged all the images accordingly + to have a proper overview: + + .. code-block:: bash + + user@netmodule-03:~/work/ci$ docker image ls + REPOSITORY TAG IMAGE ID CREATED SIZE + nwl-env-ci 0.1.1 e89036df18a3 58 minutes ago 2.19GB + nwl-env-ci latest e89036df18a3 58 minutes ago 2.19GB + nwl-jenkins-ci 0.1.1 9fbb8eeaa717 2 hours ago 2.19GB + nwl-jenkins-ci latest 9fbb8eeaa717 2 hours ago 2.19GB + nwl-jenkins 0.1.1 1f6b2c0d644a 2 hours ago 1.94GB + nwl-jenkins latest 1f6b2c0d644a 2 hours ago 1.94GB + nwl 0.1.1 a30655b9de0e 2 hours ago 1.82GB + nwl latest a30655b9de0e 2 hours ago 1.82GB + basic-os 0.1.1 fc2ea6009615 2 hours ago 823MB + basic-os latest fc2ea6009615 2 hours ago 823MB + nwl-klocwork 0.1.0 17e59d7f36fd 24 hours ago 7.18GB + nwl-klocwork latest 17e59d7f36fd 24 hours ago 7.18GB + nwl-env-ci 0.1.0 0d053988863b 24 hours ago 1.99GB + nwl-jenkins-ci 0.1.0 c4298f02759e 24 hours ago 1.99GB + nwl-jenkins 0.1.0 d6d06c06c790 25 hours ago 1.72GB + nwl 0.1.0 924de047f0bf 25 hours ago 1.6GB + basic-os 0.1.0 d20d08843c00 25 hours ago 739MB + + + +Starting the CI Instance +------------------------ +.. note:: + The *build-admin* repository does neither have a branch for CoreOS nor holds a directory with the keys for it. The + directory ``~/work/ci`` on the server was prepared by the Guardians. This preparation holds keys for the CoreOS + residing in the subdirectory keys/coreos. + + To have at least on the server a separation, we copy the keys of the CoreOS and use them for NWL. + + +.. code-block:: bash + + # Change the directory to + cd ~/work/ci + + # Separating NWL from CoreOS by copying its keys (those keys are already set up): + cp -R keys/coreos keys/nwl + + +So far we have everything set up to start the instance using ``manage.sh``. The arguments are explained as follows: + +* image + + - the docker image to take + +* branch + + - the branch of the NWL repository to build + - the branch of the repository where the jenkins file is located + + + This one here can be omitted as we use the hook over *seed.groovy* + +* name + + - the name of the instance + +* config + + - the configuration XML to use --> currently we do not have changes as we use the hook over *seed.groovy* + +* platform + + - keep in mind that this argument defines as well the directory for the keys + +* revision + + - revision of the container (build version) - Note: for HiOs this parameter is read for the release version + +* maintainer + + - the team which is in charge for this instance + + +With all those information we give now a try to launch this instance: + +.. code-block:: bash + + # create the instance: + ./manage.sh --image=nwl-env-ci:latest --branch=main \ + --name=nwl_0_1 --platform=nwl \ + --config=/home/user/work/ci/config/config.xml \ + --revision=0.1.0 --maintainer=TeamCHBE create + Creating new instance... + Done! + + # check the entry: + ./manage.sh -p + +---------+----------------------------+-------+---------+--------+----------+------------+----------+-------------------+--------------+---------+ + | name | host | port | status | branch | revision | maintainer | platform | image | container | display | + +---------+----------------------------+-------+---------+--------+----------+------------+----------+-------------------+--------------+---------+ + | nwl_0_1 | netmodule-03.tcn.gad.local | 32780 | running | main | 0.1.0 | TeamCHBE | nwl | nwl-env-ci:latest | 60726aec0ebc | NULL | + +---------+----------------------------+-------+---------+--------+----------+------------+----------+-------------------+--------------+---------+ + +.. note:: + Currently there is the LDAP password missing in jenkins configuration XML (jenkins.xml), thus Jenkins does not start + properly. + + To continue testing the instance start-up, I disabled the LDAP configuration. + + +Let's enter the newly created instance in the `browser `_. + +|coreOsCiChain| + + +As mentioned in :ref:`basicoswarning` all the images are rebuilt by basing on a Debian 11. To be sane with versioning +and to clean the instances the previous instance was destroyed with ``./manage.sh --name=nwl_0_1 destroy``. The newly +created images are tagged with version *0.1.1*. + +Let's create the new instance and bring it up: + +.. code-block:: bash + + # create the instance: + ./manage.sh --image=nwl-env-ci:0.1.1 --branch=main \ + --name=nwl_0_1_1 --platform=nwl \ + --config=/home/user/work/ci/config/config.xml \ + --revision=0.1.1 --maintainer=TeamCHBE create + Creating new instance... + Done! + + # check the entry: + ./manage.sh -p + +-----------+----------------------------+-------+---------+--------+----------+------------+----------+------------------+--------------+---------+ + | name | host | port | status | branch | revision | maintainer | platform | image | container | display | + +-----------+----------------------------+-------+---------+--------+----------+------------+----------+------------------+--------------+---------+ + | nwl_0_1_1 | netmodule-03.tcn.gad.local | 32780 | running | main | 0.1.1 | TeamCHBE | nwl | nwl-env-ci:0.1.1 | 0eb450fc827a | NULL | + +-----------+----------------------------+-------+---------+--------+----------+------------+----------+------------------+--------------+---------+ + + + + + +mma Tasks +********** +These are the tasks: + +* [x] build on the server locally the docker compound +* [x] start the instance +* [x] test the build pipelines +* [ ] implement LDAP connection? + + + +.. |coreOsCiChain| image:: ./media/nwl-ci-jenkins-dashboard.png + :width: 700px +