<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>FrostyX&apos;s blog</title>
    <description>Personal blog of Jakub Kadlčík (aka FrostyX)
</description>
    <link>http://frostyx.cz/</link>
    <atom:link href="http://frostyx.cz/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sat, 18 Jul 2026 17:34:30 +0000</pubDate>
    <lastBuildDate>Sat, 18 Jul 2026 17:34:30 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>Fedora Package Review Process reimagined</title>
        <description>&lt;p&gt;The &lt;a href=&quot;https://docs.fedoraproject.org/en-US/package-maintainers/Package_Review_Process/&quot;&gt;Fedora Package Review Process&lt;/a&gt; is clunky, archaic,
and not on par with what we expect when contributing to Open Source projects in
this century. We all know that, and we all want it to improve. That being said,
we need to realize what is currently our main bottleneck. Even though the
process is not friendly to new contributors, they are doing just fine - at all
times, &lt;a href=&quot;https://fedoraproject.org/PackageReviewStatus/reviewable.html&quot;&gt;we have hundreds of new packages in the queue&lt;/a&gt;. Our biggest
problem is our inability to effectively review them.&lt;/p&gt;

&lt;p&gt;I don’t think we talk about this problem enough. That’s why it felt so
validating to hear &lt;a href=&quot;https://github.com/hroncok&quot;&gt;Miro Hrončok&lt;/a&gt; voice my exact thoughts during the
&lt;a href=&quot;https://frostyx.cz/posts/flock-to-fedora-report-2026&quot;&gt;Flock to Fedora 2026&lt;/a&gt; keynote.&lt;/p&gt;

&lt;p&gt;In this blog post, I am going to elaborate on the ideas that we (mostly Miro)
came up with, shooting shit in the hallway after the session.&lt;/p&gt;

&lt;h2 id=&quot;proposing-new-packages-through-prs&quot;&gt;Proposing new packages through PRs&lt;/h2&gt;

&lt;p&gt;This is an obvious one, we talked about the same idea with
&lt;a href=&quot;https://fedoraproject.org/wiki/User:Zbyszek&quot;&gt;Zbigniew Jędrzejewski-Szmek&lt;/a&gt; at &lt;a href=&quot;https://frostyx.cz/posts/flock-to-fedora-report-2025&quot;&gt;Flock to Fedora 2025&lt;/a&gt;. It
is a necessary prerequisite for any potential improvements, which will allow us
to have a workflow that contributors are familiar with, inline code comments,
CI/CD, and other things that are not possible in Bugzilla.&lt;/p&gt;

&lt;p&gt;Proposing new packages through PRs would be trivial to implement if we
had all Fedora packages in a monorepo. Which we don’t, and we probably
don’t want to have. And even if we wanted to have, it would require
massive changes throughout the ecosystem.&lt;/p&gt;

&lt;p&gt;As a workaround, we discussed having an intermediate repository on the
&lt;a href=&quot;https://forge.fedoraproject.org/&quot;&gt;forge.fedoraproject.org&lt;/a&gt; into which we would only propose new
packages. It would have &lt;a href=&quot;https://communityblog.fedoraproject.org/packit-as-fedora-dist-git-ci-final-phase/&quot;&gt;Packit CI&lt;/a&gt; enabled, and therefore every
proposed package would automatically get a scratch build and a test suite run on
top of it. Currently
&lt;a href=&quot;https://github.com/packit/tmt-plans/tree/main/tests&quot;&gt;supported tests are rpmlint, rpminspect, and license-validate&lt;/a&gt;.
We know that adding new tests is easy, as I am currently working on support for
&lt;a href=&quot;https://github.com/packit/tmt-plans/tree/main/tests/fedora-review&quot;&gt;fedora-review&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Of course, a final approval from a fellow package maintainer would still be
needed. Once accepted, we would merge the PR and automatically create a new
DistGit repository and import the package. Then we would delete all data from
the intermediate repository to keep it clean.&lt;/p&gt;

&lt;h2 id=&quot;bulk-review&quot;&gt;Bulk review&lt;/h2&gt;

&lt;p&gt;The review queue is and always has been in hundreds. Many of the packages are
dependencies for something else, and people have no motivation to review them
separately. And even if they do, it’s not always easy to test them on their
own. This currently leads to accepting broken packages that nobody tested or
ignoring the tickets completely.&lt;/p&gt;

&lt;p&gt;We discussed the possibility of proposing multiple packages within one PR. They
could be reviewed, tested, and accepted all at once.&lt;/p&gt;

&lt;p&gt;For such PRs, we could automatically create a new project in Copr and build the
packages in the order they were committed. We could nicely use
&lt;a href=&quot;https://docs.copr.fedorainfracloud.org/user_documentation.html#build-batches&quot;&gt;Copr’s build batches feature&lt;/a&gt; here. If multiple packages were
added in one commit, they could be built in parallel. If the contributor decides
to force-push into their PR, we would wipe the Copr project and start over.&lt;/p&gt;

&lt;h2 id=&quot;auto-import-into-distgit&quot;&gt;Auto import into DistGit&lt;/h2&gt;

&lt;p&gt;There is no reason why the contributor would have to manually run&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;fedpkg request-repo my-package 12345
fedpkg request-branch &lt;span class=&quot;nt&quot;&gt;--all-releases&lt;/span&gt;

fedpkg clone foo
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;foo
fedpkg import /path/to/the/foo.src.rpm
fedpkg push
fedpkg build

fedpkg switch-branch f44
git rebase rawhide
fedpkg push
fedpkg build
&lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# repeat for f43, f42, etc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can request all the DistGit repositories and branches for them. And once they
are created, we can automatically import the packages. There are some open
questions though. How can the contributor signalize what branches they want?
Should we use the git history from the PR? Can we use Forgejo actions to trigger
the requests and imports?&lt;/p&gt;

&lt;h2 id=&quot;proposal-vs-prototype&quot;&gt;Proposal vs prototype&lt;/h2&gt;

&lt;p&gt;I realize this is not a formal proposal but merely a blog post on my personal
website. That was an intentional decision. We’ve been discussing and
bike-shedding this topic for years, and yet we don’t have much to show for it. I
am writing this article mainly not to forget the ideas we’ve had, and even
though I am interested in your thoughts, this is not an RFC. I already started
implementing a prototype, and soon I’ll record a demo for you. Then, I’ll start
bothering you and asking for feedback.&lt;/p&gt;

&lt;p&gt;In my opinion, it doesn’t have to be perfect. We just need to kick this off,
implement something small that works, and improve it as time goes.&lt;/p&gt;

&lt;p&gt;Maybe I should also say that I am not aiming to replace the current
&lt;a href=&quot;https://docs.fedoraproject.org/en-US/package-maintainers/Package_Review_Process/&quot;&gt;Package Review Process&lt;/a&gt;. My goal is to provide an
alternative version of this process and allow contributors to choose which one
they want to follow. Then, someday in the future, if the alternative turns out
to be popular, possibly deprecating the old review process.&lt;/p&gt;

</description>
        <pubDate>Tue, 07 Jul 2026 00:00:00 +0000</pubDate>
        <link>http://frostyx.cz/posts/fedora-package-review-process-reimagined</link>
        <guid isPermaLink="true">http://frostyx.cz/posts/fedora-package-review-process-reimagined</guid>
        
        <category>fedora</category>
        
        <category>packaging</category>
        
        
      </item>
    
      <item>
        <title>Flock to Fedora report 2026</title>
        <description>&lt;p&gt;This post is tough to write because &lt;a href=&quot;https://fedoraproject.org/flock/&quot;&gt;Flock to Fedora&lt;/a&gt; is my
favorite conference, and &lt;a href=&quot;https://frostyx.cz/posts/flock-to-fedora-report-2025&quot;&gt;last year’s Flock&lt;/a&gt; might have been the
best conference I’ve ever been to. I love the Fedora community, Prague is
beautiful, the venue is nice, we always have so many interesting talks and
workshops, the organizers do an amazing job preparing this event for us, so I
feel really guilty saying that I did not have much fun this year. That is 100%
on me, though. Flock bears no blame.&lt;/p&gt;

&lt;p&gt;It wasn’t exactly the wisest decision ever to run
&lt;a href=&quot;https://www.runczech.com/cs/akce/mattoni-running-festival-olomouc-2026/zavody/mattoni-1-2maraton-olomouc&quot;&gt;my first half-marathon&lt;/a&gt; the very evening before the conference,
and then waking up early to commute to Prague. It must have hit me much more
than I was willing to admit. I feel fine physically, but I can’t pay attention
to anything because nothing feels exciting. That is the most lifeless I’ve felt
in a long time.&lt;/p&gt;

&lt;p&gt;So, in case anyone is wondering … it was me, not you.&lt;/p&gt;

&lt;h3 id=&quot;highlights&quot;&gt;Highlights&lt;/h3&gt;

&lt;p&gt;Despite all that, these were the highlights of the event for me.&lt;/p&gt;

&lt;h4 id=&quot;forging-fedora-projects-future-with-forgejo&quot;&gt;&lt;a href=&quot;https://cfp.fedoraproject.org/flock-to-fedora-2026/talk/BTDZAA/&quot;&gt;Forging Fedora Project’s Future With Forgejo&lt;/a&gt;&lt;/h4&gt;

&lt;p&gt;Great job on the migration from &lt;a href=&quot;https://pagure.io&quot;&gt;pagure.io&lt;/a&gt; to
&lt;a href=&quot;https://forge.fedoraproject.org&quot;&gt;forge.fedoraproject.org&lt;/a&gt;. It was
handled exceptionally well. Next, we look forward to the migration of
&lt;a href=&quot;https://src.fedoraproject.org&quot;&gt;src.fedoraproject.org&lt;/a&gt; to Forgejo, which can’t come
soon enough. &lt;a href=&quot;https://cfp.fedoraproject.org/flock-to-fedora-2026/speaker/V3TBBG/&quot;&gt;Tomáš Hrčka&lt;/a&gt; teased us that this migration may take
considerably less time than the previous one because they already know how to do
things (e.g., deploy Forgejo, etc).&lt;/p&gt;

&lt;h4 id=&quot;diy-ai-build-a-private-customizable-chatbot-on-lean-hardware&quot;&gt;&lt;a href=&quot;https://cfp.fedoraproject.org/flock-to-fedora-2026/talk/DYZJHQ/&quot;&gt;DIY AI: Build a Private, Customizable Chatbot on Lean Hardware&lt;/a&gt;&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://cfp.fedoraproject.org/flock-to-fedora-2026/speaker/M9CWQQ/&quot;&gt;Ellis Low&lt;/a&gt; showed us how to run an LLM on our laptops through Llama
and how to interact with it. I really appreciated him saying that, except for
this one small text-in, text-out magic black box, everything else is standard
software engineering as we know it.&lt;/p&gt;

&lt;h4 id=&quot;fedora-council-strategic-proposals--fesco-qa&quot;&gt;&lt;a href=&quot;https://cfp.fedoraproject.org/flock-to-fedora-2026/talk/PHZW3D/&quot;&gt;Fedora Council Strategic Proposals + FESCo Q&amp;amp;A&lt;/a&gt;&lt;/h4&gt;

&lt;p&gt;Most of the discussion revolved around a decline of new contributors and us
failing to connect with the next generation. “They talk about changing
wallpaper, we talk about burnout” – &lt;a href=&quot;https://cfp.fedoraproject.org/flock-to-fedora-2026/speaker/TGZDY8/&quot;&gt;Aleksandra Fedorova&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&quot;whats-cooking-in-copr-testing-farm-tmt-packit-and-log-detective&quot;&gt;&lt;a href=&quot;https://cfp.fedoraproject.org/flock-to-fedora-2026/talk/FHYW3G/&quot;&gt;What’s Cooking in Copr, Testing Farm, tmt, Packit and Log Detective&lt;/a&gt;&lt;/h4&gt;

&lt;p&gt;I found &lt;a href=&quot;https://github.com/praiskup&quot;&gt;Pavel Raiskup&lt;/a&gt;’s return to the stage hilarious.&lt;/p&gt;

&lt;h4 id=&quot;scrapers-gotta-scrape-scrape-scrape&quot;&gt;&lt;a href=&quot;https://cfp.fedoraproject.org/flock-to-fedora-2026/talk/FWSYWR/&quot;&gt;Scrapers gotta scrape scrape scrape&lt;/a&gt;&lt;/h4&gt;

