DevOps tools at Touch4IT

We, at Touch4IT, utilize numerous tools to assist us with the development and deployment process. We have tried many more options, but the fewer tools we have to maintain, the more time we have for customer projects.
As we can see in the famous DevOps infinity loop, there are several key components involved in the process of product creation.
First, there is planning. For that, we use our customized Redmine. All the work that needs to be done is identified as issues, estimated, and assigned. Each employee of the company can view tasks assigned to them on their homepage and is notified about any changes and comments on these tasks.
Part of the initial planning of a project and the planning of visuals involves creating mockups, moodboards, clickable visual prototypes for customers, and later assets for programmers.
At the very beginning of a project, a meeting is held with several technological leaders and the project manager to select the technology to be used in the project. From there, programmers use it to create the project. We primarily use Node.js for API backends, the Symfony framework for CRMs, Drupal CMS for presentation websites, SPAs for more interactive web applications, Ionic for quick mobile prototypes, and native mobile development for Android and iOS. Over the time we also had projects on other PHP frameworks, Ruby, Java, C++, desktop applications, embedded systems, server platforms, just name it. I will focus more on the backend since it’s my primary area of expertise.
After an issue is finished, it should be verified. Is the proper verification “works on my machine” status? Absolutely not. Since we use Docker on both local machines and servers, there should not be major differences in behaviour between the local environment, the development server, the preproduction server, and the production server. But every project is like a living organism, and any malfunctioning organ is a problem at a global scale. Therefore, the system should be tested by a set of automatic tests of different types. There are unit tests that should cover parts of the logic, integration tests to verify how well the units are working together, UI tests to assess the overall appearance, and much more.
Unit and integration tests can be written in several frameworks. For Node.js, the most popular are Mocha, Jest, and Jasmine. We have used all of them, but most often we choose Mocha. It is also helpful to create coverage tests while using running these tests. To do so, built-in features come in handy or Istanbul is to be used when they are not available.
UI tests can automatically run the application in the pre-defined behaviour and produce some screenshots for developer or tester to evaluate. We have used Selenium and Puppeteer on our projects. For example, our own website is tested using Puppeteer on 8 resolutions, both desktop and mobile, landscape and portrait.
To maintain code quality, linters are set up to pop up warnings and errors both in the IDE and later in the CI/CD pipeline. For Node.js, we have used ESLint, XO, or Prettier. ESLint is supported in most IDEs out of the box, but it is relatively easy to upgrade IDE settings to work with the other two.
To build, test, and deploy the code, we use Gitlab CI. Gitlab claims to serve all steps of the DevOps lifecycle, and the truth is we use it for some of them. Builds and deployments are parametrized in it, so we can fully use configuration as a code and create infrastructure on demand using just one configuration file. Each complete application environment is running as a Docker stack.

Gitlab CI pipeline
Monitoring of running services is performed by Icinga2, which sends email notifications every time a service fails or recovers. Additionally, we monitor our infrastructure to ensure everything is functioning correctly and that no unauthorized mining is occurring on our CPUs.

Icinga2 service grid
After each release, we continually work on another one.
But wait, where is the finished product? Well, after every release. But it is never really finished until the client wants to withdraw the product from the market since there are always ways to improve the product and surpass rivals.