<?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>DEV Community: MindaugasLaganeckas</title>
    <description>The latest articles on DEV Community by MindaugasLaganeckas (@mindaugaslaganeckas).</description>
    <link>https://dev.to/mindaugaslaganeckas</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%2F258574%2Fec4f02df-9e83-4ca7-90c4-e8c158788790.jpeg</url>
      <title>DEV Community: MindaugasLaganeckas</title>
      <link>https://dev.to/mindaugaslaganeckas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mindaugaslaganeckas"/>
    <language>en</language>
    <item>
      <title>Contributing to open source can be frustrating</title>
      <dc:creator>MindaugasLaganeckas</dc:creator>
      <pubDate>Thu, 09 Nov 2023 11:52:46 +0000</pubDate>
      <link>https://dev.to/mindaugaslaganeckas/contributing-to-open-source-can-be-frustrating-o4n</link>
      <guid>https://dev.to/mindaugaslaganeckas/contributing-to-open-source-can-be-frustrating-o4n</guid>
      <description>&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;This post is about open source contributions, that happen during business hours and the company is paying for it. Why? Because the company uses open source projects and it is in the company's best interest to get certain/blocking stuff fixed.&lt;br&gt;
This post is not about contributions that happen in people's free time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;I have been a JAVA dev since the start of my career. Started as a desktop application developer in a Danish company, that produces high-end hearing aids for the hearing impaired people. After 7 great years, I switched to another high-tech Danish company, but this time as DevOps engineer. My primary task was to support 400 engineers by providing stable and reliable CI/CD system. This was the time, when my new colleagues introduced me to the Open Source and why it mattered. Great times - I can promise you :) One year into the new job, the company has decided to move from internally hosted Gitlab solution to Github. Yay!!! For our team it meant to support the migration and keep the level of build system at the same or even better performance level. Even though the time has been spent on verifying Github for our organization needs, the true issue came out only after the migration :)&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;We have had many repositories in our organization. More than 1200 actually. Some of them have been built by &lt;a href="https://www.jetbrains.com/teamcity/"&gt;TeamCity&lt;/a&gt; and some of them by &lt;a href="https://www.jenkins.io/"&gt;Jenkins&lt;/a&gt;. There was no overlap between the 2 groups of projects. While all projects in TeamCity have been created by hand (using templates), the projects in Jenkins have been managed by configuration-as-code &lt;a href="https://www.jenkins.io/projects/jcasc/"&gt;CasC&lt;/a&gt;. Great - it worked well in Gitlab - what could go wrong in Github? The answer is Repository discovery. It is a process performed by build systems to detect projects to build. Suddenly for every Jenkins restart, the repository discovery took 10+ min. These minutes got introduced into startup of Jenkins and caused a series of failures. Just to name a few: timeouts, health check problems, tests failing to start (yes, we validated every Jenkins installation), memory issues. Unfortunately, we could not silently ignore the problem and wait for the fix to appear. Engineers in our organization wanted new Jenkins features, bugfixes. We had to regularly update plugins, resize disks etc and therefore restart Jenkins. The life was not easy.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;Well, we thought, let's find the &lt;a href="//plugins.jenkins.io/github-branch-source/"&gt;plugin&lt;/a&gt; responsible for Github repository discovery in Jenkins and fix the problem. Ok. That is not hard. Few days later we came up with the &lt;a href="https://github.com/jenkinsci/github-branch-source-plugin/pull/344"&gt;fix&lt;/a&gt;. The improvement is huge: the repository discovery went from 10+ min to 2+ min. You might think that the whole community has been waiting for the update, right? Or ...&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JJ-WqW9z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lrtskjghv4cyk8hw8tb0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JJ-WqW9z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lrtskjghv4cyk8hw8tb0.png" alt="Taken from the PR mentioned above" width="800" height="142"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Here is what happened next
&lt;/h1&gt;

