<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Michal Nowikowski</title>
    <description>The latest articles on Forem by Michal Nowikowski (@godfryd).</description>
    <link>https://forem.com/godfryd</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F623303%2F614bb2c2-7c1e-42a1-8dba-11bfd8f101ed.jpeg</url>
      <title>Forem: Michal Nowikowski</title>
      <link>https://forem.com/godfryd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/godfryd"/>
    <language>en</language>
    <item>
      <title>Kraken CI vs Other CI Systems</title>
      <dc:creator>Michal Nowikowski</dc:creator>
      <pubDate>Fri, 23 Jun 2023 05:23:40 +0000</pubDate>
      <link>https://forem.com/godfryd/kraken-ci-vs-other-ci-systems-4k8n</link>
      <guid>https://forem.com/godfryd/kraken-ci-vs-other-ci-systems-4k8n</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this section, three CI/CD tools will be compared with &lt;a href="https://kraken.ci"&gt;Kraken CI&lt;/a&gt;. These tools are among the most popular systems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.jenkins.io/"&gt;Jenkins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/features/actions"&gt;GitHub Actions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://about.gitlab.com/features/continuous-integration/"&gt;GitLab CI&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The most significant difference between Kraken CI and these three&lt;br&gt;
systems, as well as other CI/CD systems, is that they lack test result&lt;br&gt;
analytics. All three systems barely touch upon the topic and are only&lt;br&gt;
able to report results acquired during a build.&lt;/p&gt;

&lt;p&gt;Having only information about passes and failures, it is difficult to&lt;br&gt;
make a decision. It is not known if this failure has appeared&lt;br&gt;
before. Maybe it has been failing for several months, or perhaps it is&lt;br&gt;
sporadic and only fails from time to time. Alternatively, it could be&lt;br&gt;
a significant regression that requires urgent fixing.&lt;/p&gt;

&lt;p&gt;This requires either using other third-party tools that can fill this&lt;br&gt;
gap or developing custom scripts that can analyze the results and&lt;br&gt;
generate comprehensive reports.&lt;/p&gt;

&lt;p&gt;In contrast, Kraken CI focuses on this topic and excels in both&lt;br&gt;
execution and results analytics. It can show:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fixes and regressions,&lt;/li&gt;
&lt;li&gt;age of test result,&lt;/li&gt;
&lt;li&gt;stability of a test case,&lt;/li&gt;
&lt;li&gt;importance of negative test result,&lt;/li&gt;
&lt;li&gt;history of a test case in a table and in a chart,&lt;/li&gt;
&lt;li&gt;total results chart ie. pass ratio over time,&lt;/li&gt;
&lt;li&gt;pass ratio chart for selected subset of tests (e.g. tests results obtain on particular operating system).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Furthermore, it allows users to comment on test results, such as&lt;br&gt;
referencing a submitted bug or identifying the root cause, among other&lt;br&gt;
things.&lt;/p&gt;

&lt;p&gt;The details are presented in &lt;a href="https://dev.to/docs/test-results-basics"&gt;Test Results Basics&lt;/a&gt; and &lt;a href="https://dev.to/docs/test-results-tracking"&gt;Test Results Tracking&lt;/a&gt; of Kraken CI docs.&lt;/p&gt;

&lt;p&gt;But now let's discuss the differences between specific CI/CD systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Jenkins
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.jenkins.io/"&gt;Jenkins&lt;/a&gt; is an open-source on-premises automation server used for building, testing, and deploying software. It offers a broad range of plugins and integrations that support continuous integration and continuous delivery workflows. Jenkins is widely used in software development and is recognized for its flexibility and extensibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bright Side
&lt;/h3&gt;

&lt;p&gt;Jenkins has many powerful features, with one of the most prominent being its flexible and convenient method for defining pipelines using scripting code.&lt;/p&gt;

&lt;p&gt;Another very positive aspect of Jenkins is its community. The&lt;br&gt;
community, besides providing lots of blog posts and tutorials about Jenkins, also develops many plugins that greatly improve Jenkins.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dark Side
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Plugin Overload and Compatibility Issues
&lt;/h4&gt;

&lt;p&gt;Jenkins relies heavily on plugins for extended functionality. However,&lt;br&gt;
the sheer number of plugins available can make it challenging to&lt;br&gt;
select, manage, and maintain the right set of plugins. Plugin&lt;br&gt;
compatibility and stability issues can also arise, leading often to&lt;br&gt;
conflicts or performance problems.&lt;/p&gt;

&lt;p&gt;Kraken CI has a different approach. All of its features are built-in, which ensures compatibility and thorough cross testing. Users are encouraged to contribute directly to the core of Kraken CI. The only extensions available to users are &lt;a href="https://dev.to/docs/tools"&gt;tools&lt;/a&gt;, which enable the integration of third-party tools with Kraken CI. This is similar to third-party actions in GitHub Actions.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Bad User Experience in UI
&lt;/h4&gt;

&lt;p&gt;Jenkins' user interface (UI) is often criticized for being outdated&lt;br&gt;
and not user-friendly. There is a dichotomy between the classic UI and&lt;br&gt;
the Ocean Blue UI. Both show more or less the same things, but one is&lt;br&gt;
better in some areas, while the other is better in other areas. This&lt;br&gt;
leads to confusion.&lt;/p&gt;

&lt;p&gt;Many UI pages in Jenkins lack usability. Some areas are exceptionally&lt;br&gt;
bad, such as presenting logs. When the logs are very large, Jenkins&lt;br&gt;
shows them very slowly, especially if timestamps are&lt;br&gt;
enabled. Sometimes the UI freezes completely and cannot show&lt;br&gt;
anything. There is also a page called &lt;code&gt;Pipeline Steps&lt;/code&gt; that shows logs&lt;br&gt;
for each step separately, but there are so many internal steps&lt;br&gt;
presented that it is very hard to navigate.&lt;/p&gt;

&lt;p&gt;Presenting logs in Kraken CI is impressive. They are divided by&lt;br&gt;
default into steps that the user has defined in a workflow, or they&lt;br&gt;
are displayed in a flat format. Users can enable internal logs to see&lt;br&gt;
details, and loading logs is paged, so it is not necessary to load the&lt;br&gt;
entire log at once. However, it is still possible to download the&lt;br&gt;
entire log in raw format. Logs can be filtered by multiple fields and&lt;br&gt;
viewed at the individual step level, job level, run, flow, branch, or&lt;br&gt;
project levels. ANSI codes are colored, and there are many more&lt;br&gt;
features. Check out these two blog posts that present these features:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/blog/standing-out-logs-handling"&gt;Standing out Logs Handling&lt;/a&gt; and &lt;a href="https://dev.to/blog/further-logging-improvements"&gt;Further Logging Improvements&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are more examples like that. For instance, navigation, browsing&lt;br&gt;
test results, and so on. In Kraken CI, all of these aspects were&lt;br&gt;
thoughtfully reevaluated and engineered with user experience (UX) in&lt;br&gt;
mind.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Reliance on Groovy Scripting
&lt;/h4&gt;

&lt;p&gt;Jenkins pipelines, which are used to define CI/CD workflows, are&lt;br&gt;
written in Groovy scripting language. While this provides flexibility&lt;br&gt;
and extensibility, it requires from developers to learn and use Groovy,&lt;br&gt;
which can be an additional learning curve for teams not familiar with&lt;br&gt;
Groovy.&lt;/p&gt;

&lt;p&gt;In the case of Kraken CI, Python is used as the language to define workflows. According to the &lt;a href="https://www.tiobe.com/tiobe-index/"&gt;TIOBE Index&lt;/a&gt;, Python is ranked number 1, making it the most popular programming language,&lt;br&gt;
while Groovy is ranked 44th.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub Actions
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/features/actions"&gt;GitHub Actions&lt;/a&gt; is a powerful and flexible automation platform that allows you to streamline and optimize your software development workflows. With GitHub Actions, you can automate tasks, build, test, and deploy your applications directly from your GitHub repositories.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bright Side
&lt;/h3&gt;

&lt;p&gt;The biggest advantage of GH Actions is that it is integrated with&lt;br&gt;
GitHub repositories, and it is free up to a certain usage level. In&lt;br&gt;
addition, it allows for the extension of defined workflows by using&lt;br&gt;
community-developed actions. The number of available third-party&lt;br&gt;
actions is quite substantial.&lt;/p&gt;

&lt;p&gt;It is also possible to expand the computing power by connecting your&lt;br&gt;
own "self-hosted" machines to the pool of all machines. Therefore,&lt;br&gt;
workflows can run on both GitHub's machine cluster and on your own&lt;br&gt;
on-premises machines.&lt;/p&gt;

&lt;p&gt;Aside from that, GitHub Actions can do more than just CI/CD. Workflows&lt;br&gt;
can be triggered for various project events, such as a new issue being&lt;br&gt;
submitted, a new comment being added to an issue, a repository being&lt;br&gt;
forked, a release being created, and more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dark Side
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Poor, not Scalable UI/UX
&lt;/h4&gt;

&lt;p&gt;The user interface is cluttered and does not scale well for larger&lt;br&gt;
projects. When a workflow reuses other workflows, the job names become&lt;br&gt;
excessively long and are frequently truncated in multiple areas within&lt;br&gt;
the UI. This makes it difficult to identify which jobs we are&lt;br&gt;
currently viewing. The problem is further compounded when nested&lt;br&gt;
workflows are utilized.&lt;/p&gt;

&lt;p&gt;The UI also does not scale well for a larger number of jobs. If there&lt;br&gt;
are more than 30 jobs in a workflow, it becomes impossible to filter,&lt;br&gt;
sort, or list them in pages. Instead, all jobs are just presented to&lt;br&gt;
you in a flat list.&lt;/p&gt;

&lt;p&gt;One more weakness is the logs panel. Initially, it appears to be&lt;br&gt;
sleek. Nonetheless, if there are numerous steps and the logs are quite&lt;br&gt;
extensive, containing thousands of lines, then navigation becomes&lt;br&gt;
difficult. While jobs are in progress, the UI attempts to predict what&lt;br&gt;
to display, causing it to jump from one location to another, making it&lt;br&gt;
difficult to choose the correct step. Additionally, paging through the&lt;br&gt;
logs is not feasible. They are all displayed at once and are&lt;br&gt;
progressively loaded while scrolling down. This is a pretty&lt;br&gt;
ineffective method of finding the appropriate location in the log if&lt;br&gt;
the log contains hundreds of pages.&lt;/p&gt;

&lt;p&gt;Kraken's logging facilities in the UI were already described in the&lt;br&gt;
Jenkins section. In terms of UI scalability, this is one of Kraken's&lt;br&gt;
goals. It is designed from the ground up to handle multiple jobs, up&lt;br&gt;
to thousands or even tens of thousands. It provides means for&lt;br&gt;
filtering and sorting jobs, and presenting workflows, even those that&lt;br&gt;
are more complicated and involve multiple forks, in a more scalable&lt;br&gt;
way than GH Actions.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Reusability Is Quite Hard
&lt;/h4&gt;