&lt;p&gt;As presentations go, &lt;a href=&quot;https://cfp.fedoraproject.org/flock-to-fedora-2026/speaker/G8QMRU/&quot;&gt;Kevin Fenzi&lt;/a&gt;’s talk about AI scrapers was
the best. It started with minor A/V dificulities, which is a nice reminder
to not feel bad, the next time it happens to you, because it happens to
everybody. Even the main infra guy. Semi-joking aside, I enjoyed the brief
history of web scraping and Kevin’s taxonomy of scrapers, clearly showing that
not all scrapers are the same (e.g.,
&lt;a href=&quot;https://web.archive.org/&quot;&gt;web.archive.org&lt;/a&gt;). However, the current AI scrapers
are the plague of the internet, and I am so glad the Fedora Infra team fights
them as best as they can to keep our services running.&lt;/p&gt;

&lt;h4 id=&quot;chat-with-adam&quot;&gt;Chat with Adam&lt;/h4&gt;

&lt;p&gt;I ran into my former Copr team mate &lt;a href=&quot;https://cfp.fedoraproject.org/flock-to-fedora-2026/talk/8GWWTY/&quot;&gt;Adam Šamalík&lt;/a&gt; in the hallway,
and we had a nice chat about life. When we still worked together (10 years ago,
oh how the time flies), I randomly asked him what he did on a weekend. “We had
no plans, so we bought plane tickets and went on a date to Amsterdam with my
girlfriend”. Fucking what?! That was the coolest response ever. Since that
day, I remember it every time my creaking, lazy bones struggle to do something
spontaneous. Why am I telling it now? Adam is now happily living in the
Netherlands full-time. Funny how one impromptu decision can completely change
your life.&lt;/p&gt;

&lt;h4 id=&quot;chat-with-emmanuel&quot;&gt;Chat with Emmanuel&lt;/h4&gt;

&lt;p&gt;Made friends with &lt;a href=&quot;https://fedoraproject.org/wiki/User:Eseyman&quot;&gt;Emmanuel Seyman&lt;/a&gt;. He said hello after seeing
the &lt;a href=&quot;https://www.youtube.com/watch?v=m59OdC3BLp0&quot;&gt;Fedora Podcast episode with me as a guest&lt;/a&gt;. I really
enjoyed our chat, and I am going to follow up online because I think he’ll
really like &lt;a href=&quot;https://github.com/sundaram123krishnan/&quot;&gt;Sundaram Krishnan&lt;/a&gt;’s project
&lt;a href=&quot;https://github.com/sundaram123krishnan/coprtree&quot;&gt;coprtree&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&quot;chat-with-miro&quot;&gt;Chat with Miro&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://cfp.fedoraproject.org/flock-to-fedora-2026/speaker/RTZAUD/&quot;&gt;Miro Hrončok&lt;/a&gt; shared some of his ideas about improving the
&lt;a href=&quot;https://docs.fedoraproject.org/en-US/package-maintainers/Package_Review_Process/&quot;&gt;Fedora Package Review Process&lt;/a&gt; with me. This deserves an
article on its own, so stay tuned.&lt;/p&gt;

&lt;p&gt;Edit: Please read the &lt;a href=&quot;https://frostyx.cz/posts/fedora-package-review-process-reimagined&quot;&gt;Fedora Package Review Process reimagined&lt;/a&gt;
article.&lt;/p&gt;

</description>
        <pubDate>Wed, 17 Jun 2026 00:00:00 +0000</pubDate>
        <link>http://frostyx.cz/posts/flock-to-fedora-report-2026</link>
        <guid isPermaLink="true">http://frostyx.cz/posts/flock-to-fedora-report-2026</guid>
        
        <category>fedora</category>
        
        <category>flock</category>
        
        <category>report</category>
        
        
      </item>
    
      <item>
        <title>Copr builders powered by bootc</title>
        <description>&lt;p&gt;As of today, all Copr builder virtual machines are now being spawned from
&lt;a href=&quot;https://docs.fedoraproject.org/en-US/bootc/getting-started/&quot;&gt;bootc&lt;/a&gt; images, which is no small feat because the builder infrastructure
involves multiple architectures (x86_64, aarch64, ppc64le, s390x), multiple
clouds (Amazon AWS, IBM Cloud), and on-premise hypervisors. It scales up to
&lt;a href=&quot;https://download.copr.fedorainfracloud.org/resalloc/pools&quot;&gt;400 builders running simultaneously&lt;/a&gt; and peaking at
&lt;a href=&quot;https://copr.fedorainfracloud.org/status/stats/&quot;&gt;30k builds a day&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;before-bootc&quot;&gt;Before bootc&lt;/h1&gt;

&lt;p&gt;You can find some interesting history and previous numbers in Pavel’s article -
&lt;a href=&quot;https://pavel.raiskup.cz/blog/copr-farm-of-builders.html&quot;&gt;Fedora Copr farm of builders - status of July 2021&lt;/a&gt;. The part it
leaves out is how we used to generate the Copr builder images.&lt;/p&gt;

&lt;p&gt;The process is documented in the
&lt;a href=&quot;https://github.com/fedora-copr/copr/blob/4221580a0fe1d30116e5841ff5eafe27bf9baead/doc/how_to_upgrade_builders.rst&quot;&gt;official Copr documentation&lt;/a&gt;. In a nutshell, it
involved manually spawning a VM from a fresh &lt;a href=&quot;https://fedoraproject.org/cloud/download&quot;&gt;Fedora Cloud&lt;/a&gt; image,
running Ansible playbooks to provision it, and then using custom scripts to
upload the image to the right place. Because we need to build the images
natively, we had to follow this process for every architecture.&lt;/p&gt;

&lt;p&gt;The easiest workflow was for x86_64 builders running on our own hypervisors. It
meant connecting to the hypervisor using SSH and running a custom
&lt;a href=&quot;https://github.com/praiskup/helpers/blob/main/bin/copr-image.in&quot;&gt;copr-image&lt;/a&gt; script from the &lt;a href=&quot;https://github.com/praiskup/helpers/&quot;&gt;praiskup/helpers&lt;/a&gt;
repository. While its usage looks innocent, internally it had to execute many
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virt-sysprep&lt;/code&gt; commands. It also required some
&lt;a href=&quot;https://github.com/praiskup/helpers/blob/5a207be90dbd9358c7d35b1b1a664a6461d91119/bin/eimg-prep.in#L39-L86&quot;&gt;guestfish hacks&lt;/a&gt; to modify &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cloud-init&lt;/code&gt; configuration inside
of the image so that it works outside of an actual cloud. Then, finally, using
the &lt;a href=&quot;https://pagure.io/fedora-infra/ansible/blob/48f66663a43f3a3407278d21b7d4957ed29f1d1c/f/roles/copr/backend/templates/provision/upload-qcow2-images&quot;&gt;upload-qcow2-images&lt;/a&gt; script to upload the image into
libvirt.&lt;/p&gt;

&lt;p&gt;The same exact workflow for ppc64le builders. However, internally it had a
special case uploading the image also to OSU OSL OpenStack.&lt;/p&gt;

&lt;p&gt;For s390x builders, we don’t have a hypervisor where we could natively build the
image. Thus we needed to &lt;a href=&quot;https://pagure.io/fedora-infra/ansible/blob/5aea865ef90c0bfbe5b7626aeb14e932fbf40c0f/f/roles/copr/backend/files/copr-prepare-s390x-image-builder&quot;&gt;spawn a new VM in IBM Cloud&lt;/a&gt; and run
the previously mentioned &lt;a href=&quot;https://github.com/praiskup/helpers/blob/main/bin/copr-image.in&quot;&gt;copr-image&lt;/a&gt; script inside of it. Once
finished, we needed to upload the image to IBM Cloud. This is supposed to be
done using the &lt;a href=&quot;https://cloud.ibm.com/docs/cli/index.html&quot;&gt;ibmcloud&lt;/a&gt; tool, but the problem is that
&lt;a href=&quot;https://github.com/IBM-Cloud/ibm-cloud-cli-release/issues/162&quot;&gt;it is not FOSS&lt;/a&gt;, and as such, it cannot be packaged for
Fedora. We don’t want to run random binaries from the internet, so we
&lt;a href=&quot;https://github.com/praiskup/ibmcloud-cli-fedora-container&quot;&gt;containerized it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;At this point, only x86_64 and aarch64 images for Amazon AWS remain.&lt;/p&gt;

&lt;p&gt;While not straightforward to create a new AMI from a local qcow2 image, it’s
quite easy to &lt;a href=&quot;https://github.com/praiskup/resalloc-aws/blob/fe2d666501b33cb3775206790b714ef5551b41de/bin/resalloc-aws-new#L327-L342&quot;&gt;create an AMI from a running EC2 instance&lt;/a&gt;. That
was our strategy. Spawn a new instance from a fresh &lt;a href=&quot;https://fedoraproject.org/cloud/download&quot;&gt;Fedora Cloud&lt;/a&gt;
image, provision it, and then create an AMI from it.&lt;/p&gt;

&lt;h1 id=&quot;current-situation&quot;&gt;Current situation&lt;/h1&gt;

&lt;p&gt;I disliked exactly three aspects concerning the previous solution. It required a
lot of manual work, the process was different for every cloud and architecture,
and the bus factor was less than one.&lt;/p&gt;

&lt;p&gt;Even though at this moment generating a fresh set of builder images still
requires about the same amount of manual work as before, there is a potential
for future automation. By switching to &lt;a href=&quot;https://docs.fedoraproject.org/en-US/bootc/getting-started/&quot;&gt;bootc&lt;/a&gt; and
&lt;a href=&quot;https://osbuild.org/&quot;&gt;Image Builder&lt;/a&gt;, we were able to offload some dirty work to them
while also unifying the process to follow the same steps for all architectures
and clouds (with minor caveats).&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/fedora-copr/copr-image-builder/blob/main/README-bootc.md&quot;&gt;current process is temporarily documented here&lt;/a&gt;. We spawn a
VM for every architecture and use it to build the system image from our
&lt;a href=&quot;https://github.com/fedora-copr/copr-image-builder/blob/main/Containerfile&quot;&gt;Containerfile&lt;/a&gt; via the
&lt;a href=&quot;https://quay.io/repository/centos-bootc/bootc-image-builder&quot;&gt;quay.io/centos-bootc/bootc-image-builder&lt;/a&gt;. Then we fetch
the results and upload them where needed.&lt;/p&gt;

&lt;p&gt;For Amazon AWS, we can utilize the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;image-builder upload&lt;/code&gt; feature which is
amazing. But for other clouds and hypervisors, we still need our custom
&lt;a href=&quot;https://pagure.io/fedora-infra/ansible/blob/48f66663a43f3a3407278d21b7d4957ed29f1d1c/f/roles/copr/backend/templates/provision/upload-qcow2-images&quot;&gt;upload-qcow2-images&lt;/a&gt; and
&lt;a href=&quot;https://github.com/praiskup/ibmcloud-cli-fedora-container&quot;&gt;quay.io/praiskup/ibmcloud-cli&lt;/a&gt;. If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;image-builder&lt;/code&gt; could
implement the missing support and enable uploading to all of them, that would be
a major win for us.&lt;/p&gt;

&lt;h1 id=&quot;future-plans&quot;&gt;Future plans&lt;/h1&gt;

&lt;p&gt;My goal is simple, I want one-button deployment. Well, almost.&lt;/p&gt;

&lt;p&gt;When a change is made to our &lt;a href=&quot;https://github.com/fedora-copr/copr-image-builder/blob/main/Containerfile&quot;&gt;Containerfile&lt;/a&gt;, or when triggered
manually, or periodically after a period of inactivity, I want the images to be
automatically built for all architectures and uploaded to all the necessary
places. Then seeing a list of image names and AMIs that I can either choose to
use or ignore.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/osbuild/bootc-image-builder-action&quot;&gt;bootc-image-builder-action&lt;/a&gt; seems like the
perfect candidate, but the problem is that it cannot natively build images for
ppc64le and s390x.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://accounts.fedoraproject.org/user/snthrailkill/&quot;&gt;SNThrailkill&lt;/a&gt; recommended &lt;a href=&quot;https://docs.gitlab.com/runner/&quot;&gt;GitLab Runners&lt;/a&gt; but
that would require us to maintain the runner VMs, which is annoying. Moreover,
there is a potential chicken-and-egg problem, meaning that if we break our
image, we might not be able to spawn a VM to build a new working image. We also
wouldn’t be able to use the existing GitHub action and would have to port it for
GitLab.&lt;/p&gt;

&lt;p&gt;At this moment, our team is leaning towards Konflux and a tekton pipeline for
building images. Fedora Konflux instance is limited to x86_64 and aarch64, so we
would temporarily have to use an internal Red Hat instance which provides all
the architectures needed by us.&lt;/p&gt;

&lt;p&gt;Many questions are yet to be answered. Is Konflux ready? Does the pipeline for
building images already exist? Does it support everything we need? Is it built
on top of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;image-builder&lt;/code&gt; so that we can use its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upload&lt;/code&gt; feature?&lt;/p&gt;

&lt;h1 id=&quot;pitfalls-along-the-way&quot;&gt;Pitfalls along the way&lt;/h1&gt;

&lt;p&gt;Hopefully, this can help &lt;a href=&quot;https://osbuild.org/&quot;&gt;Image Builder&lt;/a&gt; and &lt;a href=&quot;https://docs.fedoraproject.org/en-US/bootc/getting-started/&quot;&gt;bootc&lt;/a&gt;
developers better understand their blind spots in the onboarding process, and
also prevent new users from repeating the same mistakes.&lt;/p&gt;

&lt;p&gt;Before discovering that &lt;a href=&quot;https://docs.fedoraproject.org/en-US/bootc/getting-started/&quot;&gt;bootc&lt;/a&gt; exists, our original approach was to use
just &lt;a href=&quot;https://osbuild.org/&quot;&gt;Image Builder&lt;/a&gt; and its &lt;a href=&quot;https://osbuild.org/docs/user-guide/blueprint-reference/&quot;&gt;blueprints&lt;/a&gt;, and
automatize the process using &lt;a href=&quot;https://packit.dev/docs/cli/build/in-image-builder&quot;&gt;Packit&lt;/a&gt;.  There were several
problems. It was easy to build the image locally from our blueprint, but it
&lt;a href=&quot;https://issues.redhat.com/browse/HMS-4884&quot;&gt;wasn’t possible to upload the same blueprint&lt;/a&gt; to be built in
a hosted Image Builder service. Additionally, I had several issues with the
&lt;a href=&quot;https://osbuild.org/docs/user-guide/blueprint-reference/&quot;&gt;Blueprint TOML format&lt;/a&gt;. The order of operations is pre-defined
(e.g. all users are always created before any packages are installed). There is
no escape hatch to run a custom command. And finally, it’s yet another
specification to learn. My recommendation? Just go with &lt;a href=&quot;https://docs.fedoraproject.org/en-US/bootc/getting-started/&quot;&gt;bootc&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Our main problem with bootc is the immutability of the filesystem. Can somebody
please help me understand whether the immutable filesystem is a fundamental
building block, a key piece of technology that enables bootable containers, or
whether it is an unrelated feature? If it is technologically possible, our team
would love to see officially supported mutable bootc base images. Currently, we
are going forward with a
&lt;a href=&quot;https://github.com/fedora-copr/copr-image-builder/commit/1fcbff98f59a7832ec5d008c5ec850998280ebe4&quot;&gt;hack to make the root filesystem transient&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One of the issues that probably stems out of the immutable filesystem is the
necessity to &lt;a href=&quot;https://github.com/fedora-copr/copr-image-builder/commit/1965820aeed581592525a4fd0fa4d55625151b4d&quot;&gt;change the default location of the RPM database&lt;/a&gt;.
This hack is baked into the bootc base images and we needed to revert it because
it causes Mock to fail under some specific circumstances. This unfortunately
cost us many many hours of debugging.&lt;/p&gt;

&lt;p&gt;The process of building system images is quite storage intensive in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/lib/containers&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/run&lt;/code&gt;. To avoid running out of disk space on our
virtual machines, we had to
&lt;a href=&quot;https://github.com/fedora-copr/copr-image-builder/blob/9311d0abb54881eb5145f4b601192df426e4cd11/prepare-worker&quot;&gt;turn our swap partition into a data volume&lt;/a&gt; and mount the
problematic directories there. Not sure if there is something that
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;image-builder&lt;/code&gt; can do to make this a less of problem.&lt;/p&gt;

&lt;p&gt;We build the system images natively on VMs of the same architecture that they
are targeted for, but then we fetch all of them to an x86_64 machine and upload
the images to the respective clouds from there. We discovered a
&lt;a href=&quot;https://github.com/osbuild/image-builder-cli/pull/218&quot;&gt;bug in cross-arch upload to AWS&lt;/a&gt;, which was promptly
confirmed and fixed by the &lt;a href=&quot;https://github.com/osbuild&quot;&gt;image-builder team&lt;/a&gt;. Big
customer satisfaction right here.&lt;/p&gt;

&lt;p&gt;We also struggled with setting up AWS permissions for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;image-builder upload&lt;/code&gt;
command to work correctly.  We tried running it, fixing the insufficient
permissions it complained about, running it again, and again, and so on.  I
don’t recommend this approach. It turns out there is a
&lt;a href=&quot;https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/7/html/image_builder_guide/chap-documentation-image_builder-test_chapter5&quot;&gt;documentation page with instructions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I hope this chapter doesn’t come across as too discouraging. In fact, we found
workarounds for all of our problems, and we are now happily using this in
production. So you can probably too.&lt;/p&gt;

</description>
        <pubDate>Tue, 17 Jun 2025 00:00:00 +0000</pubDate>
        <link>http://frostyx.cz/posts/copr-builders-powered-by-bootc</link>
        <guid isPermaLink="true">http://frostyx.cz/posts/copr-builders-powered-by-bootc</guid>
        
        <category>fedora</category>
        
        <category>copr</category>
        
        <category>bootc</category>
        
        <category>image-builder</category>
        
        
      </item>
    
      <item>
        <title>Flock to Fedora report 2025</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://fedoraproject.org/flock/&quot;&gt;Flock to Fedora&lt;/a&gt; is my favorite conference and this year was no
exception.&lt;/p&gt;

&lt;p&gt;Too many good presentations and workshops to name them all. But I want to
mention at least the most surprising (in a good way) ones. It takes some courage
to be the first person to go for a lightning talk, especially when lightning
talks aren’t even scheduled and organizers open the floor at the very
moment. &lt;a href=&quot;https://accounts.fedoraproject.org/user/smeragoel/&quot;&gt;Smera&lt;/a&gt;, I tip my hat to you. Also, I was meaning to ask,
how do graphic designers choose the FOSS project they want to work on? As an
engineer, I typically get involved in sofware that I use but is broken somehow,
or is missing some features. I am curious what is it like for you. Another
pleasant surprise was &lt;a href=&quot;https://accounts.fedoraproject.org/user/mlewando/&quot;&gt;Marta&lt;/a&gt; and her efforts to
&lt;a href=&quot;https://copr.fedorainfracloud.org/coprs/mlewando/nmbl-poc/&quot;&gt;replace grub with nmbl&lt;/a&gt;. I will definitely try having &lt;strong&gt;n&lt;/strong&gt;o &lt;strong&gt;m&lt;/strong&gt;ore
&lt;strong&gt;b&lt;/strong&gt;oot &lt;strong&gt;l&lt;/strong&gt;oader. In a VM though, I’d still like to boot my workstation :D.&lt;/p&gt;

&lt;h2 id=&quot;random-thoughts&quot;&gt;Random thoughts&lt;/h2&gt;

&lt;p&gt;We bunked with &lt;a href=&quot;https://accounts.fedoraproject.org/user/praiskup/&quot;&gt;Pavel&lt;/a&gt;, which made me
&lt;a href=&quot;/files/img/delightful.png&quot;&gt;think of this office scene&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Something happened to me repeatedly during this conference and amused me every
time. I introduced myself to a person, we talked for five minutes, and then the
person asked “so what do you do in Fedora?”. I introduced myself once more, by
my nickname. To which the immediate reaction was “Ahaaa, now I know exactly what
you do!”. I am still laughing about this. Organizers, please bring back FAS
usernames on badges.&lt;/p&gt;

&lt;p&gt;It was nice to hear &lt;a href=&quot;https://copr.fedorainfracloud.org/&quot;&gt;Copr&lt;/a&gt; casually mentioned in every other
presentation. It makes the work that much more rewarding.&lt;/p&gt;

&lt;p&gt;My favorite presentation was
&lt;a href=&quot;https://cfp.fedoraproject.org/flock-to-fedora-2025/talk/WPBWC7/&quot;&gt;Bootable Containers: Moving From Concept to Implementation&lt;/a&gt;.
I’ve spent all my free time over the last couple of months trying to create a
&lt;a href=&quot;https://github.com/fedora-copr/copr-image-builder&quot;&gt;bootc image for Copr builders&lt;/a&gt;, and seeing
&lt;a href=&quot;https://accounts.fedoraproject.org/user/snthrailkill/&quot;&gt;Sean&lt;/a&gt; falling into and crawling out of all the same traps as
myself was just cathartic. We later talked in the hallway and I appreciated how
quickly he matched my enthusiasm about the project. He gave me some valuable
advice regarding CI/CD for the system images. Man, now I am even more hyped.&lt;/p&gt;

&lt;p&gt;I learned about &lt;a href=&quot;https://docs.fedoraproject.org/en-US/marketing/ready/&quot;&gt;Fedora Ready&lt;/a&gt;, an amazing initiative to partner
with laptop vendors and provide &lt;a href=&quot;https://docs.fedoraproject.org/en-US/marketing/ready/list/#fedora-ready-approved-devices&quot;&gt;a list of devices&lt;/a&gt; that
officially support Fedora. &lt;a href=&quot;https://slimbook.com/en/&quot;&gt;Slimbook&lt;/a&gt; loves Fedora so much that they
even offer a &lt;a href=&quot;https://slimbook.com/en/fedora&quot;&gt;laptop with Fedora engravings&lt;/a&gt;. How amazing would
it be if my employer provided this option for a company laptop? What surprised
me, was not seeing &lt;a href=&quot;https://system76.com/&quot;&gt;System76&lt;/a&gt; on the list. I am a fan of theirs, so I
am considering reaching out.&lt;/p&gt;

&lt;p&gt;Feeling a tap on your shoulder 30 seconds after you push a commit is never a
good sign. When you turn around, &lt;a href=&quot;https://accounts.fedoraproject.org/user/ksurma/&quot;&gt;Karolina&lt;/a&gt; is looking into your eyes
and saying that f’d up, you immediately know that push was a bad idea. For a
petite lady, she can be quite terrifying :D. I am exaggerating for effect. We
had a nice chat afterward and I pitched an idea for an RPM macro that would
remove capped versions from &lt;a href=&quot;https://github.com/python-poetry/poetry&quot;&gt;Poetry&lt;/a&gt; dependencies. That should make our
lives easier, no?&lt;/p&gt;

&lt;p&gt;One of my favorite moments this year was chilling out with &lt;a href=&quot;https://accounts.fedoraproject.org/user/zbyszek/&quot;&gt;Zbigniew&lt;/a&gt;
on a boat deck, cruising the Vltava River, and watching the sunset over the
beautiful city of Prague. Kinda romatic if you ask me. Just joking, but indeed,
it was my pleasure to get to know you Zbigniew.&lt;/p&gt;

&lt;h2 id=&quot;the-jeffpl-exchange&quot;&gt;The JefFPL exchange&lt;/h2&gt;

&lt;p&gt;The conference began with a bittersweet moment - the passing of the Fedora
Project Leadership mantle from &lt;a href=&quot;https://accounts.fedoraproject.org/user/mattdm/&quot;&gt;Matthew Miller&lt;/a&gt; to
&lt;a href=&quot;https://accounts.fedoraproject.org/user/jspaleta/&quot;&gt;Jeff Spaleta&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I didn’t know Jeff before, probably because he was busy doing really effin cool
stuff in Alaska, but we had an opportunity to chat in the hallway after the
session. He is friendly, well-spoken, and not being afraid to state his
opinions. Good qualities for a leader. That being said, Matthew left giant shoes
to fill, so I think it is reasonable not to be overly enthusiastic about the
change just yet.&lt;/p&gt;

&lt;p&gt;Matthew, best wishes in your next position, but at the same time, we are sad to
see you go.&lt;/p&gt;

&lt;h2 id=&quot;fesco-and-fedora-council&quot;&gt;FESCo and Fedora Council&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://cfp.fedoraproject.org/flock-to-fedora-2025/talk/ERLNR9/&quot;&gt;FESCo Q&amp;amp;A&lt;/a&gt; and the &lt;a href=&quot;https://cfp.fedoraproject.org/flock-to-fedora-2025/talk/FKVCHK/&quot;&gt;Fedora Council AMA&lt;/a&gt; were
two different sessions on two different days, but I am lumping them together
here. Both of them dealt with an
&lt;a href=&quot;https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org/thread/BQIXJAZXUMGOHLTNJHAZFHWVTF7PIATB/#SCO44FAQ5INRIKCVESB43LZHAJBQKCDR&quot;&gt;unspecified Proven Packager incident&lt;/a&gt;, the lack of communication
surrounding it, and the inevitable loss of trust as a consequence.&lt;/p&gt;

&lt;p&gt;I respectfully disagree with this sentiment.&lt;/p&gt;

&lt;p&gt;Let’s assume &lt;a href=&quot;https://docs.fedoraproject.org/en-US/fesco/&quot;&gt;FESCo&lt;/a&gt; actions were wrong. So what?  I mean,
really. Everybody makes mistakes. I wrote bugfixes that introduced twice as many
new bugs, I accidentally removed data in production, and I am regularly wrong in
my PR comments. Yet I wasn’t fired, demoted, or lost any trust from the
community. Everybody makes mistakes, it’s par for the course. &lt;strong&gt;Even if&lt;/strong&gt;
&lt;a href=&quot;https://docs.fedoraproject.org/en-US/fesco/&quot;&gt;FESCo&lt;/a&gt; made a mistake (I am not in the position to judge whether they
did or not), it would not overshadow the majority of decisions they made
right. They didn’t lose any of my trust.&lt;/p&gt;