&lt;p&gt;Unfortunately, and to our biggest surprise, no one from the project maintainers was really interested in reviewing the change and get it released. Here is what happened next (look at the dates!):&lt;br&gt;
Oct  1, 2020 Pull request (PR) published &lt;br&gt;
Oct  2, 2020 First ask for a review from the maintainers &lt;br&gt;
Oct 22, 2020 github-source-branch plugin comments on the PR&lt;br&gt;
Oct 22, 2020 First review received&lt;br&gt;
Oct 27, 2020 Review feedback addressed&lt;br&gt;
Oct 27, 2020 First reviewer asks for a second pair of eyes&lt;br&gt;
Jan 11, 2021 Approval for PR received&lt;br&gt;
Sep  7, 2021 A ping to project maintainers&lt;br&gt;
Sep 13, 2021 Third reviewer joins the conversation&lt;br&gt;
Sep 13, 2021 Merge issues detected in the PR&lt;br&gt;
Sep 20, 2021 Merge issues solved&lt;br&gt;
Oct  4, 2021 Changes approved and merged&lt;br&gt;
Dec 27, 2021 A new version of plugin &lt;a href="https://github.com/jenkinsci/github-branch-source-plugin/releases?page=3"&gt;released&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What happened behind the scenes
&lt;/h2&gt;

&lt;p&gt;16 releases happened between Oct 1, 2020 (the day that we published the fix) and Dec 27, 2021 (the day, when the fix was made available to everyone). Meaning we had to keep the fork of the project updated: integrate new changes, build and deploy the new version of the plugin. Everyone who has ever tried to keep Jenkins plugins updated in your Jenkins installation, knows what a mess it can be: plugins, that depend on other plugins. Oh, and do not forget transitive dependencies, that has to match. Well, should I have invested into automation? Maybe yes. Except, that my expectation was "I am very close. It will get the fix released soon."&lt;/p&gt;

&lt;h2&gt;
  
  
  How will I go about contributing to open source next time
&lt;/h2&gt;

&lt;p&gt;Well, myself being an open source project maintainer, I understand, that the issue is in man power. And that is pretty much it. It takes time to correspond, review and release. The only thing, that I would like to improve next time is to align expectations with the project maintainers and as early as possible get in touch with them. Normally open source projects have CONTRIBUTING.md or a public slack channel to get started. As the last resort I would create an issue in the project repository and present my ideas there. Basically I would like to get a feel of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How active the project is&lt;/li&gt;
&lt;li&gt;How busy the people behind the project are&lt;/li&gt;
&lt;li&gt;How much my feature is relevant/important for the project etc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This information would help to keep things more transparent with my colleagues and my boss and potentially invest into automation while waiting for the fix to get released.&lt;/p&gt;

&lt;h2&gt;
  
  
  Acknowledgments
&lt;/h2&gt;