&lt;p&gt;Initially, it seems that reusability is well supported in GH Actions&lt;br&gt;
workflow using third-party actions and reusable workflows. However,&lt;br&gt;
upon closer inspection, it is not as seamless as it&lt;br&gt;
appears. Externalizing some parts of the workflow into reusable&lt;br&gt;
actions or workflows can be quite tedious. If there is a need to&lt;br&gt;
locally reuse a fragment of code, one would like to use the YAML&lt;br&gt;
feature called anchors and aliases. Unfortunately, GH Actions does not&lt;br&gt;
support this feature.&lt;/p&gt;

&lt;p&gt;The situation becomes complicated if a user needs to maintain multiple&lt;br&gt;
repositories. Certain parts of workflows can be reused, but the&lt;br&gt;
framework of the workflow, including trigger definitions, global&lt;br&gt;
environment variables, and main jobs (which may reference reusable&lt;br&gt;
workflows), must be present in every repository. Ideally, one would&lt;br&gt;
like to fully externalize the entire workflow to a single repository&lt;br&gt;
and simply reference it in every other repository.&lt;/p&gt;

&lt;p&gt;Kraken allows for defining a workflow for particular repository in&lt;br&gt;
several way. The workflow definition can be stored&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;in Kraken server,&lt;/li&gt;
&lt;li&gt;in the same repository,&lt;/li&gt;
&lt;li&gt;in another repository.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the first case, the entire workflow definition resides in the&lt;br&gt;
Kraken server's database. It is then possible to link the workflow&lt;br&gt;
definition to any Git repository - whether it is the repository that&lt;br&gt;
needs to be built and tested or any other repository. This makes it&lt;br&gt;
easy to experiment with a workflow for any repository without the need&lt;br&gt;
to make changes. Later on, it is easy to transfer that workflow to the&lt;br&gt;
relevant repository. Furthermore, the entire workflow definition can&lt;br&gt;
be extracted to a separate repository and reused in multiple other&lt;br&gt;
repositories.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Cloud and Security
&lt;/h4&gt;

&lt;p&gt;GitHub Actions is a cloud-based CI/CD tool, which means that its&lt;br&gt;
reliability and availability are out of your control. If an outage&lt;br&gt;
occurs, the only thing left for you to do is wait until GitHub's team&lt;br&gt;
fixes their services. This may last from a few minutes to a few hours.&lt;/p&gt;

&lt;p&gt;Although GitHub Actions provides security features like access&lt;br&gt;
controls, secrets management, and vulnerability scanning, it may not&lt;br&gt;
fulfill the specific security or compliance requirements of all&lt;br&gt;
organizations or industries. Organizations with stringent security or&lt;br&gt;
compliance needs must evaluate GitHub Actions' security features&lt;br&gt;
carefully and ensure that they align with their requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitLab CI
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://about.gitlab.com/features/continuous-integration/"&gt;GitLab CI&lt;/a&gt; is a comprehensive DevOps platform that combines source code management, CI/CD pipelines, issue tracking, and more in a single&lt;br&gt;
integrated solution. It enables organizations to streamline their&lt;br&gt;
software development processes, promote collaboration, and achieve&lt;br&gt;
faster and more efficient delivery of high-quality software.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bright Side
&lt;/h3&gt;

&lt;p&gt;GitLab CI enables the definition of pipelines as code by using a&lt;br&gt;
YAML configuration file. This approach makes the CI/CD process&lt;br&gt;
version-controlled, easily replicable, and auditable. Infrastructure&lt;br&gt;
modifications, test scripts, and deployment steps can be defined&lt;br&gt;
alongside the code, promoting transparency and collaboration.&lt;/p&gt;

&lt;p&gt;Furthermore, GitLab is offered as software that can be installed&lt;br&gt;
on-premises, as well as a service that can be used in the cloud. This&lt;br&gt;
way, it combines the software aspect of Jenkins with the cloud service&lt;br&gt;
aspect of GitHub Actions in one solution. The choice belongs to the user.&lt;/p&gt;

&lt;p&gt;GitLab offers a wide range of features and integrations, with most of&lt;br&gt;
them only available in the Enterprise Edition. These features include&lt;br&gt;
code quality checks. Another strong aspect of GitLab is its&lt;br&gt;
reusability, as it is easy to reuse fragments of YAML definitions&lt;br&gt;
thanks to anchors in the language.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dark Side
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Too complex in advanced cases
&lt;/h4&gt;

&lt;p&gt;The learning curve for GitLab CI/CD is rather steep, and some poor&lt;br&gt;
design decisions have made configuring CI/CD pipelines in the&lt;br&gt;
&lt;code&gt;.gitlab-ci.yml&lt;/code&gt; file quite complex. The documentation is full of&lt;br&gt;
notes that certain aspects are not obvious, discouraged, or may&lt;br&gt;
behave unexpectedly. Furthermore, the issue tracker is filled with&lt;br&gt;
problems related to excessively complicated features.&lt;/p&gt;

&lt;p&gt;One of the problems is that a CI pipeline is triggered by all possible&lt;br&gt;
events. Then it is user role to explicitly exclude which jobs should&lt;br&gt;
be run or not for particular event. Sometimes it leads to situations&lt;br&gt;
that a pipeline is triggered multiple times. There is a dedicated&lt;br&gt;
section in the docs how to avoid such cases:&lt;br&gt;
&lt;a href="https://docs.gitlab.com/ee/ci/jobs/job_control.html#avoid-duplicate-pipelines"&gt;https://docs.gitlab.com/ee/ci/jobs/job_control.html#avoid-duplicate-pipelines&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All of these factors make developing more advanced workflows quite&lt;br&gt;
challenging.&lt;/p&gt;

&lt;p&gt;In contrast, Kraken is more deterministic. Workflows are triggered by&lt;br&gt;
user-indicated events, and it is clear why a given workflow was&lt;br&gt;
started - this information is presented in the UI.&lt;/p&gt;

</description>
      <category>krakenci</category>
      <category>devops</category>
      <category>cicd</category>
      <category>testing</category>
    </item>
    <item>
      <title>Hello Worlds in 22 Langs on Kraken CI</title>
      <dc:creator>Michal Nowikowski</dc:creator>
      <pubDate>Fri, 13 May 2022 04:45:04 +0000</pubDate>
      <link>https://forem.com/godfryd/hello-worlds-in-22-langs-on-kraken-ci-5fi2</link>
      <guid>https://forem.com/godfryd/hello-worlds-in-22-langs-on-kraken-ci-5fi2</guid>
      <description>&lt;p&gt;There is a new, quite funny workflow example for Kraken CI. It shows how to compile and run &lt;code&gt;Hello World&lt;/code&gt; programs in various programming languages, 22 languages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hello World Programs
&lt;/h3&gt;

&lt;p&gt;Every programmer knows what does &lt;code&gt;Hello World&lt;/code&gt; program looks like.&lt;/p&gt;

&lt;p&gt;Here is an example in C language:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello World&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But 22? These 22 can be seen in Kraken's repo on GitHub:&lt;br&gt;
&lt;a href="https://github.com/kraken-CI/hello-worlds" rel="noopener noreferrer"&gt;https://github.com/kraken-CI/hello-worlds&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Still, there are more languages with &lt;code&gt;Hello Worlds&lt;/code&gt;.&lt;br&gt;
The biggest collection can be found here:&lt;br&gt;
&lt;a href="http://helloworldcollection.de/" rel="noopener noreferrer"&gt;http://helloworldcollection.de/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These are just examples. In our case, they can be compiled and run. After downloading the repo you may run &lt;code&gt;./run.sh&lt;/code&gt; script providing the language folder, e.g.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./run.sh C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will display, compile and run a C example.&lt;/p&gt;

&lt;p&gt;In Kraken's case, there is defined a workflow that does it for us for each language. But first, we need to have systems with a compiler or a runtime for these languages. Docker to the rescue.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kraken Base Language Images
&lt;/h3&gt;

&lt;p&gt;For each language, there is prepared a Docker image. They are based on official images for these languages. For Kraken, they got some extras like Kraken Agent that is running using kraken user (not root).&lt;/p&gt;

&lt;p&gt;The list of all lang images is available in &lt;a href="https://dev.to/docs/docker-executor#language-images"&gt;the docs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Workflow
&lt;/h3&gt;

&lt;p&gt;The mentioned workflow can be found in &lt;a href="https://github.com/Kraken-CI/hello-worlds/blob/main/kraken-workflow.py" rel="noopener noreferrer"&gt;kraken-workflow.py&lt;/a&gt; file.&lt;/p&gt;

&lt;p&gt;In short, it looks as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;langs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;C&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gcc:11.3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;C++&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gcc:11.3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;C#&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mono:6.12&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="c1"&gt;# and more...
&lt;/span&gt;    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;lang_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lang_image&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;langs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hello world %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;lang_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;steps&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;git&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;checkout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://github.com/Kraken-CI/hello-worlds.git&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;branch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;main&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shell&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cmd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./run.sh %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;lang_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cwd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hello-worlds&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;environments&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;executor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;docker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;krakenci/%s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;lang_image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agents_group&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;all&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;config&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;default&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}]&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;parent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;triggers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;parent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;parameters&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;configs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jobs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you may notice, the list of jobs is built dynamically.  For each entry of the list of tuples (&lt;code&gt;lang-name&lt;/code&gt;, &lt;code&gt;docker-image&lt;/code&gt;), a job is defined with the same steps but various values for language and Docker image name. The lang name is passed to &lt;code&gt;./run.sh&lt;/code&gt; script in &lt;code&gt;shell&lt;/code&gt; step.  And Docker image name is used in the environments section, in the &lt;code&gt;system&lt;/code&gt; field. Such a list of jobs is then returned in the whole workflow definition. Each job will be run in parallel in separate Docker containers.&lt;/p&gt;

&lt;p&gt;The example of workflow execution is present in Kraken lab:&lt;br&gt;
&lt;a href="https://lab.kraken.ci/runs/5009/jobs" rel="noopener noreferrer"&gt;https://lab.kraken.ci/runs/5009/jobs&lt;/a&gt;. Check the workflow definitions in &lt;a href="https://lab.kraken.ci/branches/33" rel="noopener noreferrer"&gt;branch management page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This screenshot shows the execution of this workflow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuq7e83k2c7d0c4itpgv7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuq7e83k2c7d0c4itpgv7.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;This article shows how Kraken CI can build programs written in various languages. Kraken provides prepared Docker images for many languages. It is easy to define sophisticated workflows that dynamically define jobs that can be run in parallel. In the end, it is nice to observe the results of workflow execution in Kraken UI.&lt;/p&gt;