&lt;p&gt;As for the policies governing &lt;a href=&quot;https://docs.fedoraproject.org/en-US/fesco/Provenpackager_policy/&quot;&gt;Proven Packagers&lt;/a&gt;, one incident
in a decade does not necessarily imply that new rules are needed. It’s possible
to just make a gentlemen’s agreement, shake hands, and move on.&lt;/p&gt;

&lt;p&gt;That being said, I wanted to propose the same thing as
&lt;a href=&quot;https://accounts.fedoraproject.org/user/bookwar/&quot;&gt;Alexandra Fedorova&lt;/a&gt;. Proven Packagers are valuable in emergencies,
and I think, it is a bad idea to disband them. But requiring +1 from at least
one other person before pushing changes, makes sense to me. Alexandra proposed
+1 from at least one other Proven Packager, but I would broaden the eligible
reviewers to also include &lt;a href=&quot;https://docs.pagure.org/fedora-sponsors/&quot;&gt;Packager Sponsors&lt;/a&gt; and
&lt;a href=&quot;https://docs.fedoraproject.org/en-US/fesco/&quot;&gt;FESCo&lt;/a&gt; members. I would also suggest requiring the name of the reviewer
to be clearly mentioned in the commit description.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Don’t be sad if you missed the conference. &lt;a href=&quot;https://www.youtube.com/@fedora/streams&quot;&gt;There are recordings&lt;/a&gt;.&lt;/p&gt;

