{"id":3314,"date":"2018-03-28T20:50:00","date_gmt":"2018-03-28T18:50:00","guid":{"rendered":"https:\/\/blog.mi.hdm-stuttgart.de\/?p=3314"},"modified":"2023-06-09T14:22:37","modified_gmt":"2023-06-09T12:22:37","slug":"continuous-integration-deployment-for-a-cross-platform-application-part-1","status":"publish","type":"post","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2018\/03\/28\/continuous-integration-deployment-for-a-cross-platform-application-part-1\/","title":{"rendered":"Continuous Integration &#038; Deployment for a Cross-Platform Application &#8211; Part 1"},"content":{"rendered":"<p>When we started the project &#8220;Flora CI&#8221; for the lecture &#8220;System Engineering&#8221;, we planned to deal with Continuous Integration. As an important aspect of software engineering all of us have previously been involved in projects where code of developers had to be merged and builds had to be automated somehow. Anyway we felt we could dive deeper into CI pipelines and learn what it needs to get them running in a performant, useful and reliable way.<\/p>\n<p>On our journey building such a system we also planned the containerization of all components in order to achieve the strongest possible encapsulation of the individual processes and to gain experience in this topic as well. Another planned goal was the automatic deployment into the corresponding Android and iOS App Stores as well as the provision on a web server.<\/p>\n<p><!--more--><\/p>\n<p>Since all costs for the project were covered privately, it was also important to find a cost-effective solution for all challenges that arose.<\/p>\n<p><strong>The following list summarizes the goals set:<\/strong><\/p>\n<ul>\n<li>Continuous integration of a cross-platform application (Android, iOS, Web)<\/li>\n<li>Containerization of all components (GitLab, Runner, Webserver)<\/li>\n<li>Deployment in different App Stores or on web servers (Staging &amp; Production)<\/li>\n<li>Enable automated testing of the application<\/li>\n<li>Cost-effective solution<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h2>Approach<\/h2>\n<h3>Building a Hybrid App with Ionic<\/h3>\n<p>Hybrid apps are a combination of native and web apps. They are written with web technologies like HTML5, CSS and Javascript and run on the respective platforms in a WebView. Using a hybrid framework such as Apache Cordova or Electron, the applications are wrapped and built for the desired platform. In addition, these frameworks provide interfaces to native device resources.<\/p>\n<p>For our project we are using the Ionic Framework, an open source framework for building mobile apps, licensed under MIT. Ionic uses Apache Cordova to deploy natively, or runs in the browser as a Progressive Web App.<\/p>\n<p>Our app called Flora is a simple application that provides you a list of plants you can manage. By opening the detail view you get a 3D view of the plant. The data is always synced to a backend (Node.js &amp; MongoDB).<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Integrating 3D context<\/strong><\/p>\n<p>When we decided to carry out a continuous integration project for several platforms, we also wanted to take this opportunity to integrate a 3D context into the application as real-time 3D applications can pose a great challenge in terms of development and maintenance due to the different hardware and operating systems. This is the case for instance, if you use different OpenGL\/OpenGL ES for different target platforms.<\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"3660\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2018\/03\/28\/continuous-integration-deployment-for-a-cross-platform-application-part-1\/three\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/three.png\" data-orig-size=\"1004,494\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"three\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/three.png\" class=\"aligncenter size-full wp-image-3660\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/three.png\" alt=\"\" width=\"1004\" height=\"494\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/three.png 1004w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/three-300x148.png 300w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/three-768x378.png 768w\" sizes=\"auto, (max-width: 1004px) 100vw, 1004px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>The implementation of the 3D content was based on the WebGL Framework Three.js, which is executed in a browser or framework like Ionic. Only this part actually communicates with the hardware.&nbsp;Compared to other projects in which the respective hardware and operating system had to be supported natively, in this case the effort for a cross-platform application was significantly lower.<\/p>\n<p>&nbsp;<\/p>\n<h3>Evaluating CI Tools<\/h3>\n<p>After setting our goals, we defined a few points of content for further action. After one goal was the development according to the Continuous Integration principle, we started looking for a suitable CI tool. We finally chose GitLab CI\/CD because we had already used GitLab in other projects as a versioning control system and wanted to gain experience regarding its possibilities in the context of continuous integration. During our research we came across other popular tools for continuous integration besides GitLab, which we would like to mention briefly.<\/p>\n<p>Originally developed by Sun Microsystems, <strong>Jenkins<\/strong> is a build system now available under MIT license that is very popular and widely used in Java projects. By means of a plugin it can also be used for other languages. However, a native JIRA integration is missing and it is often mentioned that the actual operating costs are difficult to estimate. In addition, the possibilities for cooperation within Jenkins seem to be limited. For example, a developer cannot see the commits of another developer.<\/p>\n<p>Another tool with JIRA integration is <strong>Bamboo<\/strong>, which is developed by Atlassian like the software project management system JIRA. This is a proprietary product with a variety of useful functions. Nutern criticized that the most cost-effective basic version has extremely limited functionality.<\/p>\n<p><strong>TeamCity<\/strong>, developed by JetBrains, is another very popular continuous integration tool. JetBrains is known for its mature products in the area of Integrated Development Environments, which are usually also available across platforms and therefore also allow cross-platform development. A disadvantage here seems to be a too high license price for many users.<\/p>\n<p>In the end, the reason for using <strong>GitLab CI<\/strong> was not just because we had already gotten to know it as a repository hosting platform. Compared to Jenkins, we had even more advantages. On the one hand, GitLab CI combines the administration of the repository and tools required for continuous integration in one web application. In addition, the good user experience of GitLab is emphasized again and again, and so far we have had only positive experience with the use of GitLab. The web application also includes tools for an agile development process, like the Issue Board. We had already used these tools more intensively in previous projects.<\/p>\n<p>Another important point is that GitLab jobs can be performed in Docker Containers and runners (which execute jobs) can be distributed across multiple GitLab projects.<\/p>\n<p>&nbsp;<\/p>\n<h2>Infrastructure<\/h2>\n<h3>Finding suitable Hardware<\/h3>\n<p>The very first task to get a hands-on experience with Docker, CI and CD was setting up a server. Since we all had some experiences with a virtual server on Amazon AWS, we quickly took an EC2-instance, installed Docker, gave all of us admin access and tried to launch GitLab in a Docker container as described in the GitLab docs. Unfortunately, it did not work.<\/p>\n<p>We only got some meaningless error output in the console that GitLab could not be started. After some research, we found out that GitLab needs at least 2 GB RAM (recommended 4GB). Consequently, this free AWS instance didnt\u2019t have enough capabilities for our goals. Instead of using the HdM server, where we expected a lot of problems with insufficient rights, blocked ports, blocked applications and so on, we decided to buy an own server to get a more &#8216;real-world-use-case&#8217;.<\/p>\n<p>After some research we decided to use a <strong>vServer<\/strong> with 4 GB DDR3 RAM which costs 4\u20ac\/month and seemed to be enough for our use case. So, we had to transfer all of our Docker images and config data to our new server and thereby we created a perfect scenario for using Docker, since one of its main advantages include its portability. This process was really easy even though we learned why Docker is called a stateless application: Only transferring the Docker images to the new server was not enough since e.g. the complete GitLab configuration (like projects, tickets, webhooks, users, \u2026) is saved in a separate folder which has to be transferred as well. File or folder like those can be specified in the Docker file with the &#8216;volumes&#8217; key, which determines where e.g. the GitLab config will be mounted to: e.g.:&nbsp;<code class=\"\" data-line=\"\">\/srv\/GitLab\/config:\/etc\/GitLab<\/code><\/p>\n<p>Consequently, transfering <strong>stateless<\/strong> as well as <strong>stateful<\/strong> applications with Docker is really easy!<\/p>\n<p>But the infrastructure was still not completely solved: Our first builds needed about ~50-60 minutes on our own server! That was way too much and unsatisfying. Additionally, our server was down quite often and overstrained by executing the build process. So, again, we transferred some processes to another server: this time we moved all runners (which run the CI jobs) to the (quite fast!) HdM Server, which lowered the build time at a large scale!<\/p>\n<p>Additionally, we had to rent Apple-related hardware and software to be able to build our application for iOS and mac OS. So, in the end we had one vServer with GitLab, the HdM Server to run #web and #android jobs and a Mac Mini Server which is able to run #web, #android as well as #ios jobs.<\/p>\n<p>In the end, we also moved our backend to an Amazon AWS EC2 instance and put the web build to an Amazon AWS S3 storage. Thereby we decreased our build time to 10-20 minutes.<\/p>\n<p>&nbsp;<\/p>\n<figure id=\"attachment_3359\" aria-describedby=\"caption-attachment-3359\" style=\"width: 2458px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"3359\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2018\/03\/28\/continuous-integration-deployment-for-a-cross-platform-application-part-1\/flora_infrastructure\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/flora_infrastructure.jpg\" data-orig-size=\"2458,1248\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"flora_infrastructure\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/flora_infrastructure-1024x520.jpg\" class=\"wp-image-3359 size-full\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/flora_infrastructure.jpg\" alt=\"\" width=\"2458\" height=\"1248\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/flora_infrastructure.jpg 2458w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/flora_infrastructure-300x152.jpg 300w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/flora_infrastructure-768x390.jpg 768w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/flora_infrastructure-1024x520.jpg 1024w\" sizes=\"auto, (max-width: 2458px) 100vw, 2458px\" \/><figcaption id=\"caption-attachment-3359\" class=\"wp-caption-text\"><em>Fig.: Our final schematic infrastructure setup including 5 different servers and its applications represented by icons.<\/em><\/figcaption><\/figure>\n<p>&nbsp;<\/p>\n<h3>Setting up the server<\/h3>\n<p>All applications (node.js and MongoDB backend, GitLab, nginx) are defined by a <strong>Dockerfile<\/strong> using docker-compose and are executed in a Docker container. This brings us portability, containerization and scalability. However, as a counterpart we had to discuss how those different containers are able to communicate with each other: The solution includes the &#8216;ports&#8217; key in the Dockerfile, where it is defined which port will be exposed, as well as nginx as a reverse proxy.<\/p>\n<p>The setup of <strong>nginx<\/strong> is straight-forward: You define the port that nginx listens to, which is port 80 as a reverse-proxy. You declare the server name like the root example.de or gitlab.example.de and finally the port the request will be mapped to. In this example, all requests for the subdomain GitLab will be forwarded to the port 9090, on which the Docker of GitLab is exposed.<\/p>\n<p>As the root page we wanted to display the current web build: So in the end of each build process we started an nginx webserver, in which we mounted the web build artifact and exposed a certain port. That way it was easy accessible by configuring the nginx. Later, as the frontend was moved to Amazon AWS S3, we only had to change the location of root to proxy_pass it to the address of the S3 location.<\/p>\n<p>&nbsp;<\/p>\n<figure id=\"attachment_3360\" aria-describedby=\"caption-attachment-3360\" style=\"width: 2430px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"3360\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2018\/03\/28\/continuous-integration-deployment-for-a-cross-platform-application-part-1\/nginx\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/nginx.jpg\" data-orig-size=\"2430,1205\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"nginx\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/nginx-1024x508.jpg\" class=\"wp-image-3360 size-full\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/nginx.jpg\" alt=\"\" width=\"2430\" height=\"1205\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/nginx.jpg 2430w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/nginx-300x149.jpg 300w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/nginx-768x381.jpg 768w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/nginx-1024x508.jpg 1024w\" sizes=\"auto, (max-width: 2430px) 100vw, 2430px\" \/><figcaption id=\"caption-attachment-3360\" class=\"wp-caption-text\"><em>Fig.: A request is initially handled by nginx which is executed in a docker container and forwards it. Docker-compose lets us easily start, restart and configure all applications in docker containers.<br \/><\/em><\/figcaption><\/figure>\n<p>&nbsp;<\/p>\n<p>So, all in all setting up nginx as a reverse-proxy is really easy but you have to think about the structure of your application. You have to think in particular about how the applications in their Dockerfiles will be able to communicate to each other.<\/p>\n<p>A more annoying problem is the hardware as you do not want to spend a lot of money when getting a hands-on experience with Docker and such. On the other hand, you should at least invest enough to get a server which empowers you to focus on your application and your use case instead of getting distracted from server issues all the time.<\/p>\n<p>In the second part of our blog article we will cover how we set up our pipeline with GitLab CI, what problems we encountered and how we solved them. Stay tuned!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When we started the project &#8220;Flora CI&#8221; for the lecture &#8220;System Engineering&#8221;, we planned to deal with Continuous Integration. As an important aspect of software engineering all of us have previously been involved in projects where code of developers had to be merged and builds had to be automated somehow. Anyway we felt we could [&hellip;]<\/p>\n","protected":false},"author":188,"featured_media":3462,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[659,649,653,650,22,651,2],"tags":[],"ppma_author":[746],"class_list":["post-3314","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops","category-interactive-media","category-mobile-apps","category-scalable-systems","category-student-projects","category-system-designs","category-system-engineering"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/flora-app.jpg","jetpack-related-posts":[{"id":251,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2016\/01\/25\/continuous-integration-marina-kettschik\/","url_meta":{"origin":3314,"position":0},"title":"Continuous Integration (CI)","author":"Marina Kettschik","date":"25. January 2016","format":false,"excerpt":"Large software projects require a group of programmers. Everybody is focused on their own coding part and it may take quite a while to complete it. But what happens when the individual pieces are merged? The integration of the puzzle pieces in a system can be very time consuming and\u2026","rel":"","context":"In &quot;DevOps&quot;","block_context":{"text":"DevOps","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/scalable-systems\/devops\/"},"img":{"alt_text":"continuous integration system by Marina Kettschik","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2016\/01\/ci-system-1-1.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2016\/01\/ci-system-1-1.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2016\/01\/ci-system-1-1.jpg?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":3496,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2018\/03\/30\/ci-cd-with-gitlab-ci-for-a-web-application-part-1\/","url_meta":{"origin":3314,"position":1},"title":"CI\/CD with GitLab CI for a web application &#8211; Part 1","author":"Nina Schaaf","date":"30. March 2018","format":false,"excerpt":"Introduction When it comes to software development, chances are high that you're not doing this on your own. The main reason for this is often that implementing components like UI, frontend, backend, servers and more is just too much to handle for a single person leading to a slow development\u2026","rel":"","context":"In &quot;DevOps&quot;","block_context":{"text":"DevOps","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/scalable-systems\/devops\/"},"img":{"alt_text":"Shaky architecture","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/01_shaky-architecture-300x106.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":5163,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2019\/02\/24\/migrating-to-kubernetes-part-1-introduction\/","url_meta":{"origin":3314,"position":2},"title":"Migrating to Kubernetes Part 1 &#8211; Introduction","author":"Can Kattwinkel","date":"24. February 2019","format":false,"excerpt":"Written by: Pirmin Gersbacher, Can Kattwinkel, Mario Sallat Introduction The great challenge of collaborative working in a software developer team is to enable a high level of developer activity while ensuring a high product quality. In order to achieve this often CI\/CD processes are utilized. Talking about modern development techniques\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":3421,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2018\/03\/28\/take-me-home-project-overview\/","url_meta":{"origin":3314,"position":3},"title":"Take Me Home &#8211; Project Overview","author":"cp054","date":"28. March 2018","format":false,"excerpt":"Related articles:\u00a0\u25baCI\/CD infrastructure: Choosing and setting up a server with Jenkins as Docker image\u00a0\u25baDockerizing Android SDK and Emulator for testing\u00a0 \u25baAutomated Unit- and GUI-Testing for Android in Jenkins\u00a0 \u25baTesting a MongoDB with NodeJS, Mocha and Mongoose During the winter term 2017\/2018, we created an app called Take Me Home. The\u2026","rel":"","context":"In &quot;Mobile Apps&quot;","block_context":{"text":"Mobile Apps","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/interactive-media\/mobile-apps\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/tmh_admin_usermanagement_bearbeitet.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/tmh_admin_usermanagement_bearbeitet.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/tmh_admin_usermanagement_bearbeitet.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/tmh_admin_usermanagement_bearbeitet.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/tmh_admin_usermanagement_bearbeitet.png?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/tmh_admin_usermanagement_bearbeitet.png?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":1711,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2016\/11\/26\/snakes-exploring-pipelines-a-system-engineering-and-management-project\/","url_meta":{"origin":3314,"position":4},"title":"Snakes exploring Pipelines &#8211; A \u201cSystem Engineering and Management\u201d Project","author":"Yann Loic Philippczyk","date":"26. November 2016","format":false,"excerpt":"Part 0: Introduction This series of blog entries describes a student project focused on developing an application by using methods like pair programming, test driven development and deployment pipelines. Once upon a time, which was about one and a half months ago, an illustrious group of three students found together,\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"A python. (Because snakes. Not the language.) Source: https:\/\/rashmanly.files.wordpress.com\/2008\/10\/1439659.jpg","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2016\/11\/0_1-300x300.jpg?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":538,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2016\/04\/27\/an-emotinal-sneak-peak-into-continuous-integration\/","url_meta":{"origin":3314,"position":5},"title":"A sneak peak into Continuous Integration","author":"Mario Erazo","date":"27. April 2016","format":false,"excerpt":"What does the development of a software product involves? Is there more than programmers coding at their PCs and managers telling them what they want? What is the real meaning of \u2018release\u2019? In the old age of software development, a development team would have to deal with incredible amounts of\u2026","rel":"","context":"In &quot;DevOps&quot;","block_context":{"text":"DevOps","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/scalable-systems\/devops\/"},"img":{"alt_text":"Software development concept in tag cloud","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2016\/04\/stock-photo-25708797-software-development-concept-in-tag-cloud-1024x709.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2016\/04\/stock-photo-25708797-software-development-concept-in-tag-cloud-1024x709.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2016\/04\/stock-photo-25708797-software-development-concept-in-tag-cloud-1024x709.jpg?resize=525%2C300&ssl=1 1.5x"},"classes":[]}],"jetpack_sharing_enabled":true,"authors":[{"term_id":746,"user_id":188,"is_guest":0,"slug":"mm248","display_name":"Tobias Eberle, Marco Maisel, Tobias Staib, Mario Walz","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/a12752d216e492995fc5c8d7b5ae0bea6937c816b1c31526029e032a119b3041?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/3314","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/users\/188"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/comments?post=3314"}],"version-history":[{"count":22,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/3314\/revisions"}],"predecessor-version":[{"id":24751,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/3314\/revisions\/24751"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/media\/3462"}],"wp:attachment":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/media?parent=3314"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/categories?post=3314"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/tags?post=3314"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/ppma_author?post=3314"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}