</description>
      <category>krakenci</category>
      <category>devops</category>
      <category>cicd</category>
    </item>
    <item>
      <title>MLOps with MLflow on Kraken CI</title>
      <dc:creator>Michal Nowikowski</dc:creator>
      <pubDate>Fri, 29 Apr 2022 11:55:24 +0000</pubDate>
      <link>https://forem.com/godfryd/mlops-with-mlflow-on-kraken-ci-lj1</link>
      <guid>https://forem.com/godfryd/mlops-with-mlflow-on-kraken-ci-lj1</guid>
      <description>&lt;p&gt;Besides building, testing and deploying, Kraken CI is also a pretty nice tool to build an &lt;a href="https://en.wikipedia.org/wiki/MLOps" rel="noopener noreferrer"&gt;MLOps&lt;/a&gt; pipeline. In this article, it will be shown how to leverage Kraken CI to build a CI workflow for machine learning using &lt;a href="https://mlflow.org/" rel="noopener noreferrer"&gt;MLflow&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kraken.ci/" rel="noopener noreferrer"&gt;Kraken CI&lt;/a&gt; is a new Continuous Integration tool. It is a modern, open-source, on-premise CI/CD system that is highly scalable and focused on testing. It is licensed under Apache 2.0 license. Its source code is available on &lt;a href="https://github.com/Kraken-CI/kraken" rel="noopener noreferrer"&gt;Kraken CI GitHub page&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  MLOps and MLflow
&lt;/h3&gt;

&lt;p&gt;MLOps is a set of practices that aims to build and maintain machine learning models in production reliably and efficiently. One of prominent tools in this area is &lt;a href="https://mlflow.org/" rel="noopener noreferrer"&gt;MLflow&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;MLflow is an open-source platform for managing the end-to-end machine learning lifecycle. It tackles four primary  functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tracking experiments to record and compare parameters and results (MLflow Tracking).&lt;/li&gt;
&lt;li&gt;Packaging ML code in a reusable, reproducible form to share
with other data scientists or transfer to production (MLflow Projects).&lt;/li&gt;
&lt;li&gt;Managing and deploying models from various ML libraries to a variety of model serving and inference platforms (MLflow Models).&lt;/li&gt;
&lt;li&gt;Providing a central model store to collaboratively manage the entire lifecycle of an MLflow Model, including model versioning, stage transitions, and annotations (MLflow Model Registry).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  MLflow in Kraken CI
&lt;/h3&gt;

&lt;p&gt;In the following sections, I will describe how to prepare a workflow in Kraken CI to train an ML model. This is an LSTM model that will predict stock prices based on historical data.&lt;/p&gt;