</description>
        <pubDate>Mon, 09 Jun 2025 00:00:00 +0000</pubDate>
        <link>http://frostyx.cz/posts/flock-to-fedora-report-2025</link>
        <guid isPermaLink="true">http://frostyx.cz/posts/flock-to-fedora-report-2025</guid>
        
        <category>fedora</category>
        
        <category>flock</category>
        
        <category>report</category>
        
        
      </item>
    
      <item>
        <title>Shoving a chess engine up your butt</title>
        <description>&lt;p&gt;In the Lex Fridman Podcast &lt;a href=&quot;https://www.youtube.com/watch?v=iSMpTmibeDw&amp;amp;t=8743s&quot;&gt;episode #327&lt;/a&gt;, Levy Rozman (aka
&lt;a href=&quot;https://www.youtube.com/gothamchess&quot;&gt;GothamChess&lt;/a&gt;) explained a scandal, alleging a chess grandmaster
Hans Niemann of cheating at a tournament. Supposedly, it was done through a
remotely controlled device inserted into his backside, allowing him to receive
the next best move encoded in Morse code vibrations. And because I am evidently
twelve years old, I thought it would be really funny to implement this. By the
way, &lt;a href=&quot;https://github.com/RonSijm&quot;&gt;Ron Sijm&lt;/a&gt; is likely as immature as me, because he
&lt;a href=&quot;https://github.com/RonSijm/ButtFish&quot;&gt;beat me to it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Disclaimer: I am not endorsing cheating in chess or any other sport, I don’t
know if the allegations were true or not, and to be honest, I don’t care. I don’t know any of
the people involved, and I don’t even play chess. This project is just for shits
and giggles, not so that y’all can experience more pleasure during chess
tournaments.&lt;/p&gt;

&lt;h2 id=&quot;two-minute-demo&quot;&gt;Two-minute demo&lt;/h2&gt;

&lt;p&gt;This post is too long and you will probably not read it. So here is a fun demo
of the final product.&lt;/p&gt;

&lt;div class=&quot;text-center img-row row&quot;&gt;
&lt;iframe width=&quot;784&quot; height=&quot;441&quot; src=&quot;https://www.youtube.com/embed/HAxBOoBoVTM?si=iuqvAYfn11vl1ffi&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;h2 id=&quot;scope-of-the-project&quot;&gt;Scope of the project&lt;/h2&gt;

&lt;p&gt;At our disposal, we have several chess engines capable of beating any human. We
also have a large offering of intimate hardware built on top of open
standards. The most straightforward way to encode chess moves is the Morse code,
even though it is not the most effective choice in this situation. Squares on
chess boards go from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a1&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h8&lt;/code&gt;, which leaves us with two-thirds of the
alphabet unused, making the code for every character n-times (I am bad at math)
longer than necessary. However, creating an optimized encoding is outside
the scope of this project.&lt;/p&gt;

&lt;p&gt;Playing one side of the chess board will be a two-man job. The agent in the
field, receiving intelligence through his anal cavity, and the operator behind
the computer monitor, querying a chess engine through the interface we will
create.&lt;/p&gt;

&lt;p&gt;Joking aside, I could probably crank out a working solution in Python in under
an hour just by gluing &lt;a href=&quot;https://github.com/magmax/python-inquirer&quot;&gt;inquirer&lt;/a&gt;, &lt;a href=&quot;https://pypi.org/project/stockfish/&quot;&gt;stockfish&lt;/a&gt;,
&lt;a href=&quot;https://github.com/morse-talk/morse-talk&quot;&gt;morse-talk&lt;/a&gt;, and &lt;a href=&quot;https://github.com/Siege-Wizard/buttplug-py&quot;&gt;buttplug-py&lt;/a&gt; together. But where
would be the fun in that? That’s why I am going to learn a new programming
language on this project.&lt;/p&gt;

&lt;h2 id=&quot;chess-engines&quot;&gt;Chess engines&lt;/h2&gt;

&lt;p&gt;There are several chess engines to choose from, such as &lt;a href=&quot;https://stockfishchess.org/&quot;&gt;Stockfish&lt;/a&gt;,
&lt;a href=&quot;https://en.wikipedia.org/wiki/AlphaZero&quot;&gt;AlphaZero&lt;/a&gt;, &lt;a href=&quot;https://lczero.org/&quot;&gt;Lc0&lt;/a&gt;, &lt;a href=&quot;https://www.shredderchess.com/&quot;&gt;Shredder&lt;/a&gt;, etc. Some of them
giving us a choice between running them locally or spawning an instance
&lt;a href=&quot;https://lichess.org/api&quot;&gt;through lichess.org&lt;/a&gt;. I randomly picked Stockfish out of the hat
because it is an open-source project, and it is easy to run locally.&lt;/p&gt;

&lt;p&gt;Chess grandmasters average around 2600 Elo rating, and according to Gary
Linscott, &lt;a href=&quot;https://youtu.be/CdFLEfRr3Qk?t=70&quot;&gt;Stockfish performs at 3600 Elo&lt;/a&gt;. Don’t worry that it
won’t beat our opponents.&lt;/p&gt;

&lt;p&gt;To keep things simple, we can say that chess engines are services running in the
background (and liken them to Unix daemons). They don’t have any graphical
interfaces or CLI tools for interacting with them. At least not tools in the
conventional sense. Instead, third-party programs can communicate with chess
engines through the &lt;a href=&quot;https://en.wikipedia.org/wiki/Universal_Chess_Interface&quot;&gt;Universal Chess Interface&lt;/a&gt; (UCI).&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;$ stockfish&lt;/span&gt;
&lt;span class=&quot;&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;uci&lt;/span&gt;
&lt;span class=&quot;&quot;&gt;id name Stockfish 17&lt;/span&gt;
&lt;span class=&quot;&quot;&gt;id author the Stockfish developers (see AUTHORS file)&lt;/span&gt;
&lt;span class=&quot;&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;&quot;&gt;uciok&lt;/span&gt;
&lt;span class=&quot;&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;isready&lt;/span&gt;
&lt;span class=&quot;&quot;&gt;readyok&lt;/span&gt;
&lt;span class=&quot;&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;ucinewgame&lt;/span&gt;
&lt;span class=&quot;&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;position startpos moves a2a3 h7h6 b2b3&lt;/span&gt;
&lt;span class=&quot;&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;go depth 15&lt;/span&gt;
&lt;span class=&quot;&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;&quot;&gt;bestmove d7d5 ponder c1b2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, Stockfish provides a painfully bad REPL and UCI arms as with a
set of usable commands. There is no TAB completion, no help, no command
history, no syntax highlighting, no prompt to distinguish between commands and
their output, and so on. For better readability, I rendered the inputs red, but
in the terminal, everything is the same color.&lt;/p&gt;

&lt;p&gt;In this session, we started the game, white moved from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a2&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a3&lt;/code&gt;, black moved
from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h7&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h6&lt;/code&gt;, then again white moved from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b2&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b3&lt;/code&gt;. Stockfish then
recommends black to move from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d7&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d5&lt;/code&gt; and expect white to retaliate with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c1&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b2&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;gleam-elixir-and-the-beam&quot;&gt;Gleam, Elixir, and the BEAM&lt;/h2&gt;

&lt;p&gt;One of my goals for this project was to learn &lt;a href=&quot;https://gleam.run/&quot;&gt;Gleam&lt;/a&gt;, which is a new
addition to the &lt;a href=&quot;https://en.wikipedia.org/wiki/BEAM_(Erlang_virtual_machine)#BEAM_Languages&quot;&gt;BEAM family of languages&lt;/a&gt;, preceded by
&lt;a href=&quot;https://www.erlang.org/&quot;&gt;Erlang&lt;/a&gt; and &lt;a href=&quot;https://elixir-lang.org/&quot;&gt;Elixir&lt;/a&gt;. The main purpose of these languages is to
be used for building massively distributed, high-availability systems. So I will
be the first one to admit that this project doesn’t exactly fit the
use-case. Who knows, maybe I plan to build some distributed system in the future
and treat this project as a means to learn the languages.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/BEAM_(Erlang_virtual_machine)&quot;&gt;BEAM&lt;/a&gt; is a virtual machine for running Erlang bytecode in the same sense
that JVM is a virtual machine for Java, and .NET is a &lt;del&gt;virtual machine&lt;/del&gt;
platform for C#. And just as Java, Clojure and Scala compile to the JVM
bytecode, C#, Visual Basic, and F# compile to the &lt;a href=&quot;https://en.wikipedia.org/wiki/Common_Intermediate_Language&quot;&gt;.NET bytecode&lt;/a&gt;, Erlang,
Elixir, and Gleam compile to the BEAM bytecode. Allowing us to share code
across the related languages.&lt;/p&gt;

&lt;p&gt;The main part of this project will be written in Gleam, but we will use Elixir
interop for some peripherals. Starting with one of them right now. To control
Stockfish we can use &lt;a href=&quot;https://hexdocs.pm/elixir/Port.html&quot;&gt;Elixir ports&lt;/a&gt;, which is the best abstraction
for interacting with stdin-based programs that I’ve ever seen.&lt;/p&gt;