&lt;p&gt;I would like to thank Rasmus Jelsgaard for encouraging to write this post and Sameena Syed for proof-reading.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>technicaldebt</category>
      <category>contribute</category>
      <category>jenkins</category>
    </item>
    <item>
      <title>DevOps development guidelines</title>
      <dc:creator>MindaugasLaganeckas</dc:creator>
      <pubDate>Thu, 23 Sep 2021 11:54:10 +0000</pubDate>
      <link>https://dev.to/mindaugaslaganeckas/devops-katas-32e0</link>
      <guid>https://dev.to/mindaugaslaganeckas/devops-katas-32e0</guid>
      <description>&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;2 years ago I have switched from software development to DevOps in a Danish high-end technology company. The team, that I had joined, consisted of 5 very talented engineers, who delivered build agents, pipelines, automation scripts etc. to the whole R&amp;amp;D of more than 400 hardware and software engineers. Joining this talented and ambitious DevOps team back then, it seemed that there is no limit to what we can achieve. We could see so many new good solutions out there to ease our customers` day-to-day hurdles. Unfortunately, quite fast we had noticed, that adding more technologies to the stack made us vulnerable to &lt;a href="https://en.wikipedia.org/wiki/Bus_factor"&gt;bus-factor&lt;/a&gt; and stretched us quite thin. In addition, we had no consensus of where to keep secrets that made it hard managing them, shared pipelines implemented by us, were hard to debug/run on a dev machine, the number of self hosted solutions grew rapidly requiring more and more time to attend them... So we had started working on development guidelines for the team, which we called Katas back then. &lt;/p&gt;

&lt;h2&gt;
  
  
  Development guidelines
&lt;/h2&gt;

&lt;p&gt;Here are some of the guidelines that we would like to share with you. The idea with these guidelines is to minimize the impact on the organization and deliver high quality tools and infrastructure while keeping a high pace for it. Please, leave a comment, if you have similar experiences or more to add. &lt;br&gt;
The development guidelines are not listed in a prioritized order.&lt;/p&gt;

&lt;h3&gt;
  
  
  Programming languages
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Limit the number of programming languages
&lt;/h4&gt;

&lt;p&gt;It is so fun to solve a specific problem with the best tool there is. It is not fun at all to maintain solutions that use technologies you do not know. In the start we used Groovy, NodeJS, Powershell(Core), DotNet(Core), Bash, Java, Python. Unfortunately, we have some solutions now that we have stopped maintaining and reject any new feature requests, because we do not have the right competencies and no time to acquire them.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to choose programming languages
&lt;/h4&gt;

&lt;p&gt;For us the deciding factor in this case is our approach to &lt;a href="https://en.wikipedia.org/wiki/Inner_source"&gt;inner source&lt;/a&gt; all what we develop. We want to use the same programming languages as other engineers in the company. All our scripts, tools etc are open to contribute for everyone inside the company. We want people to help us out instead of being blocked by us. And that works quite well! :)&lt;/p&gt;

&lt;h3&gt;
  
  
  Design principles
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Always prefer a cloud-based solution
&lt;/h4&gt;

&lt;p&gt;It is so easy to download a docker image, create a VM for it, deploy and use it right away. Especially if a solution is free of charge. No budget negotiations, no approvals needed. Unfortunately, the maintenance of such VM/docker combo should not be underestimated. Your users will ask for new versions of the SW, your IT department will require to comply with the company's security policy. And it will happen when you have the least time for it.&lt;/p&gt;

&lt;h4&gt;
  
  
  CI/CD must be able to push/release/execute what you are building, not just locally.
&lt;/h4&gt;

&lt;p&gt;How many times have I heard: it works on my computer so I am done, am I? NO. You are done, when you have a pipeline for your project.&lt;/p&gt;

&lt;h4&gt;
  
  
  Design so that local builds and CI builds work the same way
&lt;/h4&gt;

&lt;p&gt;This one is tricky. The more patches/hack you will add to the pipeline to compensate a faulty tooling, the more time will you have to use when debugging the local builds that do not work.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sSzfyXe6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v9t7q1kepaiamol4x6wh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sSzfyXe6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v9t7q1kepaiamol4x6wh.png" alt="alt text" width="880" height="174"&gt;&lt;/a&gt;&lt;br&gt;
The image above shows a build stage of a DotNet project in a Jenkins pipeline. A developer will have to use time and effort before she configures local IDE to work the same way as the pipeline.&lt;br&gt;
All in all, you want to develop your pipelines/tooling so that it is easy to setup in the IDE. In the example above a simplification and integration in &lt;code&gt;dotnet build&lt;/code&gt; would be a desired solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployment strategies
&lt;/h3&gt;

&lt;p&gt;This section is mostly relevant to the organizations, that are larger or has a similar size, that I work for. While updating 2 build agents can also be challenging, still the impact of updating 40+ build agents has a much larger impact. In the latter case, the experience suggests to use Canary deployment strategy, when introducing new changes to the VM templates for your build agents. Normally, you do not know how people are using the build machines you provide, what kind of projects they are building. Introducing a change slowly minimizes the impact to the organization.&lt;/p&gt;

&lt;h3&gt;
  
  
  Open source vs Inner source
&lt;/h3&gt;

&lt;p&gt;Choose to contribute to an open source project instead of developing your own custom solution. Maintenance is a killer. Your team will have to learn your solution. Normally a community of an open source project is much larger than your team. Naturally, there are several risks (worth considering!) associated with this approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Your pull requests can get stuck for a year or longer&lt;/li&gt;
&lt;li&gt;It can take longer time to develop a contribution than a local hack. But you will get your code reviewed from someone knowledgeable in the field and you will learn something - no doubt!&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Managing secrets
&lt;/h3&gt;

&lt;p&gt;Do not distribute your secrets across build systems, environment variables on the deployment machines and other places. It is a mess! Github does not even let you read the secret back, once it is put there. Keep the secrets in one (or several) place and manage access to them.&lt;/p&gt;

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

&lt;p&gt;Working without monitoring and telemetry is like walking in the mine field in the dark. You want to stay ahead of the issues, such as servers running out of the disk space, before they hit the organization. In addition, you want to spend the time and energy on the tools and pipelines, that are being used most. Rich telemetry and monitoring data can help you to take decisions, where to put your focus most.&lt;/p&gt;

&lt;h2&gt;
  
  
  Acknowledgements
&lt;/h2&gt;

&lt;p&gt;I would like to thank Rasmus Jelsgaard and Vaida Laganeckiene for inputs, ideas when materializing development guidelines and proof-reading when working on this post.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>opensource</category>
      <category>design</category>
    </item>
    <item>
      <title>A pipeline dashboard for multi repository builds with GitHub Actions</title>
      <dc:creator>MindaugasLaganeckas</dc:creator>
      <pubDate>Sun, 10 Jan 2021 15:44:34 +0000</pubDate>
      <link>https://dev.to/mindaugaslaganeckas/a-pipeline-dashboard-for-multi-repository-builds-with-github-actions-4c7b</link>
      <guid>https://dev.to/mindaugaslaganeckas/a-pipeline-dashboard-for-multi-repository-builds-with-github-actions-4c7b</guid>
      <description>&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;A pipeline dashboard for multi repository builds with GitHub Actions&lt;/p&gt;

&lt;h3&gt;
  
  
  Category Submission:
&lt;/h3&gt;

&lt;p&gt;Built for Business&lt;/p&gt;

&lt;h3&gt;
  
  
  App Link
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://pipeline-graph-viewer-7oa6n.ondigitalocean.app/"&gt;https://pipeline-graph-viewer-7oa6n.ondigitalocean.app/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Screenshots
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HOhPn0fQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1tr54y35cvtrh2pirbfd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HOhPn0fQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1tr54y35cvtrh2pirbfd.png" alt="Alt Text" width="603" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Description
&lt;/h3&gt;

&lt;p&gt;Please, see either &lt;a href="https://pipeline-graph-viewer-7oa6n.ondigitalocean.app/"&gt;https://pipeline-graph-viewer-7oa6n.ondigitalocean.app/&lt;/a&gt;&lt;br&gt;
or&lt;br&gt;
&lt;a href="https://github.com/MindaugasLaganeckas/pipeline-graph-viewer"&gt;https://github.com/MindaugasLaganeckas/pipeline-graph-viewer&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Link to Source Code
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/MindaugasLaganeckas/pipeline-graph-viewer"&gt;https://github.com/MindaugasLaganeckas/pipeline-graph-viewer&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Permissive License
&lt;/h3&gt;

&lt;p&gt;MIT&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;An actual problem, that we face in our organization.&lt;/p&gt;

&lt;h3&gt;
  
  
  How I built it
&lt;/h3&gt;

&lt;p&gt;I have learned a lot about ReactJS and its integration with DotNet 5.&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources/Info
&lt;/h3&gt;

&lt;p&gt;None&lt;/p&gt;

</description>
      <category>dohackathon</category>
    </item>
    <item>
      <title>Create Pull Request (only)</title>
      <dc:creator>MindaugasLaganeckas</dc:creator>
      <pubDate>Wed, 02 Sep 2020 12:43:38 +0000</pubDate>
      <link>https://dev.to/mindaugaslaganeckas/create-pull-request-only-22ik</link>
      <guid>https://dev.to/mindaugaslaganeckas/create-pull-request-only-22ik</guid>
      <description>&lt;p&gt;Create Pull Request against another or the same repository. There is no extra functionality. If the Pull Request already exists, the action exits without failing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    - name: Make a PR
      uses: MindaugasLaganeckas/create-pull-request@v1
      with:
        token: ${{ secrets.SUPER_SECRET }}
        owner: ${{ env.OWNER }}
        repo: ${{ env.REPO }}
        headBranch: ${{ env.DEST_BRANCH }}
        title: "Install Release Drafter"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Maintainer Must-Haves&lt;/p&gt;

&lt;h3&gt;
  
  
  Yaml File or Link to Code
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/mindaugaslaganeckas/create-pull-request/"&gt;https://github.com/mindaugaslaganeckas/create-pull-request/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>actionshackathon</category>
    </item>
    <item>
      <title>Get Default Branch Name</title>
      <dc:creator>MindaugasLaganeckas</dc:creator>
      <pubDate>Tue, 01 Sep 2020 10:49:13 +0000</pubDate>
      <link>https://dev.to/mindaugaslaganeckas/get-default-branch-name-1clo</link>
      <guid>https://dev.to/mindaugaslaganeckas/get-default-branch-name-1clo</guid>
      <description>&lt;h3&gt;
  
  
  Get the default branch or an empty string, if there are no branches in the repository.
&lt;/h3&gt;

&lt;p&gt;You can call the action in your workflow like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    - name: Get default branch name
      id: defaultBranchName
      uses: MindaugasLaganeckas/get-default-branch@v1
      with:
        token: ${{ secrets.SUPER_SECRET }}
        path: ${{ env.OWNER }}/${{ env.REPO }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can access the output like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    - name: Change to master branch if repository is empty
      if: ${{ steps.defaultBranchName.outputs.default-branch == '' }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Maintainer Must-Haves&lt;/p&gt;

&lt;h3&gt;
  
  
  Yaml File or Link to Code
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/MindaugasLaganeckas/get-default-branch"&gt;https://github.com/MindaugasLaganeckas/get-default-branch&lt;/a&gt;&lt;/p&gt;

</description>
      <category>actionshackathon</category>
    </item>
    <item>
      <title>Percy upload simplified</title>
      <dc:creator>MindaugasLaganeckas</dc:creator>
      <pubDate>Fri, 21 Aug 2020 08:42:26 +0000</pubDate>
      <link>https://dev.to/mindaugaslaganeckas/percy-upload-simplified-3o3c</link>
      <guid>https://dev.to/mindaugaslaganeckas/percy-upload-simplified-3o3c</guid>
      <description>&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;

&lt;p&gt;Wraps percy/agent docker in a Github action. Executes&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;percy upload&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 operation. The users of this action does not need to know docker. They get a simplified interface to upload generated images to percy.io for regression testing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Maintainer Must-Haves (for image regression testing)&lt;/p&gt;

&lt;h3&gt;
  
  
  Link to Repository
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/MindaugasLaganeckas/percy-upload"&gt;Percy Upload&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/mermaid-js/mermaid-cli/"&gt;Mermaid CLI&lt;/a&gt; uses percy-upload action&lt;/p&gt;

</description>
      <category>actionshackathon</category>
    </item>
  </channel>
</rss>