&lt;p&gt;The workflow will be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;pulling live stock data and preparing it for training (&lt;a href="https://github.com/Kraken-CI/mlflow-example/blob/master/download_raw_data.py" rel="noopener noreferrer"&gt;source 1&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://github.com/Kraken-CI/mlflow-example/blob/master/transform_data.py" rel="noopener noreferrer"&gt;source 2&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;performing the training (&lt;a href="https://github.com/Kraken-CI/mlflow-example/blob/master/train_model.py" rel="noopener noreferrer"&gt;source 3&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;storing model metrics in Kraken CI for charting&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The MLflow project is described in &lt;a href="https://github.com/Kraken-CI/mlflow-example/blob/master/MLproject" rel="noopener noreferrer"&gt;MLproject&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Workflow Definition
&lt;/h3&gt;

&lt;p&gt;The whole Kraken CI workload is defined &lt;a href="https://github.com/Kraken-CI/mlflow-example/blob/master/.kraken/one.py" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are 3 steps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nl"&gt;"steps"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"tool"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"git"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"checkout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://github.com/Kraken-CI/mlflow-example.git"&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"tool"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"cmd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/opt/conda/bin/mlflow run ."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"cwd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mlflow-example"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"timeout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1200&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"tool"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"values_collect"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"files"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"metrics.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nl"&gt;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"metrics"&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"params.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nl"&gt;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"params"&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"cwd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mlflow-example"&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Checkout mflow example project sources&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run the mlflow project ie. download data, prepare it, run a training and at the end store metrics about the trained model to metrics.json&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upload collected metrics together with hyperparameters from params.json to Kraken server&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The last step allows for charting accuracy and RMS of the model over builds.&lt;/p&gt;

&lt;p&gt;There is one more element defined in the workflow: the definition of execution environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nl"&gt;"environments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"system"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"krakenci/mlflow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"executor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"docker"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"agents_group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"all"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"config"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"default"&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we can notice the use of a pre-prepared image with mlflow. It is available in Docker hub: &lt;a href="https://hub.docker.com/r/krakenci/mlflow" rel="noopener noreferrer"&gt;krakenci/mlflow&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The whole example of workflow is present in Kraken lab:&lt;br&gt;
&lt;a href="https://lab.kraken.ci/branches/32/ci" rel="noopener noreferrer"&gt;https://lab.kraken.ci/branches/32/ci&lt;/a&gt;. Check the steps definitions in&lt;br&gt;
&lt;a href="https://lab.kraken.ci/branches/32" rel="noopener noreferrer"&gt;branch management page&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Execution and Monitoring
&lt;/h3&gt;

&lt;p&gt;Besides the workflow definition, Kraken UI also shows collected data&lt;br&gt;
and the charts drawn from this data:&lt;br&gt;
&lt;a href="https://lab.kraken.ci/test_case_results/595950" rel="noopener noreferrer"&gt;https://lab.kraken.ci/test_case_results/595950&lt;/a&gt;, the charts tab.&lt;/p&gt;

&lt;p&gt;The right chart shows value of &lt;code&gt;loss&lt;/code&gt; collected over time:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2d2pjwdqz4ee9jysihzv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2d2pjwdqz4ee9jysihzv.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;This article shows how Kraken CI can be used to build an MLOps pipeline.  The pipeline downloads raw data, prepares the data for training and then executes the training. The trained model metrics are collected and charted in Kraken UI at the end.&lt;/p&gt;

</description>
      <category>cicd</category>
      <category>devops</category>
      <category>mlops</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>What is Wrong with Your Testing?</title>
      <dc:creator>Michal Nowikowski</dc:creator>
      <pubDate>Mon, 21 Feb 2022 06:33:22 +0000</pubDate>
      <link>https://forem.com/godfryd/what-is-wrong-with-your-testing-2pim</link>
      <guid>https://forem.com/godfryd/what-is-wrong-with-your-testing-2pim</guid>
      <description>&lt;p&gt;As I observe, software projects mostly have nearly all the time 100% pass ratio. But I think this is not possible in reality, and we cheat ourselves. This may be due to a few reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a project was not that big, so it was not that hard to achieve 100%&lt;/li&gt;
&lt;li&gt;lots of failing or problematic tests were marked as skip, so they are not executed&lt;/li&gt;
&lt;li&gt;there was not many tests or no tests at all, i.e. tests coverage was non-existing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Generally, it is impossible to have a 100% pass ratio in more significant projects. If we look at a bug database, we find plenty of various issues. If there were tests that reveal them, then they would be failing.&lt;br&gt;
Maybe this is due to poor tools for tracking many tests and their results. This is an area where Kraken CI can help.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kraken.ci/"&gt;Kraken CI&lt;/a&gt; is a new Continuous Integration tool. It is a modern, open-source, on-premise CI/CD system that is highly scalable and focused on testing. It is licensed under Apache 2.0 license. Its source code is available on &lt;a href="https://github.com/Kraken-CI/kraken"&gt;Kraken CI GitHub page&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.istqb.org/"&gt;ISTQB&lt;/a&gt; defines several goals for testing. Two&lt;br&gt;
of them that are pretty important are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;To find defects and failures thus reduce the level of risk of
inadequate software quality.&lt;/li&gt;
&lt;li&gt;To provide sufficient information to stakeholders to allow them to
make informed decisions, especially regarding the level of quality of
the test object.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At first glance, these goals do not seem that hard. In small projects,&lt;br&gt;
it is pretty easy to achieve. Not many tests and not many code changes&lt;br&gt;
do not generate much work to analyze and reason.&lt;/p&gt;

&lt;p&gt;In the case of bigger projects, where testing is performed even several&lt;br&gt;
times a day, and where test content contains thousands or tens of&lt;br&gt;
thousands of test cases and where the number of combinations of&lt;br&gt;
environments (like operating systems and various types of hardware)&lt;br&gt;
and configurations is high, tracking and monitoring tests results&lt;br&gt;
gets really difficult.&lt;/p&gt;

&lt;p&gt;Proper tools must be employed to match these expectations that will&lt;br&gt;
automatically do much of this analytical work. Basic tests results&lt;br&gt;
reporting is not enough. More sophisticated analysis is required. The&lt;br&gt;
following sections present tools and features in Kraken CI that help in&lt;br&gt;
this area.&lt;/p&gt;

&lt;h2&gt;
  
  
  Result Changes in the Last Flow
&lt;/h2&gt;

&lt;p&gt;The basic approach to testing is observing results. The results&lt;br&gt;
include passes, failures, errors and sometimes some other types of&lt;br&gt;
status.  Looking at failures and errors allows for finding some&lt;br&gt;
problems, these lead to some debugging, root-casing, defect&lt;br&gt;
submission and fixing eventually.&lt;/p&gt;

&lt;p&gt;Observing a list of results from subsequent test sessions for&lt;br&gt;
subsequent product builds is not easy anymore. Again, there are some&lt;br&gt;
failures, but which were also present in the previous build and which&lt;br&gt;
are new regressions? In the case of small projects with a handful of&lt;br&gt;
tests, it is easy to go back to previous results and compare and&lt;br&gt;
manually find out what has changed. If there are tens or hundreds of&lt;br&gt;
failures, then a feature is needed to spot regression or fixes&lt;br&gt;
compared to the previous build.&lt;/p&gt;

&lt;h3&gt;
  
  
  New button
&lt;/h3&gt;

&lt;p&gt;In the case of Kraken CI, the table with test case results allows&lt;br&gt;
immediately for filtering and showing only these results that are&lt;br&gt;
regressions or fixes. For that purpose, a &lt;code&gt;New&lt;/code&gt; button shows only the&lt;br&gt;
test cases that changed the status in the current build compared to&lt;br&gt;
the previous one, i.e. shows "new", interesting results that require&lt;br&gt;
some attention.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xLnPNBXo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bxwfqipswke8q1p1cxcx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xLnPNBXo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bxwfqipswke8q1p1cxcx.png" alt="Filter results using New button" width="880" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The screenshot above shows the &lt;code&gt;New&lt;/code&gt; button and filtered results list.&lt;br&gt;
The two first test case results indicate a &lt;code&gt;regression&lt;/code&gt; and a &lt;code&gt;fix&lt;/code&gt;.&lt;br&gt;
This way, we can focus only on results that indicate some changes and&lt;br&gt;
ignore the failures that are there for weeks or months because they&lt;br&gt;
were not fixed yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Filter by Result Change
&lt;/h3&gt;

&lt;p&gt;It is possible to do more fine-grain filtering and select a particular&lt;br&gt;
change, e.g., &lt;code&gt;regression&lt;/code&gt; or &lt;code&gt;fix&lt;/code&gt;. For this purpose, there is a&lt;br&gt;
dropdown &lt;code&gt;Result Change&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gmgmuruc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/03k8wyy7kapuu4o0kgc6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gmgmuruc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/03k8wyy7kapuu4o0kgc6.png" alt="Image description" width="880" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The screenshot shows selecting &lt;code&gt;regressions&lt;/code&gt; only. So now we can focus&lt;br&gt;
only on a negative aspect of result changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Instability
&lt;/h3&gt;

&lt;p&gt;Even if only the regressions are presented, some tests are still not&lt;br&gt;
interesting or maybe interesting but for different reasons. These not&lt;br&gt;
interesting results are sporadic or unstable tests. Sometimes a test&lt;br&gt;
case passes, sometimes it fails. It changes its results status quite&lt;br&gt;
often. It can be concluded that this is all the time the same problem:&lt;br&gt;
either there is a bug in the product or in the test. If this is a&lt;br&gt;
known problem, it is better to filter out such results. This is&lt;br&gt;
possible by filtering results by their instability. There is a column&lt;br&gt;
called &lt;code&gt;Ins.&lt;/code&gt; (for instability) that shows a count of status changes&lt;br&gt;
in the last 10 builds. If it is equal to 9 it means that it was&lt;br&gt;
flipping from passed to failed, back and forth. So using a slider in&lt;br&gt;
the filtering pane, the instability can be narrowed to, e.g. 0-3&lt;br&gt;
range.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tjcaR7s4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cpj5rvyvhirjfrv9d9tl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tjcaR7s4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cpj5rvyvhirjfrv9d9tl.png" alt="Image description" width="880" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This screenshot shows results filtered by instability that is set to&lt;br&gt;
range 0-3.  Now it is visible in the &lt;code&gt;Instability&lt;/code&gt; column that it is 1&lt;br&gt;
i.e. the regression is new, and in the past 10 builds, the test cases&lt;br&gt;
were stable and passed.&lt;/p&gt;

&lt;p&gt;In the previous case and previous screenshot, this column was showing 9. Let's get back to this situation and click such a test case to check its details.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eSYDqP28--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dvm13pc7bcliqxhvpirm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eSYDqP28--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dvm13pc7bcliqxhvpirm.png" alt="Image description" width="880" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This screenshot presents a table with the historical results of the&lt;br&gt;
selected test case. At the top, there is the latest result in the&lt;br&gt;
first row. The &lt;code&gt;Result&lt;/code&gt; column shows result statuses. It is visible&lt;br&gt;
now that the status was constantly changing in the last results. The&lt;br&gt;
&lt;code&gt;Age&lt;/code&gt; column shows 0, i.e. every time the result was new. The&lt;br&gt;
&lt;code&gt;Instability&lt;/code&gt; column is all the time high. Such test case require some&lt;br&gt;
investigation and either fixing or removing from the test scope.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pTjFTups--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4123wz843mvuhak7ap2s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pTjFTups--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4123wz843mvuhak7ap2s.png" alt="Image description" width="880" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is possible to switch the view to a chart by selecting the second&lt;br&gt;
tab at the top of the page: &lt;code&gt;Charts&lt;/code&gt;. Here it is also visible that the&lt;br&gt;
results are pretty unstable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Relevancy
&lt;/h3&gt;

&lt;p&gt;Another way for getting important results is sorting them by&lt;br&gt;
&lt;code&gt;relevancy&lt;/code&gt;.  This is a metric built on properties of particular&lt;br&gt;
results. The higher the &lt;code&gt;relevancy&lt;/code&gt; is, the more important the result&lt;br&gt;
is.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xQRuzGq---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ohp03c3rulu2jlw19v6m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xQRuzGq---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ohp03c3rulu2jlw19v6m.png" alt="Image description" width="880" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This &lt;code&gt;relevancy&lt;/code&gt; score is calculated as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;+1&lt;/code&gt; if the result is not passed&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;+1&lt;/code&gt; if there is no comment attached to the result ie. it is not root-caused yet&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;+1&lt;/code&gt; if the result is failure&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;+1&lt;/code&gt; if the result was pretty stable (so it is the same over several test runs), ie. instability is &amp;lt;= 3&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;+1&lt;/code&gt; if the result is rather recent (the age is &amp;lt; 5) ie. ignore old failures&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;+1&lt;/code&gt; if this is a regression&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Max &lt;code&gt;relevancy&lt;/code&gt; is 6. So more interesting results are recent&lt;br&gt;
regressions that till now were pretty stable and are not root-caused&lt;br&gt;
yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Comments
&lt;/h3&gt;

&lt;p&gt;To remember the conclusions of investigation of given failure it is&lt;br&gt;
good to store them. For that purpose, there are test case comments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--00FU8mG5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xba76hjh42proi5vcem3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--00FU8mG5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xba76hjh42proi5vcem3.png" alt="Image description" width="880" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are two columns on the right side of the results table related&lt;br&gt;
to comments. Clicking a given cell allows for entering a comment a&lt;br&gt;
state. The state may indicate if the problem has been root-cased or&lt;br&gt;
not. This way, the next we get the results for this same test case, we&lt;br&gt;
will already see the comment and conclusions we made previously.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding Changes in the Past
&lt;/h2&gt;

&lt;p&gt;It is hard to spot regressions if the results are not analyzed&lt;br&gt;
immediately after tests execution. The failures are getting stable, so&lt;br&gt;
it is not visible as regressions anymore. To find such results,&lt;br&gt;
results that were regressions during, e.g. last week, we need to&lt;br&gt;
filter by age. Age allows filtering results that are not recent but&lt;br&gt;
happened in the near past. If, e.g. we set age to 1-5 range, then the&lt;br&gt;
test case results table will show results that persist (are stable in&lt;br&gt;
the last 1-5 runs) the change happened in the previous 1-5&lt;br&gt;
executions. This allows for filtering out recent failures (because&lt;br&gt;
e.g. we already have analyzed them) and very old, stable results&lt;br&gt;
(because e.g. no one cares about them anymore).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MWTgQWnG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tocskzylb188nruiq3e5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MWTgQWnG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tocskzylb188nruiq3e5.png" alt="Image description" width="880" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This screen shows results filtered by age from 2 (since 2 builds ago)&lt;br&gt;
to let's say infinity. The table at the bottom contains now only a&lt;br&gt;
handful of results with age 2 or 3. This way, we can find not current&lt;br&gt;
regressions but still quite recent.&lt;/p&gt;

</description>
      <category>cicd</category>
      <category>testing</category>
      <category>devops</category>
    </item>
    <item>
      <title>Tests Basics in Kraken CI</title>
      <dc:creator>Michal Nowikowski</dc:creator>
      <pubDate>Mon, 24 Jan 2022 16:14:31 +0000</pubDate>
      <link>https://forem.com/godfryd/tests-basics-in-kraken-ci-1lne</link>
      <guid>https://forem.com/godfryd/tests-basics-in-kraken-ci-1lne</guid>
      <description>&lt;p&gt;In the last few articles there was a lot about autoscaling. Now let's get back to the core of Kraken CI: testing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kraken.ci/"&gt;Kraken CI&lt;/a&gt; is a new Continuous Integration tool. It is a modern, open-source, on-premise CI/CD system that is highly scalable and focused on testing. It is licensed under Apache 2.0 license. Its source code is available on &lt;a href="https://github.com/Kraken-CI/kraken"&gt;Kraken CI GitHub page&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Testing in Kraken CI is much more organized that it is in e.g. Jenkins. Testing is planned in branches and high level view on results is also presented for branches. Then, it is possible to dig deeper into runs, jobs and particular test case results. More details about all this can be found in the following sections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Branch Results
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Branch Results&lt;/code&gt; page presents high-level information about the flows and runs of a given branch. It organizes flows in rows. The top row contains the latest flow. Each flow row contains a list of boxes. Each box contains information about a run of a given stage. The order of boxes with runs is chronological according to their start time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0f8wgIo---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fc0fqt18wt0rbrcnp1cf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0f8wgIo---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fc0fqt18wt0rbrcnp1cf.png" alt="Image description" width="880" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Run Box
&lt;/h2&gt;

&lt;p&gt;The color of the run box indicates the final status of the run:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;red: one or more jobs finished with an error&lt;/li&gt;
&lt;li&gt;yellow: no errors in jobs but some test results failed or there are issues discovered in the code&lt;/li&gt;
&lt;li&gt;green: all jobs finished without error and there are no failures in tests and no issues in the code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A run box contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;data about execution: total number of scheduled jobs, number of erred jobs, etc.&lt;/li&gt;
&lt;li&gt;summary of testing: pass ratio, total, regressions and fixes counts, etc&lt;/li&gt;
&lt;li&gt;issues summary: total number of discovered issues, number of new issues&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example 1:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1cjdSzHF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/868lkpn3cckyvbmtvrua.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1cjdSzHF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/868lkpn3cckyvbmtvrua.png" alt="Image description" width="880" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This run has 1 successful job that reported tests results. There were 100 test cases run, where 16 did not pass, so the pass ratio is 16%. There were detected 15 regressions and 13 fixes. There are failures, so the box is yellow.&lt;/p&gt;

&lt;p&gt;Example 2:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q0MQK9ex--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/es9st56u1tj0wo7dvglx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q0MQK9ex--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/es9st56u1tj0wo7dvglx.png" alt="Image description" width="391" height="136"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This run has 4 jobs with no errors. Some of them reported tests results, the other ones reported issues. There were 17 test cases run, all passed, so the pass ratio is 100%. There were detected 15 issues in the code. There are issues, so the box is yellow.&lt;/p&gt;

&lt;p&gt;Example 3:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f9-UNcR5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9nst92eu1tu50re0xjpn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f9-UNcR5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9nst92eu1tu50re0xjpn.png" alt="Image description" width="389" height="116"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This run has 2 jobs with no errors. In the reported tests results, there are 100% passed test cases. No failures and no issues, so the box is green.&lt;/p&gt;

&lt;p&gt;Example 4:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sOzC6l7W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/34iom00rf1yfj00a97vn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sOzC6l7W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/34iom00rf1yfj00a97vn.png" alt="Image description" width="392" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This run has 4 jobs with 1 error. All tests reported are passed but there could be not reported tests due to errors in job execution. There were detected 6 issues in the code. There is one erred job so the box is red.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Case Results Table
&lt;/h2&gt;

&lt;p&gt;A job that performs testing reports test results. The test results are visible on a &lt;code&gt;Run Results&lt;/code&gt; page, in &lt;code&gt;Test Results&lt;/code&gt; tab. They are presented in a table.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1zVHGky_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o05kmlzpmxaekmt4i5v3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1zVHGky_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o05kmlzpmxaekmt4i5v3.png" alt="Image description" width="880" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The table presents test case results in each row. They contain details of the test case result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the result status&lt;/li&gt;
&lt;li&gt;a name of the test case&lt;/li&gt;
&lt;li&gt;job name and ID&lt;/li&gt;
&lt;li&gt;age, instability and relevancy&lt;/li&gt;
&lt;li&gt;values&lt;/li&gt;
&lt;li&gt;execution environment: system, agent group and actual agent and config&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Kraken, a test case result besides status can contain values. Values are pairs: attribute and its value. They are also a result of a test case but hold numbers. They can hold e.g. performance data or anything similar to performance. These values are tracked over time. Kraken can draw charts of values and do more things with them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filtering Test Case Results
&lt;/h2&gt;

&lt;p&gt;It is possible to filter test results by various attributes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;by &lt;code&gt;Results Status&lt;/code&gt; ie. &lt;code&gt;Passed&lt;/code&gt;, &lt;code&gt;Failed&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;by &lt;code&gt;Result Change&lt;/code&gt; ie. &lt;code&gt;Fixes&lt;/code&gt;, &lt;code&gt;Regressions&lt;/code&gt;, &lt;code&gt;New&lt;/code&gt; and &lt;code&gt;No Changes&lt;/code&gt;; the change is determined between the current result and the previous result from previous run&lt;/li&gt;
&lt;li&gt;by &lt;code&gt;Age&lt;/code&gt; where age is a number of previous runs with the same result as in the current run; so e.g. age 0 means that in the previous run test case had a different result than it has now (so these are regressions and fixes); age 1 means that the current run and the previous run has the same result but the result before the previous one is different&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;New&lt;/code&gt; is a shortcut to set &lt;code&gt;Age&lt;/code&gt; between 0 and 0, ie. show changes that happened in the last run (fixes + regressions)&lt;/li&gt;
&lt;li&gt;by &lt;code&gt;Instability&lt;/code&gt; where instability is a count of result status changes in the last 10 runs; if this is 0 then in the last 10 runs test case has the same result (it was pretty stable); if this is 10 then it means that in every run of the last 10 runs the status was changing compared to the previous one (it was very unstable)&lt;/li&gt;
&lt;li&gt;by &lt;code&gt;Test Case&lt;/code&gt; name&lt;/li&gt;
&lt;li&gt;by &lt;code&gt;Job&lt;/code&gt; name of ID&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example 1:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dC4m1LAk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i3l75qg8ckcsxdvluyrk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dC4m1LAk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i3l75qg8ckcsxdvluyrk.png" alt="Image description" width="880" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Filtering by &lt;code&gt;Result Changes&lt;/code&gt;: show only regressions. Regression means a change from non-passed status to passed status.&lt;/p&gt;

&lt;p&gt;Example 2:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HtasxJT7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cs2f3i376f51g1w5gwxv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HtasxJT7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cs2f3i376f51g1w5gwxv.png" alt="Image description" width="880" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Filtering by &lt;code&gt;Result Status&lt;/code&gt; and &lt;code&gt;Result Changes&lt;/code&gt;: show only failures that are regressions.&lt;/p&gt;

&lt;p&gt;Example 3:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7XaZIt6S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1lj63tjm8mcdvptmujso.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7XaZIt6S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1lj63tjm8mcdvptmujso.png" alt="Image description" width="880" height="305"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Filtering by &lt;code&gt;Age&lt;/code&gt;: show only results in age between 2 and 3.&lt;/p&gt;

&lt;p&gt;Example 4:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XOgvCK_j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jbgf6rn1lt3q3quph4ze.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XOgvCK_j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jbgf6rn1lt3q3quph4ze.png" alt="Image description" width="880" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Filtering by &lt;code&gt;Instability&lt;/code&gt;: show only results that have instability greater than 7 i.e. very unstable test cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sorting Test Case Results
&lt;/h2&gt;

&lt;p&gt;Test case results can be sorted. This can be done using several columns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;li&gt;result&lt;/li&gt;
&lt;li&gt;change&lt;/li&gt;
&lt;li&gt;age&lt;/li&gt;
&lt;li&gt;instability&lt;/li&gt;
&lt;li&gt;relevancy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ceSAGwIy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hpp797b3aquycxgo4m86.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ceSAGwIy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hpp797b3aquycxgo4m86.png" alt="Image description" width="880" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By default results are sorted by test case name.&lt;/p&gt;

&lt;p&gt;One of the most important sorting order is by &lt;code&gt;Relevancy&lt;/code&gt;.&lt;br&gt;
Relevancy is estimated according to this rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;0 is initial&lt;/li&gt;
&lt;li&gt;+1 for not passed&lt;/li&gt;
&lt;li&gt;+1 for not root caused problem&lt;/li&gt;
&lt;li&gt;+1 for failure&lt;/li&gt;
&lt;li&gt;+1 for instability &amp;lt;= 3&lt;/li&gt;
&lt;li&gt;+1 for age &amp;lt; 5&lt;/li&gt;
&lt;li&gt;+1 for regression&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This way the most relevant results get the highest score. They need an&lt;br&gt;
attention.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---hgxCFBW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i5yopmwj3rqtfhvqol13.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---hgxCFBW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i5yopmwj3rqtfhvqol13.png" alt="Image description" width="880" height="211"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Comments
&lt;/h2&gt;

&lt;p&gt;In the test case results table, it is possible to add sticky comments to test case results. When a new failure is spotted, a comment stating, e.g. the reason for the failure or link to a bug in a bug tracker may be added.&lt;/p&gt;

&lt;p&gt;To add a comment, click on the cell of a particular test case result in the &lt;code&gt;Comment&lt;/code&gt; or &lt;code&gt;Comment State&lt;/code&gt; columns.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BfX8z9AQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g3jtq20mx02fck86mysu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BfX8z9AQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g3jtq20mx02fck86mysu.png" alt="Image description" width="880" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will reveal a dialog box that shows a form for introducing new comment and a history of previous comments related to this test case.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--waK2PNcx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zfom9d9milv36tkloj2e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--waK2PNcx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zfom9d9milv36tkloj2e.png" alt="Image description" width="880" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each comment has a state. It can be one of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;new&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;investigating&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bug in product&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bug in test&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The state allows concluding quickly if given failure has been analyzed and it is known where is the root cause and what needs to be fixed or if the failure still requires some investigation.&lt;/p&gt;

&lt;p&gt;If a failure is root-caused, then its relevancy is decreased by 1.&lt;/p&gt;

&lt;p&gt;If the failure persists in the subsequent test runs, the added comment is still presented next to the new results. If new facts about the failure are revealed, you may extend the comment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Case History
&lt;/h2&gt;

&lt;p&gt;Each test case has its history of results. In the table with test case results a link under the test case name leads to a page dedicated to the given test case. This page presents a table with the historical results of the test case.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---Pa-H8d0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/be4zpq0nte2zyekkojgc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---Pa-H8d0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/be4zpq0nte2zyekkojgc.png" alt="Image description" width="880" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is another tab called &lt;code&gt;Charts&lt;/code&gt; that shows these results on charts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8TKZjGp2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ijft4x6np4ten69wd18.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8TKZjGp2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ijft4x6np4ten69wd18.png" alt="Image description" width="880" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The left chart shows the history of result status. The right one presents the history of values in time. Error bars are shown if there were run multiple iterations and there were reported multiple values for a given attribute.&lt;/p&gt;

</description>
      <category>cicd</category>
      <category>testing</category>
      <category>devops</category>
    </item>
    <item>
      <title>Autoscaling CI on Kubernetes in Kraken CI</title>
      <dc:creator>Michal Nowikowski</dc:creator>
      <pubDate>Thu, 30 Dec 2021 14:04:44 +0000</pubDate>
      <link>https://forem.com/godfryd/autoscaling-ci-on-kubernetes-in-kraken-ci-2j84</link>
      <guid>https://forem.com/godfryd/autoscaling-ci-on-kubernetes-in-kraken-ci-2j84</guid>
      <description>&lt;p&gt;&lt;a href="https://kraken.ci/" rel="noopener noreferrer"&gt;Kraken CI&lt;/a&gt; is a new Continuous Integration tool. It is a modern, open-source, on-premise CI/CD system that is highly scalable and focused on testing. It is licensed under Apache 2.0 license. Its source code is available on &lt;a href="https://github.com/Kraken-CI/kraken" rel="noopener noreferrer"&gt;Kraken CI GitHub page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This tutorial is the fifth installment of the series of articles about Kraken CI. &lt;a href="https://dev.to/godfryd/kraken-ci-new-kid-on-the-ci-block-4imo"&gt;Part 1, Kraken CI, New Kid on the CI block&lt;/a&gt;, presented the installation of Kraken. The second part covered &lt;a href="https://dev.to/godfryd/your-first-workflow-in-kraken-ci-43hb"&gt;how to prepare a workflow for a simple Python project&lt;/a&gt;. The 3rd one was about &lt;a href="https://dev.to/godfryd/autoscaling-ci-with-kraken-ci-jij"&gt;autoscaling on AWS and Azure&lt;/a&gt;. The last part was introducing to &lt;a href="https://dev.to/godfryd/webhooks-in-kraken-ci-for-github-gitlab-and-gitea-4878"&gt;Webhooks in Kraken CI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This time we would like to show the latest feature that was developed in Kraken CI: deploying Kraken CI and autoscaling in Kubernetes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;One of the methods of deploying Kraken CI is installing it into Kubernetes cluster. Kraken CI is natively divided into several services packed in Docker images so they can be nicely laid out in the cluster. The other aspect is running Kraken jobs. In this case, they are run in containers natively scheduled onto Kubernetes nodes.&lt;/p&gt;

&lt;p&gt;This guide shows how to install and configure Kraken CI in Kubernetes to leverage its potential.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-requisites
&lt;/h2&gt;

&lt;p&gt;Several things are required to install Kraken CI in Kubernetes using Helm. In short:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://kubernetes.io" rel="noopener noreferrer"&gt;Kubernetes&lt;/a&gt; cluster and kubectl tool&lt;/li&gt;
&lt;li&gt;&lt;a href="https://helm.sh" rel="noopener noreferrer"&gt;Helm tool&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Helm is used to deploy several Kraken services and expose them to an external network. These Kraken services are described in &lt;a href="https://kraken.ci/docs/architecture" rel="noopener noreferrer"&gt;Architecture chapter&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kubernetes Clusters
&lt;/h2&gt;

&lt;p&gt;There are multiple ways for setting up a Kubernetes cluster. One of the easiest ones that is most often used for experimenting is Minikube. There are also managed clusters like EKS (Elastic Kubernetes Service) in AWS.&lt;/p&gt;

&lt;p&gt;This manual will show how to install Kraken CI in Minikube but the steps are similar for other Kubernetes environments as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install in Minikube
&lt;/h2&gt;

&lt;p&gt;First, download minikube from &lt;a href="https://minikube.sigs.k8s.io/docs/" rel="noopener noreferrer"&gt;https://minikube.sigs.k8s.io/docs/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And then create a cluster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;minikube start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you may install Kraken CI, but first, let's add a repo with Kraken Helm charts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;helm repo add kraken-ci https://kraken.ci/helm-repo/charts
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;helm repo update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and now install Kraken CI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;helm upgrade &lt;span class="nt"&gt;--install&lt;/span&gt; &lt;span class="nt"&gt;--create-namespace&lt;/span&gt; &lt;span class="nt"&gt;--namespace&lt;/span&gt; kraken &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="go"&gt;  --debug --wait \
  --set access.method='external-ips' \
  --set access.external_ips={`minikube ip`} \
  kraken-ci kraken-ci/kraken-ci
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command actually upgrades Kraken CI if it is already installed but if it was not yet installed, then it installs it.&lt;/p&gt;

&lt;p&gt;More details about using Helm to install Kraken CI can be found in &lt;a href="https://kraken.ci/docs/install-helm" rel="noopener noreferrer"&gt;installation docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When everything completes successfully, then at the end of the whole output there should be presented short instruction about getting the URL of Kraken service like that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NOTES:
Get the application URL by running these commands:
  export NODE_PORT=$(kubectl get --namespace kk-1 -o jsonpath="{.spec.ports[0].port}" services ui)
  export NODE_IP=$(kubectl get nodes --namespace kk-1 -o jsonpath="{.items[0].status.addresses[0].address}")
  echo http://$NODE_IP:$NODE_PORT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you may check if Kraken is working by visiting the URL&lt;br&gt;
given by this code and by checking if Kubernetes is running Kraken's services with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;kubectl get all -n kraken
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will show Kraken's pods, services, deployments and replica sets.&lt;/p&gt;

&lt;p&gt;At this moment, Kraken CI should be operating. Please visit the website on the URL presented above. You should see a login page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F02ucrkqi4ehltwaslgde.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F02ucrkqi4ehltwaslgde.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter &lt;code&gt;admin&lt;/code&gt; for Username and &lt;code&gt;admin&lt;/code&gt; for Password.&lt;/p&gt;

&lt;h2&gt;
  
  
  Global Settings
&lt;/h2&gt;

&lt;p&gt;First, let's set some global settings. In Web UI, click &lt;code&gt;Settings&lt;/code&gt; in the top menu bar.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;General&lt;/code&gt; tab, fill the following fields:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffoqyun00s2tq2mc8zwqz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffoqyun00s2tq2mc8zwqz.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Kraken Server URL&lt;/code&gt; - an URL with a port of the server that is visible inside the Kubernetes cluster&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;MinIO/S3 Address&lt;/code&gt; - the IP address and port of Kraken's internal artifacts storage address&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Clickhouse Proxy Address&lt;/code&gt; - the IP address and port of Kraken's internal logs storage address&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In all these cases minikube IP address can be used. It can be obtained using &lt;code&gt;minikube ip&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;Having set the &lt;code&gt;General&lt;/code&gt; settings, let's move to the &lt;code&gt;Cloud&lt;/code&gt; tab.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F67celu7debyy9ve1pwcd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F67celu7debyy9ve1pwcd.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, please move to Kubernetes section and set only the &lt;code&gt;Namespace&lt;/code&gt; field to the value that was provided in &lt;code&gt;helm&lt;/code&gt; command above (if it was not changed, then it should be &lt;code&gt;kraken&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;API Server URL&lt;/code&gt; field must be empty as Kraken CI is installed inside Kubernetes and it knows where the API server is.&lt;/p&gt;

&lt;p&gt;After saving the settings, check if connectivity is ok using &lt;code&gt;Test Kubernetes Access&lt;/code&gt; button.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration in Agents Groups
&lt;/h2&gt;

&lt;p&gt;After setting global settings, it is possible now to configure aspects of spawning Kubernetes pods for Kraken jobs. This can be done on Kraken -&amp;gt; Agents -&amp;gt; Groups page.  Let's create a new Agents Group by clicking &lt;code&gt;Add New Group&lt;/code&gt; button and naming it &lt;code&gt;k8s&lt;/code&gt;. The newly created group's details will be presented on a separate tab. On this tab, there is a section &lt;code&gt;Agents Deployment&lt;/code&gt; - select Kubernetes. In this&lt;br&gt;
case, there is only one field to set: &lt;code&gt;Instances Limit&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fscnghx5ssyot08qmhdnb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fscnghx5ssyot08qmhdnb.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This limit value will not allow having more running pods than it - here 5.&lt;/p&gt;
&lt;h2&gt;
  
  
  Job Definition
&lt;/h2&gt;

&lt;p&gt;Now, to use the defined &lt;code&gt;k8s&lt;/code&gt; Agents Group, we need to prepare a project with a branch and a stage. More details about that can be found in &lt;a href="https://kraken.ci/docs/guide-intro" rel="noopener noreferrer"&gt;Introductory Guide&lt;/a&gt;. So let's concentrate now on defining a job.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"parent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"root"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"triggers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"parent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;True&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"configs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"jobs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"timeout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"steps"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"tool"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"cmd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo 'hello world'"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"environments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"system"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ubuntu:20.04"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"agents_group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"k8s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"config"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"default"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is not much difference compared to regular Kraken jobs. The job has a defined environments section where we are pointing to our &lt;code&gt;k8s&lt;/code&gt; Agents Group. In the case of &lt;code&gt;system&lt;/code&gt; field here, we have a &lt;code&gt;Ubuntu:20.04&lt;/code&gt; Docker image.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run
&lt;/h2&gt;

&lt;p&gt;Now when a job is assigned to an agents group with configured Agents Deployment then a new pod will be spawned for that job if agents are not available in the Kraken.&lt;/p&gt;

&lt;p&gt;Let's change the view to Branch Results view and trigger a new flow by clicking &lt;code&gt;Run Flow&lt;/code&gt; button. On the run page, the list of jobs shows our AWS job:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F40eu3o69rr8str40tdt4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F40eu3o69rr8str40tdt4.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>autoscaling</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Webhooks in Kraken CI for GitHub, GitLab and Gitea</title>
      <dc:creator>Michal Nowikowski</dc:creator>
      <pubDate>Mon, 15 Nov 2021 11:49:39 +0000</pubDate>
      <link>https://forem.com/godfryd/webhooks-in-kraken-ci-for-github-gitlab-and-gitea-4878</link>
      <guid>https://forem.com/godfryd/webhooks-in-kraken-ci-for-github-gitlab-and-gitea-4878</guid>
      <description>&lt;p&gt;&lt;a href="https://kraken.ci/"&gt;Kraken CI&lt;/a&gt; is a new Continuous Integration tool. It is a modern, open-source, on-premise CI/CD system that is highly scalable and focused on testing. It is licensed under Apache 2.0 license. Its source code is available on &lt;a href="https://github.com/Kraken-CI/kraken"&gt;Kraken CI GitHub page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This tutorial is the third installment of the series of articles about Kraken CI. &lt;a href="https://dev.to/godfryd/kraken-ci-new-kid-on-the-ci-block-4imo"&gt;Part 1, Kraken CI, New Kid on the CI block&lt;/a&gt;, presented the installation of Kraken. The second part covered &lt;a href="https://dev.to/godfryd/your-first-workflow-in-kraken-ci-43hb"&gt;how to prepare a workflow for a simple Python project&lt;/a&gt;. The last one was about &lt;a href="https://dev.to/godfryd/autoscaling-ci-with-kraken-ci-jij"&gt;autoscaling on AWS and Azure&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This time we would like to show the latest feature that was developed in Kraken CI: webhooks for GitHub, GitLab and Gitea.&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro to Webhooks
&lt;/h2&gt;

&lt;p&gt;Kraken CI allows triggering a flow of a branch in a project using a&lt;br&gt;
webhook in a Git hosting service. A push to a regular branch e.g. main&lt;br&gt;
branch or to a branch associated with a pull or a merge request will cause&lt;br&gt;
a Git hosting service to call a webhook exposed by Kraken CI. To make&lt;br&gt;
it happen a webhook URL and a secret have to be stored in a project&lt;br&gt;
settings in Git hosting service.&lt;/p&gt;

&lt;p&gt;Currenty there are support the following Git hosting services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub&lt;/li&gt;
&lt;li&gt;GitLab&lt;/li&gt;
&lt;li&gt;Gitea&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following guide shows how to configure webhooks: 1) how to enable&lt;br&gt;
them in a project in Kraken CI and then 2) how to set a webhook URL and&lt;br&gt;
a secret in Git hosting service. In the end, the usage of webhooks&lt;br&gt;
will be presented by doing a push to Git repository.&lt;/p&gt;
&lt;h2&gt;
  
  
  Enable Webhooks in a Project