&lt;div class=&quot;language-elixir highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;defmodule&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Stockfish&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_game&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:spawn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;stockfish&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:binary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;uci&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;isready&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ucinewgame&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At the, we are returning the port, so we can pass it to other functions. To
implement a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;move&lt;/code&gt; function for example.&lt;/p&gt;

&lt;div class=&quot;language-elixir highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;defmodule&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Stockfish&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;history&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;moves&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;history&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Enum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Enum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;position startpos moves &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;moves&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You wouldn’t believe how easy it is to use this code from Gleam through
&lt;a href=&quot;https://tour.gleam.run/advanced-features/externals/&quot;&gt;externals&lt;/a&gt;. Since Gleam is statically typed, we need to tell
the compiler the shape of our Elixir functions, but that’s all.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;gleam&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;erlang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;erlang&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Elixir.Stockfish&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;new_game&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;new_game&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Port&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;erlang&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Elixir.Stockfish&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;game&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;history&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For illustrative purposes, we are going to avoid the domain-specific type
masturbation and stick with lists and strings. In the actual implementation,
we’ll likely want to avoid exposing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Port&lt;/code&gt; directly, and create custom types
for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Position&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;History&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now we can use the functions in Gleam.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;new_game&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;a2a3&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;morse-code&quot;&gt;Morse code&lt;/h2&gt;

&lt;p&gt;Several packages for encoding and decoding Morse code were available, but I
decided to write my own called &lt;a href=&quot;https://github.com/FrostyX/morsey&quot;&gt;Morsey&lt;/a&gt;. I don’t expect any rapid
development in the Morse code department, causing this reinvention of the wheel
to be the final blow to my personal life, and putting me on a hamster wheel of
perpetual maintenance of my Open Source projects.&lt;/p&gt;

&lt;p&gt;The source code is available in &lt;a href=&quot;https://github.com/FrostyX/morsey&quot;&gt;FrostyX/morsey&lt;/a&gt; repository, and look,
we already got a star from the one and only &lt;a href=&quot;https://github.com/hayleigh-dot-dev&quot;&gt;Hayleigh Thompson&lt;/a&gt;. The
package can be used like this:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;gleam&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;io&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;morsey&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Hello world!&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;morsey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;symbols&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Morse code for &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; is &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;morsey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;to_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;symbols&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;morsey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;InvalidCharacter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;println_error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Invalid character: &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// And the output will be:&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// .... . .-.. .-.. --- / .-- --- .-. .-.. -.. -.-.--&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can see several Gleam features in this example. It doesn’t have exceptions
and instead returns errors as values. It leans heavily towards pattern
matching, there is not even an if-else statement in the language. The pattern
matching is exhaustive, otherwise, I would definitely forget to handle the
error case. I love all of these features. The one I quite dislike, however, is
that for the sake of simplicity, Gleam doesn’t support string formatting.&lt;/p&gt;

&lt;h2 id=&quot;intimate-hardware&quot;&gt;Intimate hardware&lt;/h2&gt;

&lt;p&gt;On paper, hardware should’ve been the easy part. There is an
&lt;a href=&quot;https://iostindex.com/?filter0Availability=Available,DIY&amp;amp;filter1Connection=Digital&quot;&gt;exhaustive list&lt;/a&gt; of manufacturers and devices supported by
the &lt;a href=&quot;https://buttplug.io/&quot;&gt;buttplug.io&lt;/a&gt; project. I randomly picked some device that was
possible to buy in Czech Republic. It paired with my phone within seconds, so I
started celebrating an easy victory, just to waste the rest of the day trying to
pair the device with my computer.&lt;/p&gt;

&lt;p&gt;Here is the ten-thousand-foot view. A toy communicates with your computer via Bluetooth LE. Some manufacturers
require &lt;a href=&quot;https://faq.docs.buttplug.io/hardware/bluetooth.html#when-should-i-pair-my-device-with-my-operating-system&quot;&gt;pairing before use&lt;/a&gt;, some don’t. You don’t use the system
Bluetooth manager to connect to the device. Clients like
&lt;a href=&quot;https://github.com/Siege-Wizard/buttplug-py&quot;&gt;buttplug-py&lt;/a&gt;, &lt;a href=&quot;https://github.com/buttplugio/buttplug-js&quot;&gt;buttplug-js&lt;/a&gt;, &lt;a href=&quot;https://github.com/buttplugio/awesome-buttplug?tab=readme-ov-file#development-and-libraries&quot;&gt;etc&lt;/a&gt;,
don’t control the toy directly, they only communicate with a server like
&lt;a href=&quot;https://github.com/intiface/intiface-engine&quot;&gt;intiface-engine&lt;/a&gt; via websockets. The server then does the heavy
lifting. You can run the server like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cargo install intiface-engine
$ ~/.cargo/bin/intiface-engine --websocket-port 12345 --use-bluetooth-le
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;websockets&quot;&gt;Websockets&lt;/h2&gt;

&lt;p&gt;The previous chapter linked officially supported libraries that provide a
high-level interface to control the devices. However, there weren’t any for the
BEAM family of languages, so I had to raw-dog the websocket communication. It’s
almost embarrassing that in fifteen years of programming, I have never used
websockets, and this was my first exposure.&lt;/p&gt;

&lt;p&gt;An example session can look like this
(The snippet only shows messages from the client to the server. The responses were
omitted).&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cargo install websocat
$ ~/.cargo/bin/websocat ws://127.0.0.1:12345/
[{&quot;RequestServerInfo&quot;: {&quot;ClientName&quot;: &quot;Test Client&quot;, &quot;MessageVersion&quot;: 1, &quot;Id&quot;: 1}}]
[{&quot;RequestDeviceList&quot;: {&quot;Id&quot;: 2}}]
[{&quot;StartScanning&quot;: {&quot;Id&quot;: 3}}]
[{&quot;VibrateCmd&quot;: {&quot;DeviceIndex&quot;: 0, &quot;Speeds&quot;: [{&quot;Index&quot;: 0, &quot;Speed&quot;: 500}], &quot;Id&quot;: 4}}]
[{&quot;StopDeviceCmd&quot;: {&quot;DeviceIndex&quot;: 0, &quot;Id&quot;: 5}}]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I created a Gleam package with a high-level interface around this, called
&lt;a href=&quot;https://github.com/FrostyX/bummer&quot;&gt;Bummer&lt;/a&gt;. Its usage is fairly simple.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bummer&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bummer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;ws://127.0.0.1:12345/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Connected to intiface-engine websocket&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Initiating a test sequence&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;bummer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;bummer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;vibrate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;bummer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rotate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Test sequence finished&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Cannot connect to intiface-engine websocket. Is it running?&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;println_error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The public API is leaking some internals. The users probably don’t even want to
know what communication protocol is being used, and it should be treated as an
implementation detail. This calls for more custom types.&lt;/p&gt;

&lt;p&gt;Also, websockets are a bi-directional protocol but &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bummer&lt;/code&gt; is currently
unidirectional. It was really easy to send messages to the server but due to the
Gleam + Elixir interop, I couldn’t figure out how to properly handle messages
from the server. I started running out of time, so this remains unfinished. PRs
are more then welcome.&lt;/p&gt;

&lt;h2 id=&quot;tying-it-all-together&quot;&gt;Tying it all together&lt;/h2&gt;

&lt;p&gt;Throughout this blog post, we’ve seen code snippets for communicating
with Stockfish, converting text to Morse code, and controlling intimate toys
via websockets. The last missing piece is vibrating a Morse code sequence.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;vibrate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bummer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Connection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sequence&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;morsey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Sequence&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Nil&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// International Morse Code&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// 1. The length of a dot is one unit.&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// 2. A dash is three units.&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// 3. The space between parts of the same letter is one unit.&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// 4. The space between letters is three units.&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// 5. The space between words is seven units.&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;interval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sequence&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Nil&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;morsey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Dot&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bummer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;vibrate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;morsey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Comma&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bummer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;vibrate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;interval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;morsey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Space&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;interval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;morsey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Break&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;interval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;morsey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Invalid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Nil&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;vibrate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;All code is available in my &lt;a href=&quot;https://github.com/FrostyX/crooked-rook&quot;&gt;FrostyX/crooked-rook&lt;/a&gt; repository.&lt;/p&gt;

&lt;h2 id=&quot;a-room-for-improvement&quot;&gt;A room for improvement&lt;/h2&gt;

&lt;p&gt;This being a fun little project to keep myself busy over the holidays, having no
real use-case, and providing zero value to anyone, it had to be cut short. Codes
for letters in the Morse alphabet are too long. One could come up with much more
effective encoding. Additionally, there is no need to encode the whole move
(e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a2a3&lt;/code&gt;). An experienced chess player can infer the starting position
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a2&lt;/code&gt;) from the end position (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a3&lt;/code&gt;). These two combined improvements would
result in significantly shorter
messages.&lt;/p&gt;

&lt;p&gt;The other limitation is having a human relay between the player and the chess
engine. I am sure there are AI models capable of observing a chessboard and
recognizing all the figures and their positions. The whole system could be
autonomous with the exception of the human player.&lt;/p&gt;

&lt;p&gt;Sounds like a pt.2 next holiday?&lt;/p&gt;

</description>
        <pubDate>Sun, 29 Dec 2024 00:00:00 +0000</pubDate>
        <link>http://frostyx.cz/posts/shoving-a-chess-engine-up-your-butt</link>
        <guid isPermaLink="true">http://frostyx.cz/posts/shoving-a-chess-engine-up-your-butt</guid>
        
        <category>chess</category>
        
        <category>morse</category>
        
        <category>gleam</category>
        
        <category>elixir</category>
        
        <category>meme</category>
        
        
      </item>
    
      <item>
        <title>Copr Modularity, the End of an Era</title>
        <description>&lt;p&gt;Our team has put a lot of effort into the possibility of
&lt;a href=&quot;https://docs.fedoraproject.org/en-US/modularity/building-modules/copr/building-modules-in-copr/&quot;&gt;building modules in Copr&lt;/a&gt;.  This feature went through
&lt;a href=&quot;https://frostyx.cz/posts/copr-modularity-in-retrospect&quot;&gt;many iterations and rewrites from scratch&lt;/a&gt; as the
concepts, requirements, and goals of &lt;a href=&quot;https://docs.pagure.org/modularity/&quot;&gt;Fedora Modularity&lt;/a&gt; kept
changing. This will be my last article about this topic because we are planning
to drop Modularity and all of its functionality from Copr. The only exceptions
are &lt;a href=&quot;https://frostyx.cz/posts/module-hotfixes-in-copr&quot;&gt;Module hotfixes&lt;/a&gt; and &lt;a href=&quot;https://docs.copr.fedorainfracloud.org/user_documentation.html#modularity&quot;&gt;module dependencies&lt;/a&gt;,
which are staying for good (until they are supported by Mock and DNF).&lt;/p&gt;

&lt;h2 id=&quot;why&quot;&gt;Why?&lt;/h2&gt;

&lt;p&gt;The Fedora Modularity project never really took off, and building modules in
Copr even less so.  We’ve had only 14 builds in the last two years. It’s not
feasible to maintain the code for so few users. Modularity has also been
&lt;a href=&quot;https://fedoraproject.org/wiki/Changes/RetireModularity&quot;&gt;retired since Fedora 39&lt;/a&gt; and will die with RHEL 9.&lt;/p&gt;

&lt;div class=&quot;text-center img-row row&quot;&gt;
  &lt;div style=&quot;width:550px;font-size:17px;display:inline-block;&quot;&gt;
    &lt;svg class=&quot;line-chart&quot;&gt;&lt;/svg&gt;
    &lt;script src=&quot;https://cdn.jsdelivr.net/npm/chart.xkcd@1/dist/chart.xkcd.min.js&quot;&gt;&lt;/script&gt;
    &lt;script&gt;
      const svg = document.querySelector(&apos;.line-chart&apos;)
      new chartXkcd.Line(svg, {
          title: &apos;Copr module builds throughout the years&apos;,
          data: {
              labels:[&apos;2015&apos;, &apos;2016&apos;, &apos;2017&apos;, &apos;2018&apos;, &apos;2019&apos;, &apos;2020&apos;,&apos;2021&apos;, &apos;2022&apos;, &apos;2023&apos;, &apos;2024&apos;],
              datasets: [{
                  data: [0, 11, 67, 86, 82, 95, 63, 54, 5, 9],
              }]
          },
          options: {yTickCount: 5}
      });
    &lt;/script&gt;
    &lt;noscript&gt;Enable Javascript to see a cute XKCD looking chart.&lt;/noscript&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Additionally, one of our larger goals for the upcoming years is to start using
&lt;a href=&quot;https://github.com/fedora-copr/copr/issues/2533&quot;&gt;Pulp as a storage for all Copr build results&lt;/a&gt;. This requires
rewriting several parts of the backend code. Factoring in reimplementation for
module builds would result in many development hours wasted for very little
benefit. All projects with modules will remain in the current storage until the
Modularity is finally dropped.&lt;/p&gt;

&lt;h2 id=&quot;schedule&quot;&gt;Schedule&lt;/h2&gt;

&lt;p&gt;In the ideal world, we would keep the feature available as long as RHEL 9 is
supported, but we cannot wait until &lt;a href=&quot;https://access.redhat.com/support/policy/updates/errata&quot;&gt;2032&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;October 2024 - All Modularity features in Copr are now deprecated&lt;/li&gt;
  &lt;li&gt;April 2025 - It won’t be possible to submit new module builds&lt;/li&gt;
  &lt;li&gt;October 2025 - Web UI and API endpoints for getting module information will
disappear&lt;/li&gt;
  &lt;li&gt;April 2026 - All module information will be removed from the database, and
their build results will be removed from our storage&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;communication&quot;&gt;Communication&lt;/h2&gt;

&lt;p&gt;It was me who introduced all the Modularity code into Copr, so it should also be
me who decommissions it. Feel free to ping me directly if you have any questions
or concerns, but you are also welcome to reach out on the
&lt;a href=&quot;https://matrix.to/#/#buildsys:fedoraproject.org&quot;&gt;Copr Matrix channel&lt;/a&gt;, &lt;a href=&quot;https://lists.fedorahosted.org/archives/list/copr-devel@lists.fedorahosted.org/&quot;&gt;mailing list&lt;/a&gt;, or in the form of
&lt;a href=&quot;https://github.com/fedora-copr/copr/issues&quot;&gt;GitHub issues&lt;/a&gt;. In the meantime, I will contact everybody who
submitted a module build in Copr in the past two years and make sure they don’t
rely on this feature.&lt;/p&gt;

</description>
        <pubDate>Wed, 23 Oct 2024 00:00:00 +0000</pubDate>
        <link>http://frostyx.cz/posts/copr-modularity-the-end-of-an-era</link>
        <guid isPermaLink="true">http://frostyx.cz/posts/copr-modularity-the-end-of-an-era</guid>
        
        <category>copr</category>
        
        <category>fedora</category>
        
        <category>modularity</category>
        
        
      </item>
    
      <item>
        <title>Ruff my dirty code</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://luminousmen.com/post/python-static-analysis-tools&quot;&gt;Static analysis tools&lt;/a&gt; have their limitations but
regardless they help us quickly discover many types of bugs. That is not a
controversial take. What may be disputed is whether enabling them for large
projects with a long-standing history is worth the effort and I would say it
most definitely is.  In this article will take a look at how to report problems
only for new code, lowering the barrier to entry to the minimum.&lt;/p&gt;

&lt;h2 id=&quot;the-dilemma&quot;&gt;The dilemma&lt;/h2&gt;

&lt;p&gt;Creating a new project from scratch is so enjoyable, isn’t it? No technical
debt, no backward compatibility, no compromises, all the code is beautifully
formatted and brilliantly architected. We don’t really need to run any static
analysis tools but we do it anyway just so that they can say that “All checks
passed!” and that we are awesome. Obviously, I am being sarcastic, but the point
is that enabling such tools for new projects is easy.&lt;/p&gt;

&lt;p&gt;Now, let’s consider projects that have been developed in the span of
decades. Everything is a mess. Running &lt;a href=&quot;https://github.com/pylint-dev/pylint&quot;&gt;pylint&lt;/a&gt;, &lt;a href=&quot;https://github.com/python/mypy&quot;&gt;mypy&lt;/a&gt; or
&lt;a href=&quot;https://github.com/astral-sh/ruff&quot;&gt;ruff&lt;/a&gt; overwhelms you with hundreds or thousands of reports and leaves you
with the following dilemma - Should you just abandon all hope and pretend that
this never happened?  Should you pollute your codebase with a bunch of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#
pylint: disable=foo&lt;/code&gt; comments? Or should you devote the next month of your life
to rewriting all the problematic code while risking to introduce even more bugs
in the process?&lt;/p&gt;

&lt;p&gt;There is one more option that worked for our team quite well for years now -
running static analysis tools for the whole project but reporting only
newly introduced problems.&lt;/p&gt;

&lt;h2 id=&quot;reporting-only-new-problems&quot;&gt;Reporting only new problems&lt;/h2&gt;

&lt;p&gt;There is a tool called &lt;a href=&quot;https://github.com/csutils/csdiff&quot;&gt;csdiff&lt;/a&gt; which takes two lists of defects
(formatted errors from static analysis tools), compares them, and prints only
defects that newly appeared or that are missing from the second list. This can
be understood either as newly added or fixed defects.&lt;/p&gt;

&lt;p&gt;We created a tool called &lt;a href=&quot;https://github.com/fedora-copr/vcs-diff-lint&quot;&gt;vcs-diff-lint&lt;/a&gt; which does the obvious
thing. It runs &lt;a href=&quot;https://github.com/pylint-dev/pylint&quot;&gt;pylint&lt;/a&gt;, &lt;a href=&quot;https://github.com/python/mypy&quot;&gt;mypy&lt;/a&gt;, and &lt;a href=&quot;https://github.com/astral-sh/ruff&quot;&gt;ruff&lt;/a&gt; for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt;
branch of your git repository, and then runs them again for your current
branch. There we have our two lists of defects which get internally passed to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;csdiff&lt;/code&gt;. The output looks like this.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ vcs-diff-lint
Error: RUFF_WARNING:
fedora_distro_aliases/__init__.py:23:20: F821[undefined-name]: Undefined name `requests`

Error: MYPY_ERROR:
fedora_distro_aliases/__init__.py:11: mypy[error]: &quot;None&quot; has no attribute &quot;append&quot;  [attr-defined]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can clearly see that our code introduced two new errors. Sometimes it may be
useful to also see how many existing errors our code fixed. In that case, use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vcs-diff-lint --print-fixed-errors&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Please follow the &lt;a href=&quot;https://github.com/fedora-copr/vcs-diff-lint&quot;&gt;installation instructions&lt;/a&gt; here.&lt;/p&gt;

&lt;h2 id=&quot;github-action&quot;&gt;Github Action&lt;/h2&gt;

&lt;p&gt;I don’t trust myself (or anyone else for that matter) to run the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vcs-diff-lint&lt;/code&gt;
tool manually for every proposed change. And neither should you. There is an
easy-to-use &lt;a href=&quot;https://github.com/fedora-copr/vcs-diff-lint-action&quot;&gt;GitHub action&lt;/a&gt; that runs the tool automatically for
every pull request. It tries to be as user-friendly as possible and reports the
problems as comments directly in your “Files changed” section.&lt;/p&gt;

&lt;div class=&quot;text-center img-row row&quot;&gt;
  &lt;a href=&quot;/files/img/vcs-diff-lint-github.png&quot; title=&quot;vcs-diff-lint action commenting your code&quot;&gt;
    &lt;img src=&quot;/files/img/vcs-diff-lint-github.png&quot; /&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Please follow the &lt;a href=&quot;https://github.com/fedora-copr/vcs-diff-lint-action&quot;&gt;installation instructions&lt;/a&gt; here or take a
look at &lt;a href=&quot;https://github.com/fedora-copr/copr/blob/main/.github/workflows/python-diff-lint.yml&quot;&gt;our setup&lt;/a&gt; as an example.&lt;/p&gt;

&lt;h2 id=&quot;ruff-support&quot;&gt;Ruff support&lt;/h2&gt;

&lt;p&gt;Ruff is all the rage nowadays, and rightfully so. It checks our whole codebase
in under a second (20ms actually) while mypy takes its sweet time and finishes
around a one-minute mark. Up until recently, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vcs-diff-lint&lt;/code&gt; tool supported
only &lt;a href=&quot;https://github.com/pylint-dev/pylint&quot;&gt;pylint&lt;/a&gt; and &lt;a href=&quot;https://github.com/python/mypy&quot;&gt;mypy&lt;/a&gt; but since the last release, &lt;a href=&quot;https://github.com/astral-sh/ruff&quot;&gt;ruff&lt;/a&gt;
is supported as well. Please give it a try.&lt;/p&gt;

&lt;p&gt;As a matter of fact, I am writing this article as a celebration of the
&lt;a href=&quot;https://github.com/fedora-copr/vcs-diff-lint/releases/tag/vcs-diff-lint-6.1-1&quot;&gt;new vcs-diff-lint release&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;but-what-about-diff-cover&quot;&gt;But what about diff-cover&lt;/h2&gt;

&lt;p&gt;Speaking about differential static analysis, you may have already heard about
&lt;a href=&quot;https://github.com/Bachmann1234/diff_cover&quot;&gt;diff-cover&lt;/a&gt;. It has many more contributors and GitHub stars so why
would I recommend trying &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vcs-diff-lint&lt;/code&gt; instead?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diff-cover&lt;/code&gt; runs static analysis for the whole project but reports only
problems for lines changed by the patch. This can’t fundamentally catch
problems caused by the changed code but lying outside of it. For example when
you add a parameter to a function definition but forget to update all of its
calls&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diff-cover&lt;/code&gt; doesn’t provide a GitHub action&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vcs-diff-lint&lt;/code&gt; supports &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ruff&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ruff&lt;/code&gt; is cool now&lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Tue, 17 Sep 2024 00:00:00 +0000</pubDate>
        <link>http://frostyx.cz/posts/ruff-my-dirty-code</link>
        <guid isPermaLink="true">http://frostyx.cz/posts/ruff-my-dirty-code</guid>
        
        <category>ruff</category>
        
        <category>python</category>
        
        <category>dev</category>
        
        <category>github</category>
        
        
      </item>
    
      <item>
        <title>Do you want to contribute to Copr?</title>
        <description>&lt;p&gt;I had a realization at &lt;a href=&quot;https://frostyx.cz/posts/devconf-2024-report&quot;&gt;this year’s DevConf&lt;/a&gt;. Even if people want to
contribute to large open-source projects, they have no idea how. Or they don’t
even realize they can contribute in the first place and that such a thing would
be appreciated That’s why I wanted to try this experiment and offer 5
interesting RFEs for the Fedora community to implement.&lt;/p&gt;

&lt;h2 id=&quot;why-you-should-contribute&quot;&gt;Why you should contribute&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://copr.fedorainfracloud.org&quot;&gt;Copr&lt;/a&gt; is a build system and third-party package repository for RPM-based
distributions. It’s similar to &lt;a href=&quot;https://aur.archlinux.org/&quot;&gt;AUR&lt;/a&gt; for example. The project has been
around since 2012 and has become an integral part of the Fedora packaging
ecosystem, as corroborated by many conference talks and articles mentioning
it. We currently host 29000 projects from 7000 Fedora users and the package
downloads are in millions.&lt;/p&gt;

&lt;p&gt;At this moment, there are &lt;a href=&quot;https://github.com/fedora-copr/copr/issues&quot;&gt;275 valid and triaged issues and RFEs&lt;/a&gt; in the
issue tracker. On &lt;a href=&quot;https://github.com/orgs/fedora-copr/projects/1&quot;&gt;this board&lt;/a&gt;, you can see the roadmap for the upcoming
months, years, and possible futures. One obvious reason for contributing to the
project is getting a feature implemented sooner. Another reason is to improve
your skills as a software developer. It may be more fun and more useful than
creating a new TODO application from scratch. Last but not least, it’s never a
bad idea to show your skills and collaborate with people who can do job
referrals. &lt;a href=&quot;https://research.redhat.com/blog/theses/determine-applications-affected-by-upgrade/&quot;&gt;That’s how&lt;/a&gt; I got my dream job 9 years ago. I think this is
a great opportunity for students looking to get some infield experience during
the summer break.&lt;/p&gt;