&lt;/h2&gt;

&lt;p&gt;In Kraken CI go to your project page and switch to &lt;code&gt;WebHooks&lt;/code&gt;&lt;br&gt;
tab. There are available webhooks for several Git hosting services.&lt;br&gt;
Enable the one that you are using for hosting your Git repository.&lt;br&gt;
Enabled webhooks show an actuall webhook URL and a secret. These&lt;br&gt;
information should be copied and set in you webhooks setting page in&lt;br&gt;
your Git hosting service.&lt;/p&gt;


&lt;h2&gt;
  
  
  Set Webhook URL in Git Hosting Service
&lt;/h2&gt;

&lt;p&gt;The following sections show how to set webhook URL to Kraken CI, a&lt;br&gt;
secret that is used to authenticate and they show which event types&lt;br&gt;
should be selected that will trigger a new flow in you Kraken CI&lt;br&gt;
project.&lt;/p&gt;
&lt;h3&gt;
  
  
  GitHub
&lt;/h3&gt;



&lt;p&gt;The arrows on the picture above indicate where the webhook URL and the&lt;br&gt;
secret from your Kraken CI project should be pasted on your GitHub&lt;br&gt;
repository webhooks settings page. In case of GitHub two event types&lt;br&gt;
should be selected:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Pull Requests&lt;/code&gt; - they will trigger DEV flows in you Kraken CI
project, in a branch indicated in the event&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Pushes&lt;/code&gt; - they will trigger CI flows in you Kraken CI project,
in a branch indicated in the event&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  GitLab
&lt;/h3&gt;