&lt;p&gt;Don’t worry if you don’t feel competent enough to contribute. We have
&lt;a href=&quot;https://frostyx.cz/posts/copr-docker-compose-without-supervisord&quot;&gt;documentation&lt;/a&gt; for setting up your local development environment,
tests and a review process to improve the code quality, and a
&lt;a href=&quot;https://matrix.to/#/#buildsys:fedoraproject.org&quot;&gt;Matrix channel&lt;/a&gt; for more informal communication. If you ever get stuck
somewhere in the process, please &lt;a href=&quot;https://github.com/FrostyX&quot;&gt;ping me&lt;/a&gt; and mention this article.&lt;/p&gt;

&lt;h2 id=&quot;how-you-can-contribute&quot;&gt;How you can contribute&lt;/h2&gt;

&lt;p&gt;Of course, you can pick any issue from the &lt;a href=&quot;https://github.com/fedora-copr/copr/issues&quot;&gt;Copr issue tracker&lt;/a&gt; that
seems interesting to you. Or you can pick any other project for that matter,
help is appreciated everywhere. However, In this article, I wanted to put
together a list of interesting and useful RFEs that our team won’t have time to
implement in the near future. Please let us know if you would like to
collaborate with us on any of them. We will get you started and make sure you
have all the information you need.&lt;/p&gt;

&lt;h3 id=&quot;1-external-repository-validation-&quot;&gt;1. External repository validation &lt;i class=&quot;fa fa-check&quot;&gt;&lt;/i&gt;&lt;/h3&gt;

&lt;table style=&quot;margin-bottom:10px;&quot;&gt;
  &lt;tr&gt;&lt;th style=&quot;min-width:120px;&quot;&gt;Difficulty:&lt;/th&gt;&lt;td&gt;Trivial&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;th&gt;Required skills:&lt;/th&gt;&lt;td&gt;Python&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;th&gt;Ticket:&lt;/th&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/fedora-copr/copr/issues/1178&quot;&gt;fedora-copr/copr#1178&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;th&gt;Contributor:&lt;/th&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/jaitjacob&quot;&gt;@jaitjacob&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Copr projects can depend on other projects. It is possible to specify such a
dependency via a fully qualified URL or a shortcut in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;copr://owner/project&lt;/code&gt;
format. It would be nice to have a validation making sure that users cannot set
a dependency on a non-existing project (due to typos for example).&lt;/p&gt;

&lt;h3 id=&quot;2-possibility-to-force-delete-a-project&quot;&gt;2. Possibility to force delete a project&lt;/h3&gt;

&lt;table style=&quot;margin-bottom:10px;&quot;&gt;
  &lt;tr&gt;&lt;th style=&quot;min-width:120px;&quot;&gt;Difficulty:&lt;/th&gt;&lt;td&gt;Easy&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;th&gt;Required skills:&lt;/th&gt;&lt;td&gt;Python&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;th&gt;Ticket:&lt;/th&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/fedora-copr/copr/issues/2629&quot;&gt;fedora-copr/copr#2629&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Through the &lt;a href=&quot;https://developer.fedoraproject.org/deployment/copr/copr-cli.html&quot;&gt;Copr CLI&lt;/a&gt; utility, it is possible to delete an existing
project with all of its builds. This, however, fails when some of the builds are
not yet finished. We would like to improve the respective API endpoint to
automatically cancel all running builds, making sure that no matter the state of
the project, it can be deleted.&lt;/p&gt;

&lt;h3 id=&quot;3-dark-mode-support&quot;&gt;3. Dark mode support&lt;/h3&gt;

&lt;table style=&quot;margin-bottom:10px;&quot;&gt;
  &lt;tr&gt;&lt;th style=&quot;min-width:120px;&quot;&gt;Difficulty:&lt;/th&gt;&lt;td&gt;Medium&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;th&gt;Required skills:&lt;/th&gt;&lt;td&gt;HTML, CSS, Javascript&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;th&gt;Ticket:&lt;/th&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/fedora-copr/copr/issues/3150&quot;&gt;fedora-copr/copr#3150&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;The &lt;a href=&quot;https://copr.fedorainfracloud.org&quot;&gt;Copr website&lt;/a&gt; offers only one theme and that is black text on a white
background. According to many online articles, dark-mode web designs are
getting increasingly more popular, helping to reduce eye strain and power
consumption. We would like our users to have the option to choose whether they
prefer light or dark mode of the website.&lt;/p&gt;

&lt;h3 id=&quot;4-webhook-history-&quot;&gt;4. Webhook history &lt;i class=&quot;fa fa-check&quot;&gt;&lt;/i&gt;&lt;/h3&gt;

&lt;table style=&quot;margin-bottom:10px;&quot;&gt;
  &lt;tr&gt;&lt;th style=&quot;min-width:120px;&quot;&gt;Difficulty:&lt;/th&gt;&lt;td&gt;Medium&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;th&gt;Required skills:&lt;/th&gt;&lt;td&gt;Python, HTML&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;th&gt;Ticket:&lt;/th&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/fedora-copr/copr/issues/304&quot;&gt;fedora-copr/copr#304&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;th&gt;Contributor:&lt;/th&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/jaitjacob&quot;&gt;@jaitjacob&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Copr provides integration with Git forges like &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt;,
&lt;a href=&quot;https://gitlab.com/&quot;&gt;GitLab&lt;/a&gt;, and &lt;a href=&quot;https://bitbucket.org/&quot;&gt;Bitbucket&lt;/a&gt; through webhooks. Usually,
everything works smoothly. However, when builds are not being triggered when
they should be, or conversely, when they are triggered multiple times, it is
hard for users to debug the issue. We would to have a table of all received
webhooks. This would allow project owners to understand
what exactly happened.&lt;/p&gt;

&lt;h3 id=&quot;5-actions-overview&quot;&gt;5. Actions overview&lt;/h3&gt;

&lt;table style=&quot;margin-bottom:10px;&quot;&gt;
  &lt;tr&gt;&lt;th style=&quot;min-width:120px;&quot;&gt;Difficulty:&lt;/th&gt;&lt;td&gt;Hard&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;th&gt;Required skills:&lt;/th&gt;&lt;td&gt;Python, HTML&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;th&gt;Ticket:&lt;/th&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/fedora-copr/copr/issues/1108&quot;&gt;fedora-copr/copr#1108&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Copr is a complex system, requiring various so-called “actions” to run in the
background. For example, in a project overview, there is a button for
regenerating the project repositories. When clicked, it triggers an
asynchronous action which is performed on an entirely different server. It
usually takes seconds to complete but it may take longer depending on the
current queue. It may even fail for some unexpected reason. Project owners
have no way of knowing what actions affected their projects and whether they
finished successfully. We would like to have a table for every project, showing
all the actions that happened.&lt;/p&gt;

</description>
        <pubDate>Thu, 27 Jun 2024 00:00:00 +0000</pubDate>
        <link>http://frostyx.cz/posts/do-you-want-to-contribute-to-copr</link>
        <guid isPermaLink="true">http://frostyx.cz/posts/do-you-want-to-contribute-to-copr</guid>
        
        <category>fedora</category>
        
        <category>copr</category>
        
        
      </item>
    
      <item>
        <title>DevConf 2024 report</title>
        <description>&lt;p&gt;This year’s &lt;a href=&quot;https://www.devconf.info/&quot;&gt;DevConf&lt;/a&gt; was a blast and the best time I had at a
conference probably since &lt;a href=&quot;https://frostyx.cz/posts/flock-report-2019&quot;&gt;2019 Flock in Budapest&lt;/a&gt;. Thank you all who
make events like these happen.&lt;/p&gt;

&lt;h2 id=&quot;day-1&quot;&gt;Day 1&lt;/h2&gt;

&lt;p&gt;It all started a bit unfavorable for me. I arrived underslept, forgot
that am supposed to have a ticket, and when I finally got to the
&lt;a href=&quot;https://pretalx.com/devconf-cz-2024/talk/TNGEQ9/&quot;&gt;Go language basis course&lt;/a&gt;, which I was very much looking
forward to, the room was already packed and we weren’t allowed in.&lt;/p&gt;

&lt;p&gt;Without much thinking, I joined the
&lt;a href=&quot;https://pretalx.com/devconf-cz-2024/talk/PSGCSK/&quot;&gt;Upstream maintainers meetup&lt;/a&gt; instead, which turned out to be
a good choice. For me, the most interesting part was a discussion between an
OpenSSL maintainer and an LVM maintainer about why they don’t have many
contributions from the community. What I realized afterward:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;People only care about one or two layers below whatever they are working
on. For the lack of a better example, as a &lt;a href=&quot;https://copr.fedorainfracloud.org/&quot;&gt;Copr&lt;/a&gt; developer, I am likely
to provide feedback or a small patch for &lt;a href=&quot;https://github.com/rpm-software-management/createrepo_c&quot;&gt;createrepo_c&lt;/a&gt; which we
directly build on top of. But it is very unlikely I will ever submit a patch
for some of its dependencies like &lt;a href=&quot;https://gitlab.gnome.org/GNOME/libxml2/-/wikis/home&quot;&gt;libxml2&lt;/a&gt; or &lt;a href=&quot;https://github.com/zchunk/zchunk&quot;&gt;zchunk&lt;/a&gt;. They
are too far removed from me.&lt;/li&gt;
  &lt;li&gt;Even if I was feeling philanthropic and wanted to spend my vacation hacking on
OpenSSL, I have no idea which of the 2k issues in their tracker would be a
good fit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two takeaways for me. First, I think we should try to reach contributors only
one level up and one level down from our project. Also, I would like to pick
five RFEs from the &lt;a href=&quot;https://github.com/orgs/fedora-copr/projects/1&quot;&gt;Copr backlog&lt;/a&gt; which would be nice to have but
our team won’t have time to implement them. Probably ever. I will write a short
paragraph about each of them, score them with difficulty, and list the needed
skills for their completion. I want to see if anyone from the community would be
interested in implementing them.&lt;/p&gt;

&lt;p&gt;On my way to another talk, I stumbled into &lt;a href=&quot;https://pretalx.com/devconf-cz-2024/speaker/HDHYAH/&quot;&gt;Florian Festi&lt;/a&gt;. We haven’t
talked in person for years, so I tried to re-introduce myself. I have high
regard for Florian, so of course, I couldn’t even stutter out my name. I don’t
know why. He is a kind and friendly dude with a majestic fluffy beard. There was
no reason to be nervous. Anyway, we discussed the insufficiencies of the Python
RPM documentation, and what should be done with them.&lt;/p&gt;

&lt;p&gt;The price for the best presentation of the conference goes to
&lt;a href=&quot;https://pretalx.com/devconf-cz-2024/speaker/VSXEDS/&quot;&gt;Evan Goode&lt;/a&gt; for
&lt;a href=&quot;https://pretalx.com/devconf-cz-2024/talk/NNKT3F/&quot;&gt;Learning from Nix: how other package managers can do better&lt;/a&gt;.
The topic was novel, the analysis was on point, and I very much appreciate his
speaking skills. After the talk, I lamented about Nix not being packaged for
Fedora, which is in my opinion a big drawback. During the lecture, the whole
room raised their hands that they know Nix. Then the whole room raised their
hands again that they use an RPM-based GNU/Linux distribution. Yet nobody raised
their hand that they actually use Nix. I think the reason is that it isn’t
easily available on Fedora. And many of us just are not willing to run
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl ... |sudo bash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After lunch, I finally got the opportunity to meet and chat with
&lt;a href=&quot;https://pretalx.com/devconf-cz-2024/speaker/KKDM87/&quot;&gt;Dan Čermák&lt;/a&gt; in person, after having several online discussions
about &lt;a href=&quot;https://github.com/dcermak/rpm-spec-language-server/&quot;&gt;rpm-spec-language-server&lt;/a&gt;. His lightning talk was on the same
topic - &lt;a href=&quot;https://pretalx.com/devconf-cz-2024/talk/RXKMKA/&quot;&gt;Creating a Language Server for RPM Spec Files&lt;/a&gt;. Cudos for
doing a live demo with a mic in one hand. Also, it was nice to see somebody else
use Emacs.&lt;/p&gt;

&lt;h2 id=&quot;day-2&quot;&gt;Day 2&lt;/h2&gt;

&lt;p&gt;This year, I decided to try something different, and … don’t go. I stayed
home, recharged my social battery, and worked on all the action items from the
previous day.&lt;/p&gt;