&lt;p&gt;The arrows on the picture above indicate where the webhook URL and the&lt;br&gt;
secret from your Kraken CI project should be pasted on your GitLab&lt;br&gt;
repository webhooks settings page. In case of GitLab two event&lt;br&gt;
types should be selected:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Push events&lt;/code&gt; - they will trigger CI flows in you Kraken CI
project, in a branch indicated in the event&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Merge Request events&lt;/code&gt; - they will trigger DEV flows in you Kraken CI project,
in a branch indicated in the event&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Gitea
&lt;/h3&gt;



&lt;p&gt;The arrows on the picture above indicate where the webhook URL and the&lt;br&gt;
secret from your Kraken CI project should be pasted on your Gitea&lt;br&gt;
repository webhooks settings page. In case of GitLab two event&lt;br&gt;
types should be selected:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Push&lt;/code&gt; - they will trigger CI flows in you Kraken CI project,
in a branch indicated in the event&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Pull Request&lt;/code&gt; and &lt;code&gt;Pull Request Synchronized&lt;/code&gt; - they will trigger
DEV flows in you Kraken CI project, in a branch indicated in the event&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Trigger a Flow
&lt;/h2&gt;

&lt;p&gt;Now, in your a folder with source code repository you may invoke git push command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should trigger a new flow in CI branch in you Kraken CI project.&lt;/p&gt;

&lt;p&gt;If you create a new branch, do some commits to it, then push this new&lt;br&gt;
branch, and then create a pull request (PR) or merge request (MR) in&lt;br&gt;
your Git hosting service UI, then all this will trigger a new DEV flow&lt;br&gt;
that is a base branch for the PR or MR:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; my-branch
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git push &lt;span class="nt"&gt;--set-upstream&lt;/span&gt; origin my-branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it!&lt;/p&gt;

</description>
      <category>ci</category>
      <category>cd</category>
      <category>devops</category>
      <category>github</category>
    </item>
    <item>
      <title>Autoscaling CI with Kraken CI</title>
      <dc:creator>Michal Nowikowski</dc:creator>
      <pubDate>Mon, 19 Jul 2021 05:41:40 +0000</pubDate>
      <link>https://forem.com/godfryd/autoscaling-ci-with-kraken-ci-jij</link>
      <guid>https://forem.com/godfryd/autoscaling-ci-with-kraken-ci-jij</guid>
      <description>&lt;p&gt;&lt;a href="https://kraken.ci/"&gt;Kraken CI&lt;/a&gt; is a new Continuous Integration tool. It is a modern, open-source, on-premise CI/CD system that is highly scalable and focused on testing. It is licensed under Apache 2.0 license. Its source code is available on &lt;a href="https://github.com/Kraken-CI/kraken"&gt;Kraken CI GitHub page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This tutorial is the third installment of the series of articles about Kraken CI. &lt;a href="https://dev.to/godfryd/kraken-ci-new-kid-on-the-ci-block-4imo"&gt;Part 1, Kraken CI, New Kid on the CI block&lt;/a&gt;, presented the installation of Kraken. The second part covered &lt;a href="https://dev.to/godfryd/your-first-workflow-in-kraken-ci-43hb"&gt;how to prepare a workflow for a simple Python project&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This time we would like to show the latest feature that was developed in Kraken CI: autoscaling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Maintaining a fixed number of machines for Kraken CI can be costly. If there is no high traffic of builds, then some machines sit idle and waste power. The solution to this problem is autoscaling ie. spawning machines with Kraken Agents dynamically depending on the current needs in the Kraken CI. If there is submitted a new flow with many building or testing jobs, then new machines are spawned. When the flow completes, machines are terminated and no costs are incurred.&lt;/p&gt;

&lt;p&gt;Currently, Kraken CI autoscaling is supporting AWS EC2 virtual machines.&lt;/p&gt;

&lt;p&gt;The following chapters show how to configure access to AWS, then how to configure parameters and behaviour of spawned machines. In the end, the usage in job definitions is presented.&lt;/p&gt;

&lt;p&gt;Details about configuration can be found in &lt;a href="https://kraken.ci/docs/autoscale-in-cloud"&gt;the Kraken docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Global Cloud Settings
&lt;/h2&gt;

&lt;p&gt;First, global settings have to be set to allow access to a given cloud provider. In Web UI, on Kraken -&amp;gt; Settings page, in Cloud tab, there is a form for collecting credentials to cloud providers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lMtMCtll--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/resipud8fec1bihh2141.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lMtMCtll--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/resipud8fec1bihh2141.png" alt="Global Settings with AWS Cloud"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the case of AWS, there are required &lt;code&gt;Access Key&lt;/code&gt; and &lt;code&gt;Secret Access Key&lt;/code&gt;. After filling in the values and saving settings, it is possible to check if it works by clicking &lt;code&gt;Test Access&lt;/code&gt; button.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparing Cloud Environment
&lt;/h2&gt;

&lt;p&gt;In the case of AWS it is also required to assign proper permissions so that Kraken can create or destroy EC2 instances. The list of all requires permissions looks as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VisualEditor0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"ec2:AuthorizeSecurityGroupIngress"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"ec2:CreateKeyPair"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"ec2:CreateSecurityGroup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"ec2:CreateTags"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"ec2:DeleteKeyPair"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"ec2:DescribeInstances"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"ec2:DescribeInstanceStatus"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"ec2:DescribeInstanceTypeOfferings"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"ec2:DescribeRegions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"ec2:DescribeSecurityGroups"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"ec2:DescribeVpcs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"ec2:RunInstances"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"ec2:TerminateInstances"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuration in Agents Groups
&lt;/h2&gt;

&lt;p&gt;Having set credentials to cloud providers, it is possible now to configure aspects of spawning new machines. This can be done on Kraken -&amp;gt; Agents -&amp;gt; Groups page.  Let's create a new Agents Group by clicking &lt;code&gt;Add New Group&lt;/code&gt; button and naming it &lt;code&gt;aws-t2-micro&lt;/code&gt;. The newly created details will be presented on a separate tab. On this tab, there is a section &lt;code&gt;Agents Deployment&lt;/code&gt;. So the deployment can be manual (default)&lt;br&gt;
or automated to a particular cloud provider. In the case of Amazon Web Services, there are the following options that can be set:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8EYaAMJ8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tv4fo4miukf8zxrr31dl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8EYaAMJ8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tv4fo4miukf8zxrr31dl.png" alt="Agents Group with AWS Settings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select any region that fits you. Limit of instances can be set to 2. This will not allow having more running machines than 2. For now, the default AMI can be empty.&lt;/p&gt;

&lt;p&gt;Then in VM options, let's stick to AWS free tier and select &lt;code&gt;t2.micro&lt;/code&gt; instance type. The rest of the checkboxes leave empty. Init script also can be blank.&lt;/p&gt;

&lt;p&gt;To ensure that dangling instances do not eat up our budget, let's set the options in Destruction section to 1 job and 10 minutes. So a spawned machine will be terminated after executing 1 job. And even then, if it sits idle for more than 10 minutes, it will be destroyed as well.&lt;/p&gt;
&lt;h2&gt;
  
  
  Job Definition
&lt;/h2&gt;

&lt;p&gt;Now, to use the defined &lt;code&gt;aws-t2-micro&lt;/code&gt; Agents Group, we need to prepare a project with a branch and a stage. More details about that can be found in &lt;a href="https://kraken.ci/docs/guide-intro"&gt;Introductory Guide&lt;/a&gt;. So let's concentrate now on defining a job.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"parent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"root"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"triggers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"parent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;True&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"configs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"jobs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"timeout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"steps"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"tool"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"cmd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo 'hello world'"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"environments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"system"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ami-0967f290f3533e5a8"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"agents_group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"aws-t2-micro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"config"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"default"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no much difference comparing to regular Kraken jobs. The job has a defined environments section where we are pointing to out &lt;code&gt;aws-t2-micro&lt;/code&gt; Agents Group. What's is new is &lt;code&gt;system&lt;/code&gt; field which points to &lt;code&gt;AMI&lt;/code&gt; identifier - this indicates AWS EC2 image.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run
&lt;/h2&gt;

&lt;p&gt;Now when a job is assigned to an agents group with configured Agents Deployment then a new machine will be spawned for that job if agents are no available in the Kraken.&lt;/p&gt;

&lt;p&gt;Let's change the view to Branch Results view and trigger a new flow by clicking &lt;code&gt;Run Flow&lt;/code&gt; button. On the run page, the list of jobs shows our AWS job:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MYH7fMsk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fgtsnij6254uyun5qyfa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MYH7fMsk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fgtsnij6254uyun5qyfa.png" alt="Job Executed in AWS EC2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it!&lt;/p&gt;

</description>
      <category>ci</category>
      <category>cd</category>
      <category>buildautomation</category>
      <category>devops</category>
    </item>
    <item>
      <title>Your First Workflow in Kraken CI</title>
      <dc:creator>Michal Nowikowski</dc:creator>
      <pubDate>Thu, 17 Jun 2021 04:12:32 +0000</pubDate>
      <link>https://forem.com/godfryd/your-first-workflow-in-kraken-ci-43hb</link>
      <guid>https://forem.com/godfryd/your-first-workflow-in-kraken-ci-43hb</guid>
      <description>&lt;p&gt;&lt;a href="https://kraken.ci" rel="noopener noreferrer"&gt;Kraken CI&lt;/a&gt; is a new Continuous Integration tool. It is a modern, open-source, on-premise CI/CD system that is highly scalable and focused on testing. It is licensed under Apache 2.0 license. Its source code is available on &lt;a href="https://github.com/Kraken-CI/kraken" rel="noopener noreferrer"&gt;Kraken CI GitHub page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This tutorial is the second installment of the series of articles about Kraken CI. &lt;a href="https://dev.to/godfryd/kraken-ci-new-kid-on-the-ci-block-4imo"&gt;Part 1&lt;/a&gt;, Kraken CI, New Kid on the CI block, presented the installation of Kraken. This time we will cover how to prepare a workflow for a simple Python project. The workflow will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;fetch sources from GitHub,&lt;/li&gt;
&lt;li&gt;run tests using Pytest,&lt;/li&gt;
&lt;li&gt;build a wheel package,&lt;/li&gt;
&lt;li&gt;upload built package to Kraken's artifacts storage.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here we are using fresh Kraken installation using Docker Compose with built-in Kraken Agent running in Docker container. Installation procedure details can be found in &lt;a href="https://dev.to/godfryd/kraken-ci-new-kid-on-the-ci-block-4imo"&gt;part 1&lt;/a&gt; or in &lt;a href="https://kraken.ci/docs/installation" rel="noopener noreferrer"&gt;the installation manual&lt;/a&gt; from &lt;a href="https://kraken.ci" rel="noopener noreferrer"&gt;https://kraken.ci&lt;/a&gt; project web page.&lt;/p&gt;

&lt;h1&gt;
  
  
  Project Preparation
&lt;/h1&gt;

&lt;p&gt;Details about a new project setup in Kraken CI can be found in the previous article, &lt;a href="https://dev.to/godfryd/kraken-ci-new-kid-on-the-ci-block-4imo"&gt;part 1&lt;/a&gt; as well.&lt;/p&gt;

&lt;p&gt;Here, in short, let's do:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a project with a name: &lt;em&gt;Demo&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Create a branch with a name: &lt;em&gt;main&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Use a pre-created stage and rename it to: &lt;em&gt;Hello World&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Stage Hello World
&lt;/h1&gt;

&lt;p&gt;The stage should look as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6f5e14o5ctyiymo4f1im.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6f5e14o5ctyiymo4f1im.png" alt="Branch management page with workflow schema code editor"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the original workflow schema code looks as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;parent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;triggers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;parent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;parameters&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;configs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jobs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;steps&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shell&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cmd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;echo &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hello world&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;
            &lt;span class="p"&gt;}],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;environments&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;any&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agents_group&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;all&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;config&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;default&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}]&lt;/span&gt;
        &lt;span class="p"&gt;}]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's try if it works. Click &lt;strong&gt;Run CI Flow&lt;/strong&gt; button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnmzlt68dxcxyahs4g9ue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnmzlt68dxcxyahs4g9ue.png" alt="Logs from the job with echo Hello World"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Git Repo Checkout Step
&lt;/h1&gt;

&lt;p&gt;Ok, let's start extending our schema to make it more real life. First, let's add a step for checking out a Git repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;steps&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;git&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;checkout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://github.com/Kraken-CI/sample-project-python.git&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shell&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cmd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ls -al&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now run new CI flow. The output should look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4qp6dff9oeyaenvlw2js.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4qp6dff9oeyaenvlw2js.png" alt="Logs from the job with git clone"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The logs show that the repository has been cloned and &lt;strong&gt;ls -al&lt;/strong&gt; shows &lt;strong&gt;sample-project-python&lt;/strong&gt; folder.&lt;/p&gt;