&lt;div class=&quot;text-center img-row row&quot;&gt;
  &lt;a href=&quot;/files/img/social-battery.png&quot; title=&quot;&quot;&gt;
    &lt;img src=&quot;/files/img/social-battery.png&quot; /&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;I submitted a &lt;a href=&quot;https://github.com/rpm-software-management/rpm-web/pull/54&quot;&gt;PR with Python API examples for the RPM documentation&lt;/a&gt;
and texted Evan a &lt;a href=&quot;https://copr.fedorainfracloud.org/coprs/prathampatel/nix/&quot;&gt;Copr project with Nix&lt;/a&gt; that could be a good
starting point for the official package. I created a
&lt;a href=&quot;https://github.com/dcermak/rpm-spec-language-server/issues/176#issuecomment-2166612811&quot;&gt;containerized reproducer for a Vim issue&lt;/a&gt; we are having with Dan in
the &lt;a href=&quot;https://github.com/dcermak/rpm-spec-language-server/&quot;&gt;rpm-spec-language-server&lt;/a&gt; project. And finally, I picked some
interesting Copr RFEs that I would like to offer to the community.&lt;/p&gt;

&lt;p&gt;Not attending the second day hugely paid off. I was pumped for Day 3.&lt;/p&gt;

&lt;h2 id=&quot;day-3&quot;&gt;Day 3&lt;/h2&gt;

&lt;p&gt;I skipped breakfast and came in early to see
&lt;a href=&quot;https://pretalx.com/devconf-cz-2024/talk/EJZQGJ/&quot;&gt;Gickup - Keep your repositories safe&lt;/a&gt; by
&lt;a href=&quot;https://pretalx.com/devconf-cz-2024/speaker/NZKK3B/&quot;&gt;Andreas Wachter&lt;/a&gt;. I was the first one in the room and Andy
promised to do the talk even if I was the only one. Fortunately, more people
came.  Afterward, we had a long chat about the &lt;a href=&quot;https://github.com/cooperspencer/gickup&quot;&gt;Gickup&lt;/a&gt; project and the
things I am planning to contribute. You see, I started working on a similar
project a few weeks ago but Gickup is miles ahead, which is great because now I
don’t have to implement all of it by myself from scratch.&lt;/p&gt;

&lt;p&gt;Mainly I am planning to create a systemd service so it doesn’t have to be run in
a container, add support for backing up project metadata like followers,
stars, etc (a good opportunity to learn Go), and package the tool for Fedora.&lt;/p&gt;

&lt;p&gt;On the &lt;a href=&quot;https://pretalx.com/devconf-cz-2024/talk/TTCJTB/&quot;&gt;Self-hosting/homelab meetup&lt;/a&gt;, I learned about new
interesting ways how to over-engineer my 200€ ThinkCentre running from behind
the couch. Specifically, I am planning to take a look at
&lt;a href=&quot;https://healthchecks.io/&quot;&gt;healthchecks.io&lt;/a&gt;, &lt;a href=&quot;https://www.borgbackup.org/&quot;&gt;Borg&lt;/a&gt;, &lt;a href=&quot;https://gethomepage.dev/latest/&quot;&gt;gethomepage.dev&lt;/a&gt;,
and some services for push notifications like &lt;a href=&quot;https://ntfy.sh/&quot;&gt;ntfy&lt;/a&gt; or &lt;a href=&quot;https://gotify.net/&quot;&gt;gotify&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;text-center img-row row&quot;&gt;
  &lt;a href=&quot;/files/img/wife-acceptance-factor.png&quot; title=&quot;Imporant consideration for home server - The Wife Acceptance Factor&quot;&gt;
    &lt;img src=&quot;/files/img/wife-acceptance-factor.png&quot; /&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;During a lunch break, I picked switches for my next mechanical keyboard and
tried to hit 10 WPM on this … thing.&lt;/p&gt;

&lt;div class=&quot;text-center img-row row&quot;&gt;
  &lt;a href=&quot;/files/img/split-keyboard.png&quot; title=&quot;Not a typo, I really meant 10 WPM, not 100 WPM&quot;&gt;
    &lt;img src=&quot;/files/img/split-keyboard.png&quot; /&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;I got unexpectedly mentioned in &lt;a href=&quot;https://pretalx.com/devconf-cz-2024/speaker/M3XBXT/&quot;&gt;Michel Lind&lt;/a&gt;’s talk about
&lt;a href=&quot;https://pretalx.com/devconf-cz-2024/talk/BXQNEQ/&quot;&gt;Applying Production Engineering mindset to RPM Packaging for fun and profit&lt;/a&gt;.
Not going to lie, felt really good.&lt;/p&gt;

&lt;div class=&quot;text-center img-row row&quot;&gt;
  &lt;a href=&quot;/files/img/package-review-mentioned.png&quot; title=&quot;Mum, can you see me?&quot;&gt;
    &lt;img src=&quot;/files/img/package-review-mentioned.png&quot; /&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;After the lecture, we brainstormed on
moving the &lt;a href=&quot;https://pagure.io/FedoraReview/&quot;&gt;fedora-review&lt;/a&gt; project from Pagure to GitLab so that
we can set up Packit for it and have a proper release process and CI. Which is
currently the biggest pain point of the project. As &lt;a href=&quot;https://pretalx.com/devconf-cz-2024/speaker/GSJ7WA/&quot;&gt;Neal Gompa&lt;/a&gt;
pointed out, that is the exact reason why neither of us publishes a release even
though it is needed. It is so bad I rather generated a downstream patch for the
Fedora package the last time I needed to ship something.&lt;/p&gt;

&lt;p&gt;And that was it, the end of the conference.&lt;/p&gt;

&lt;h2 id=&quot;closing-thoughts&quot;&gt;Closing thoughts&lt;/h2&gt;

&lt;p&gt;The event schedule was packed with ten tracks going in parallel at any given
moment. It was virtually impossible to attend everything I wanted to.
Good thing &lt;a href=&quot;https://www.youtube.com/@DevConfs&quot;&gt;there are recordings&lt;/a&gt; to keep me occupied during all my
meals this week.&lt;/p&gt;

&lt;p&gt;Also, I am not a social person. I know that, you know that, everybody knows
that. I loved to see you all but I cannot handle being three consecutive days in
crowds of hundreds of people without feeling like shit. That’s something I had
to contend and reconcile with. Skipping one day paid off, my social battery held
up, and I am already looking forward to DevConf 2025.&lt;/p&gt;

&lt;p&gt;Surprisingly, I felt so great afterward, that on my way home I even
approached a beautiful woman that smiled at me in a park. We had a nice
conversation but she was married so we parted ways after a few minutes. She
liked my compliment though. Hopefully, it made her day better.&lt;/p&gt;

</description>
        <pubDate>Sat, 15 Jun 2024 00:00:00 +0000</pubDate>
        <link>http://frostyx.cz/posts/devconf-2024-report</link>
        <guid isPermaLink="true">http://frostyx.cz/posts/devconf-2024-report</guid>
        
        <category>fedora</category>
        
        <category>report</category>
        
        <category>devconf</category>
        
        
      </item>
    
      <item>
        <title>LSP for Vim Boomers</title>
        <description>&lt;p&gt;There are many great videos and articles about configuring NeoVim LSP
using quickstart plugins or opinionated NeoVim distributions. Here I
would like to focus on people who still use Vim and refuse to use
plugins and custom configuration.&lt;/p&gt;

&lt;p&gt;This is a supporting article for my &lt;a href=&quot;https://www.youtube.com/watch?v=-aIPEOxUCUY&quot;&gt;LSP for Vim Boomers&lt;/a&gt;
video, so you can easily copy-paste things. Please watch the video for more information.&lt;/p&gt;

&lt;div class=&quot;text-center img-row row&quot;&gt;
&lt;iframe width=&quot;784&quot; height=&quot;441&quot; src=&quot;https://www.youtube.com/embed/-aIPEOxUCUY?si=qvz4LF3C0s9tWx82&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;h3 id=&quot;installation&quot;&gt;Installation&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mkdir -p ~/.vim/pack/vendor/start
cd ~/.vim/pack/vendor/start
git clone https://github.com/prabirshrestha/vim-lsp.git
sudo dnf install python3-lsp-server+all
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;configuration&quot;&gt;Configuration&lt;/h3&gt;

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;g:lsp_diagnostics_enabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;executable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;pylsp&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;au&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;User&lt;/span&gt; lsp_setup &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;lsp&lt;/span&gt;#register_server&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;        \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;pylsp&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;        \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;cmd&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;server_info&lt;span class=&quot;p&quot;&gt;-&amp;gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;pylsp&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]},&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;        \&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;allowlist&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;python&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;        \&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:on_lsp_buffer_enabled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; abort
    &lt;span class=&quot;k&quot;&gt;setlocal&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;omnifunc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;lsp&lt;/span&gt;#&lt;span class=&quot;nb&quot;&gt;complete&lt;/span&gt;
    nmap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;gd&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;plug&lt;span class=&quot;p&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;lsp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;definition&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    nmap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;gr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;plug&lt;span class=&quot;p&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;lsp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;references&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    nmap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; K &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;plug&lt;span class=&quot;p&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;lsp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;hover&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;

augroup lsp_install
    &lt;span class=&quot;k&quot;&gt;au&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;&quot; call s:on_lsp_buffer_enabled only for languages that has the server registered.&lt;/span&gt;
    autocmd &lt;span class=&quot;nb&quot;&gt;User&lt;/span&gt; lsp_buffer_enabled &lt;span class=&quot;k&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s:on_lsp_buffer_enabled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
augroup END
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;appendix&quot;&gt;Appendix&lt;/h3&gt;

&lt;h4 id=&quot;1-pre-configured-servers&quot;&gt;1. Pre-configured servers&lt;/h4&gt;

&lt;p&gt;There is a plugin not mentioned in the video called
&lt;a href=&quot;https://github.com/mattn/vim-lsp-settings&quot;&gt;vim-lsp-settings&lt;/a&gt;. It features a long list of
programming languages, and for each, configuration which LSP
server should be used. If you wish to make the tradeoff and
depend on one more plugin in exchange for a shorter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.vimrc&lt;/code&gt;, then
throw away the Python-specific configuration from the previous example
and do&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cd ~/.vim/pack/vendor/start
git clone https://github.com/prabirshrestha/vim-lsp.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;2-performance&quot;&gt;2. Performance&lt;/h4&gt;

&lt;p&gt;A &lt;a href=&quot;https://www.reddit.com/r/vim/comments/1cyh7rs/comment/l5astyh/?utm_source=share&amp;amp;utm_medium=web2x&amp;amp;context=3&quot;&gt;Reddit comment&lt;/a&gt; suggests that the following configuration line can
noticeably boost the LSP performance.&lt;/p&gt;

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;g:lsp_use_native_client&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;3-alternative-lsp-plugins&quot;&gt;3. Alternative LSP plugins&lt;/h4&gt;

&lt;p&gt;A possible alternative to &lt;a href=&quot;https://github.com/prabirshrestha/vim-lsp&quot;&gt;vim-lsp&lt;/a&gt; might be
&lt;a href=&quot;https://github.com/yegappan/lsp&quot;&gt;yegappan/lsp&lt;/a&gt;. It should have a similarly easy
configuration and it may be slightly faster. However, it requires Vim
9 and higher. Another alternative is &lt;a href=&quot;https://github.com/dense-analysis/ale&quot;&gt;ALE&lt;/a&gt; which should provide a
faster autocomplete according to &lt;a href=&quot;https://www.reddit.com/r/vim/comments/1cyh7rs/comment/l5lbpxj/?utm_source=share&amp;amp;utm_medium=web2x&amp;amp;context=3&quot;&gt;this Reddit comment&lt;/a&gt;. Example
configuration:&lt;/p&gt;

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;omnifunc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;ale#completion#OmniFunc
nnoremap K &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;cmd&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;ALEHover&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;CR&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;gd&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;cmd&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;ALEGoToDefinition&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;CR&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;gr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;cmd&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;ALEFindReferences&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;CR&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ca&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;cmd&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;ALECodeAc
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;g:ale_completion_enabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Tue, 21 May 2024 00:00:00 +0000</pubDate>
        <link>http://frostyx.cz/posts/lsp-for-vim-boomers</link>
        <guid isPermaLink="true">http://frostyx.cz/posts/lsp-for-vim-boomers</guid>
        
        <category>video</category>
        
        <category>vim</category>
        
        <category>lsp</category>
        
        <category>python</category>
        
        
      </item>
    
  </channel>
</rss>