&lt;h1&gt;
  
  
  Run Tests Step
&lt;/h1&gt;

&lt;p&gt;Now let's replace the step with listing the current directory with something more interesting, like running tests. Kraken provides several built-in tools for running tests. In the case of our Python sample project, we will use &lt;strong&gt;pytest&lt;/strong&gt; built-in tool.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;steps&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;git&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;checkout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://github.com/Kraken-CI/sample-project-python.git&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pytest&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cwd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sample-project-python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;params&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-vv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pythonpath&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;src&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
 &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change the steps in schema editor, save it and run new CI flow. And the job output should be:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffcq16f7k9aqawxx38hpr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffcq16f7k9aqawxx38hpr.png" alt="Logs from the job with running Pytest"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Building Step
&lt;/h1&gt;

&lt;p&gt;So if tests succeeded we could build a package of our Python project. Add step for building a wheel package using project's setup.py script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;steps&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;git&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;checkout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://github.com/Kraken-CI/sample-project-python.git&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pytest&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cwd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sample-project-python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;params&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-vv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pythonpath&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;src&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shell&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cwd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sample-project-python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cmd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;python3 setup.py sdist bdist_wheel&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
 &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now run CI flow again. The output should look as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flonn3bb9xsrytnmjt5qh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flonn3bb9xsrytnmjt5qh.png" alt="Logs from the job with packaging step with error"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It seems that there is missing a package that provides wheel support for Python. Let's install it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;steps&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;git&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;checkout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://github.com/Kraken-CI/sample-project-python.git&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pytest&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cwd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sample-project-python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;params&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-vv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pythonpath&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;src&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shell&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cmd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sudo apt update &amp;amp;&amp;amp; sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends python3-wheel python3-setuptools&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shell&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cwd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sample-project-python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cmd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;python3 setup.py sdist bdist_wheel&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
 &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;New output with building:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7c0ri9bdl2pjvrcdxbtl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7c0ri9bdl2pjvrcdxbtl.png" alt="Logs from the job with successful deps installation and package building"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Storing Artifacts Step
&lt;/h1&gt;

&lt;p&gt;The results of building the sample project are two packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dist/sampleproject-2.0.0-py3-none-any.whl&lt;/li&gt;
&lt;li&gt;dist/sampleproject-2.0.0.tar.gz&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We could store it Kraken storage and make it available for user for downloading. For that purpose there is another built-in tool: &lt;em&gt;artifacts&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;steps&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;git&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;checkout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://github.com/Kraken-CI/sample-project-python.git&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pytest&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cwd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sample-project-python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;params&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-vv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pythonpath&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;src&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shell&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cmd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sudo apt update &amp;amp;&amp;amp; sudo DEBIAN_FRONTEND=noninteractive apt-get install -y - no-install-recommends python3-wheel python3-setuptools&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shell&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cwd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sample-project-python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cmd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;python3 setup.py sdist bdist_wheel&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;artifacts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;action&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;upload&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cwd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sample-project-python/dist&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sampleproject-2.0.0-py3-none-any.whl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sampleproject-2.0.0.tar.gz&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;public&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
 &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the job output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo73lih1m4v3uj84phyfk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo73lih1m4v3uj84phyfk.png" alt="Logs from the job with storing build artifacts"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here the log shows that artifacts have been stored. Now, as they were marked as public in artifacts step, they are available in the UI:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8e0r1iicelmbixfsxhob.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8e0r1iicelmbixfsxhob.png" alt="The Run page, Artifacts tab"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is it. In this installment we learn how to clone Git repository, how to run tests using Pytest, how to install dependencies and how to build artifacts and store them in Kraken's storage. More about Kraken CI you can find on &lt;a href="https://kraken.ci" rel="noopener noreferrer"&gt;https://kraken.ci&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ci</category>
      <category>cd</category>
      <category>buildautomation</category>
      <category>testing</category>
    </item>
    <item>
      <title>Kraken CI, New Kid on the CI Block</title>
      <dc:creator>Michal Nowikowski</dc:creator>
      <pubDate>Fri, 30 Apr 2021 08:41:39 +0000</pubDate>
      <link>https://forem.com/godfryd/kraken-ci-new-kid-on-the-ci-block-4imo</link>
      <guid>https://forem.com/godfryd/kraken-ci-new-kid-on-the-ci-block-4imo</guid>
      <description>&lt;p&gt;&lt;a href="https://kraken.ci" rel="noopener noreferrer"&gt;Kraken CI&lt;/a&gt; is a new Continuous Integration tool. It is a modern, open-source, on-premise CI/CD system that is highly scalable and focused on testing. It is licensed under Apache 2.0 license. Its source code is available on &lt;a href="https://github.com/kraken-ci/kraken" rel="noopener noreferrer"&gt;Kraken CI GitHub page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The main features of the system are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;flexible workflow planning using Starlark/Python&lt;/li&gt;
&lt;li&gt;distributed building and testing&lt;/li&gt;
&lt;li&gt;various executors: bare metal, Docker, LXD&lt;/li&gt;
&lt;li&gt;highly scalable to thousands of executors&lt;/li&gt;
&lt;li&gt;sophisticated test results analysis&lt;/li&gt;
&lt;li&gt;email and Slack notifications&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  1. Download Kraken Files for Docker Compose
&lt;/h3&gt;

&lt;p&gt;Download configuration files for Docker Compose from &lt;a href="https://github.com/Kraken-CI/kraken/releases" rel="noopener noreferrer"&gt;Kraken GitHub releases page&lt;/a&gt;.&lt;br&gt;
They are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;kraken-docker-compose-X.Y.yaml&lt;/strong&gt; - a services configuration file for Docker Compose&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;kraken-X.Y.env&lt;/strong&gt; - an example configuration for Kraken services that is used by Docker Compose file&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  2. Start Kraken Services
&lt;/h3&gt;

&lt;p&gt;In a terminal, in the folder where downloaded files are located, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;docker-compose --env-file kraken-X.Y.env -f kraken-docker-compose-X.Y.yaml up
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you should see lots of logs. They will not stop. First, Docker&lt;br&gt;
images are downloaded, and then services are started.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F034ed3wyxqwgv6jt2fn5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F034ed3wyxqwgv6jt2fn5.png" alt="Logs after starting docker-compose"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try to get to the web page on &lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Log In
&lt;/h3&gt;

&lt;p&gt;On the main page, log in as admin using &lt;code&gt;admin/admin&lt;/code&gt; credentials.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4x26abuhrx5jl5cuz0dx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4x26abuhrx5jl5cuz0dx.png" alt="Login page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After logging in, the dashboard page will appear. It shows tiles with&lt;br&gt;
projects and their branches.  There is already a prepared project&lt;br&gt;
called &lt;code&gt;Demo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But first, a built-in agent that will be executing jobs needs to be&lt;br&gt;
authorized.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Authorize Agent
&lt;/h3&gt;

&lt;p&gt;Go to the menu Agents -&amp;gt; Discovered. The Discovered Agents page shows&lt;br&gt;
agents that try to connect to the Kraken server but were not yet&lt;br&gt;
authorized by an admin.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpzxgxy0cd48ihj78yu7i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpzxgxy0cd48ihj78yu7i.png" alt="Dashboard page and a menu to Discovered Agents"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select the checkbox and click the &lt;code&gt;Authorized&lt;/code&gt; button.&lt;/p&gt;

&lt;p&gt;Now we can go back to the main page (the dashboard) and explore&lt;br&gt;
&lt;code&gt;Demo&lt;/code&gt; project. Click on the Kraken logo in the top left corner.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. The First Project and its Branch
&lt;/h3&gt;

&lt;p&gt;Click the cog icon on the right side of &lt;code&gt;Project Demo&lt;/code&gt;. It leads to&lt;br&gt;
the project settings page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbo2qhjsf81olwo0cciwq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbo2qhjsf81olwo0cciwq.png" alt="Dashboard page and a cog link to project settings page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the project page, there is a list of branches. Let's go to the&lt;br&gt;
already prepared &lt;code&gt;Master&lt;/code&gt; branch:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnfhzllbxxh21qhjq26zq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnfhzllbxxh21qhjq26zq.png" alt="Project settings page and a link to branch page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the branch page, there is a defined workflow that consists of stages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F40fly35p0xzvuxo0z5bf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F40fly35p0xzvuxo0z5bf.png" alt="Branch page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the screen, on the left, there is visible one stage, &lt;code&gt;Tests&lt;/code&gt;. The&lt;br&gt;
right side presents details of this stage. The black box shows the&lt;br&gt;
critical part of the stage: it is a workflow schema that is written in&lt;br&gt;
Starlark/Python.&lt;/p&gt;

&lt;p&gt;Currently, the stage's workflow pulls a sample project from&lt;br&gt;
&lt;a href="https://github.com/Kraken-CI/sample-project-python.git" rel="noopener noreferrer"&gt;https://github.com/Kraken-CI/sample-project-python.git&lt;/a&gt; and then run&lt;br&gt;
&lt;code&gt;pytest&lt;/code&gt; tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Trigger the First Flow
&lt;/h3&gt;

&lt;p&gt;Click the &lt;code&gt;Run CI Flow&lt;/code&gt; button to trigger the first flow of the branch&lt;br&gt;
workflow, and then confirm it by clicking the &lt;code&gt;Submit&lt;/code&gt; button.&lt;/p&gt;

&lt;p&gt;The next page shows triggered flow details.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frpozn9pwqsai44usvimz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frpozn9pwqsai44usvimz.png" alt="Flow page and a link to Stage Run page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the left side, there is a list of runs of stages (currently there is&lt;br&gt;
only one run: &lt;code&gt;Tests&lt;/code&gt;), and on the right, there are details of this&lt;br&gt;
stage run. All is green, so it means that all completed successfully.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Results of The Run
&lt;/h3&gt;

&lt;p&gt;Click the &lt;code&gt;Tests&lt;/code&gt; run link to get to results of the run.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2rc61q2vvy59imzecnhl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2rc61q2vvy59imzecnhl.png" alt="Run page and Jobs tab"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first tab, Jobs, on the run results page, shows a list of executed&lt;br&gt;
jobs. Our job was pretty quick, so we see the final results. If a&lt;br&gt;
job takes more time, then here will be presented its live status and&lt;br&gt;
logs.&lt;/p&gt;

&lt;p&gt;The next tab, Test Results, presents a table with test cases and their&lt;br&gt;
status (passed, failed, etc.).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frymreichu4sajgpv5irk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frymreichu4sajgpv5irk.png" alt="Run page and Test Results tab"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We may conclude the quick start guide here. We encourage you to try&lt;br&gt;
play with the workflow schema and check what can be accomplished more.&lt;/p&gt;

</description>
      <category>ci</category>
      <category>cd</category>
      <category>buildautomation</category>
    </item>
  </channel>
</rss>
