<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>eldevelopment &amp;mdash; qi.bookwar.info</title>
    <link>https://qi.bookwar.info/tag:eldevelopment</link>
    <description>Notes on Release, Build and CI Engineering</description>
    <pubDate>Tue, 26 May 2026 01:49:48 +0000</pubDate>
    <image>
      <url>https://i.snap.as/B5tGWZ1X.ico</url>
      <title>eldevelopment &amp;mdash; qi.bookwar.info</title>
      <link>https://qi.bookwar.info/tag:eldevelopment</link>
    </image>
    <item>
      <title>dist-git and exploded SRPMS - demystified</title>
      <link>https://qi.bookwar.info/dist-git-and-exploded-srpms-demystified?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[In this article we address another topic which appeared in multiple discussions recently. We take a look at the difference between the SRPM and the so called dist-git repository of a package. And why do we indeed prefer the dist-git.&#xA;&#xA;!--more--&#xA;&#xA;How RPM packages work?&#xA;&#xA;In simple words RPM packages need three things:&#xA;&#xA;archive of the original sources of the upstream application;&#xA;set of patches which needs to be applied to the original sources;&#xA;recipe (RPM spec file), which describes how to apply the patches, how to build the code and how to install it on a target system.&#xA;&#xA;When developing an RPM package you treat the upstream sources as a read-only object. You can not change the upstream sources, they should match the exact content upstream has released.&#xA;&#xA;To diverge from upstream, for example to backport a fix or to integrate the software better in the system, you create and maintain patches as separate files next to your upstream sources.&#xA;&#xA;Then to build a package the build system needs to fetch the archive with original sources, unpack it, apply patches as described in the spec, run the build scripts again as described in the spec, arrange the resulting files in a specific way and pack them into archive together with the installation recipe.&#xA;&#xA;This archive is the final &#34;binary RPM&#34; which you can install on your system using rpm  or dnf commands.&#xA;&#xA;As we build software for multiple architectures, we can produce several binary RPMs from the same source data by building them on different workers with different architectures (one for x8664, one for aarch64 and so on).&#xA;&#xA;What is dist-git&#xA;&#xA;dist-git is a git repository with a specific layout, which Fedora, CentOS Stream and RHEL use to develop RPM packages.&#xA;&#xA;The very minimal dist-git repo would look like this:&#xA;.&#xA;├── my-app.spec                      // spec file&#xA;├── sources                          // reference to the sources&#xA;└── patch-for-some-feature.patch     // patch to apply to the sources&#xA;&#xA;The important feature of the dist-git is that it doesn&#39;t store the unpacked sources of the application. It only stores a reference to the tarball of original upstream sources in a so-called lookaside cache.&#xA;&#xA;This reference is stored in the file which is called ./sources in the root of the git repository. See for example sources of a glibc package in Fedora Rawhide&#xA;&#xA;The lookaside cache of Fedora and CentOS (Stream or not Stream) is public and you can download any of its content.&#xA;&#xA;Now, since dist-git is the main repository where package development is happening, package maintainers often use it to store all sorts of additional things (scripts, readme files, infra configurations..) which can help them to do the work.&#xA;&#xA;There is also a recommended way to write tests in dist-git (see TMT). These integration tests are not part of the RPM package, but they are used in CI workflows and we recommend to put them in the dist-git repository, so that people can contribute to the package and the test development via the same interface.&#xA;&#xA;Example - keepalived dist-git&#xA;&#xA;Let&#39;s take a random package build, for example keepalived-2.2.4-6.el9.&#xA;&#xA;dist-git for the package has the following structure:&#xA;.&#xA;├── bz2028351-fix-dbus-policy-restrictions.patch  // patches&#xA;├── bz2102493-fix-variable-substitution.patch&#xA;├── bz2134749-fix-memory-leak-https-checks.patch&#xA;├── gating.yaml         //  CI configuration&#xA;├── .gitignore          //  standard gitignore&#xA;├── keepalived.init     // additional sources&#xA;├── keepalived.service  // additional sources&#xA;├── keepalived.spec     // spec file&#xA;├── rpminspect.yaml     //  rpminspect checks configuration  &#xA;├── sources             // reference to the lookaside cache &#xA;└── tests               //  dist-git test scenarios, run on every merge request&#xA;    ├── keepalived.conf.in&#xA;    ├── runtests.sh&#xA;    └── tests.yml&#xA;&#xA;Here I marked with asterisk the files which are not relevant to the RPM package build.&#xA;&#xA;What is SRPM&#xA;&#xA;As explained above, RPM package build requires multiple inputs. While the inputs are stored in dist-git and lookaside cache, you need to fetch them and carry around the build system to the build workers.&#xA;&#xA;Instead of fetching data from the internet during the build process (no build systems should ever do this!), we fetch all of the sources at the beginning, pack them in a tarball (SRPM file) and then use that self-contained tarball to run the builds in the isolated build environment. &#xA;&#xA;The SRPM then serves as a record of what build system got as input to produce the binary files.&#xA;&#xA;Example - keepalived SRPM&#xA;&#xA;SRPM for the package contains the following data:&#xA;bz2028351-fix-dbus-policy-restrictions.patch&#x9;1.58 KB&#xA;bz2102493-fix-variable-substitution.patch&#x9;929.00 B&#xA;bz2134749-fix-memory-leak-https-checks.patch&#x9;1.87 KB&#xA;keepalived-2.2.4.tar.gz&#x9;1.10 MB&#xA;keepalived.service&#x9;392.00 B&#xA;keepalived.spec&#x9;20.47 KB&#xA;You can see how the SRPM was produced by the build system together with binary RPMs via the Koji build task https://kojihub.stream.centos.org/koji/buildinfo?buildID=27965 &#xA;&#xA;The build task used dist-git commit as the input:&#xA;Source:  git+https://gitlab.com/redhat/centos-stream/rpms/keepalived#fc07f81c047dca49df2fc9d20513a7f52005a54d&#xA;&#xA;Note how the SRPM contains full tarball of the original upstream sources (1.10 MB of it). This tarball was fetched from the dist-git lookaside cache during the SRPM build step.&#xA;&#xA;What is exploded SRPM&#xA;&#xA;Fedora and RHEL use dist-git repositories for a very long time. Fedora dist-git has always been public, while RHEL dist-git repositories were internal and not available for people outside of Red Hat.&#xA;&#xA;So the only way for CentOS Project to rebuild RHEL code was to take the SRPM files and use them as the source of the rebuild.&#xA;&#xA;Since CentOS Project needed to rebrand or adjust certain packages, they didn&#39;t take RHEL SRPMs as is, rather they unpacked them and put the unpacked sources in git repository. This way they got access to at least some history of the changes, were able to apply their own patches and generally increased the visibility of the content.&#xA;&#xA;Example - keepalived exploded SRPM&#xA;&#xA;&#34;Exploded SRPM&#34; at git.centos.org for this package looks like:&#xA;.&#xA;├── .gitignore&#xA;├── .keepalived.metadata  // same as ./sources in dist-git&#xA;├── SOURCES&#xA;│   ├── bz2028351-fix-dbus-policy-restrictions.patch  // patches&#xA;│   ├── bz2102493-fix-variable-substitution.patch&#xA;│   ├── bz2134749-fix-memory-leak-https-checks.patch&#xA;│   └── keepalived.service  // additional sources&#xA;└── SPECS&#xA;    └── keepalived.spec  // spec file&#xA;&#xA;Exploded SRPM git again doesn&#39;t store the upstream tarball in the repository and references the lookaside cache via .keepalived.metadata file.&#xA;&#xA;You can see the same files as included in the SRPM, though they are put into a different directory structure. And none of the additional files (tests, scripts, configs) are available.&#xA;&#xA;Take away&#xA;&#xA;dist-git repository is the original source of an RPM package build. Fedora, CentOS Stream and RHEL packages are all built directly from dist-git repositories.&#xA;&#xA;SRPM is an artifact of the build process. It is produced from the commit in dist-git and then stored alongside the binary RPM.&#xA;&#xA;Exploded SRPM is an attempt to recover the original git structure from the SRPM in case there is no access to the dist-git repository. It does contain the same source files and spec as in dist-git, but it is not able to recover additional non-packaged data, like configuration files, tests and so on.&#xA;&#xA;We recommend to use dist-git for any collaboration and development purposes.&#xA;&#xA;----&#xA;&#xA;P.S. You can also take a look at the Source Git initiative which aims to change the approach to RPM sources to make upstream source code more accessible.&#xA;&#xA;ELdevelopment&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>In this article we address another topic which appeared in multiple discussions recently. We take a look at the difference between the SRPM and the so called <em>dist-git repository</em> of a package. And why do we indeed prefer the dist-git.</p>



<h2 id="how-rpm-packages-work" id="how-rpm-packages-work">How RPM packages work?</h2>

<p>In simple words RPM packages need three things:</p>
<ul><li>archive of the original sources of the upstream application;</li>
<li>set of patches which needs to be applied to the original sources;</li>
<li>recipe (RPM spec file), which describes how to apply the patches, how to build the code and how to install it on a target system.</li></ul>

<p>When developing an RPM package you treat the upstream sources as a read-only object. You can not change the upstream sources, they should match the exact content upstream has released.</p>

<p>To diverge from upstream, for example to backport a fix or to integrate the software better in the system, you create and maintain patches as separate files next to your upstream sources.</p>

<p>Then to build a package the build system needs to fetch the archive with original sources, unpack it, apply patches as described in the spec, run the build scripts again as described in the spec, arrange the resulting files in a specific way and pack them into archive together with the installation recipe.</p>

<p>This archive is the final “binary RPM” which you can install on your system using <code>rpm</code>  or <code>dnf</code> commands.</p>

<p>As we build software for multiple architectures, we can produce several binary RPMs from the same source data by building them on different workers with different architectures (one for <code>x86_64</code>, one for <code>aarch64</code> and so on).</p>

<h2 id="what-is-dist-git" id="what-is-dist-git">What is dist-git</h2>

<p><em>dist-git</em> is a git repository with a specific layout, which Fedora, CentOS Stream and RHEL use to develop RPM packages.</p>

<p>The very minimal dist-git repo would look like this:</p>

<pre><code>.
├── my-app.spec                      // spec file
├── sources                          // reference to the sources
└── patch-for-some-feature.patch     // patch to apply to the sources
</code></pre>

<p>The important feature of the dist-git is that it doesn&#39;t store the unpacked sources of the application. It only stores a reference to the tarball of original upstream sources in a so-called lookaside cache.</p>

<p>This reference is stored in the file which is called <code>./sources</code> in the root of the git repository. See for example <a href="https://src.fedoraproject.org/rpms/glibc/blob/rawhide/f/sources" rel="nofollow"><code>sources</code> of a glibc package in Fedora Rawhide</a></p>

<p>The lookaside cache of Fedora and CentOS (Stream or not Stream) is public and you can download any of its content.</p>

<p>Now, since dist-git is the main repository where package development is happening, package maintainers often use it to store all sorts of additional things (scripts, readme files, infra configurations..) which can help them to do the work.</p>

<p>There is also a recommended way to write tests in dist-git (see <a href="https://docs.fedoraproject.org/en-US/ci/tmt/" rel="nofollow">TMT</a>). These integration tests are not part of the RPM package, but they are used in CI workflows and we recommend to put them in the dist-git repository, so that people can contribute to the package and the test development via the same interface.</p>

<h3 id="example-keepalived-dist-git" id="example-keepalived-dist-git">Example – keepalived dist-git</h3>

<p>Let&#39;s take a random package build, for example <code>keepalived-2.2.4-6.el9</code>.</p>

<p><a href="https://gitlab.com/redhat/centos-stream/rpms/keepalived/-/tree/fc07f81c047dca49df2fc9d20513a7f52005a54d" rel="nofollow">dist-git for the package</a> has the following structure:</p>

<pre><code>.
├── bz2028351-fix-dbus-policy-restrictions.patch  // patches
├── bz2102493-fix-variable-substitution.patch
├── bz2134749-fix-memory-leak-https-checks.patch
├── gating.yaml         // * CI configuration
├── .gitignore          // * standard gitignore
├── keepalived.init     // additional sources
├── keepalived.service  // additional sources
├── keepalived.spec     // spec file
├── rpminspect.yaml     // * rpminspect checks configuration  
├── sources             // reference to the lookaside cache 
└── tests               // * dist-git test scenarios, run on every merge request
    ├── keepalived.conf.in
    ├── run_tests.sh
    └── tests.yml
</code></pre>

<p>Here I marked with asterisk the files which are not relevant to the RPM package build.</p>

<h2 id="what-is-srpm" id="what-is-srpm">What is SRPM</h2>

<p>As explained above, RPM package build requires multiple inputs. While the inputs are stored in dist-git and lookaside cache, you need to fetch them and carry around the build system to the build workers.</p>

<p>Instead of fetching data from the internet during the build process (no build systems should ever do this!), we fetch all of the sources at the beginning, pack them in a tarball (SRPM file) and then use that self-contained tarball to run the builds in the isolated build environment.</p>

<p>The SRPM then serves as a record of what build system got as input to produce the binary files.</p>

<h3 id="example-keepalived-srpm" id="example-keepalived-srpm">Example – keepalived SRPM</h3>

<p><a href="https://kojihub.stream.centos.org/koji/rpminfo?rpmID=722889" rel="nofollow">SRPM for the package</a> contains the following data:</p>

<pre><code>bz2028351-fix-dbus-policy-restrictions.patch	1.58 KB
bz2102493-fix-variable-substitution.patch	929.00 B
bz2134749-fix-memory-leak-https-checks.patch	1.87 KB
keepalived-2.2.4.tar.gz	1.10 MB
keepalived.service	392.00 B
keepalived.spec	20.47 KB
</code></pre>

<p>You can see how the SRPM was produced by the build system together with binary RPMs via the Koji build task <a href="https://kojihub.stream.centos.org/koji/buildinfo?buildID=27965" rel="nofollow">https://kojihub.stream.centos.org/koji/buildinfo?buildID=27965</a></p>

<p>The build task used dist-git commit as the input:</p>

<pre><code>Source:  git+https://gitlab.com/redhat/centos-stream/rpms/keepalived#fc07f81c047dca49df2fc9d20513a7f52005a54d
</code></pre>

<p>Note how the SRPM contains full tarball of the original upstream sources (1.10 MB of it). This tarball was fetched from the dist-git lookaside cache during the SRPM build step.</p>

<h2 id="what-is-exploded-srpm" id="what-is-exploded-srpm">What is exploded SRPM</h2>

<p>Fedora and RHEL use dist-git repositories for a very long time. Fedora dist-git has always been public, while RHEL dist-git repositories were internal and not available for people outside of Red Hat.</p>

<p>So the only way for CentOS Project to rebuild RHEL code was to take the SRPM files and use them as the source of the rebuild.</p>

<p>Since CentOS Project needed to rebrand or adjust certain packages, they didn&#39;t take RHEL SRPMs as is, rather they unpacked them and put the unpacked sources in git repository. This way they got access to at least some history of the changes, were able to apply their own patches and generally increased the visibility of the content.</p>

<h3 id="example-keepalived-exploded-srpm" id="example-keepalived-exploded-srpm">Example – keepalived exploded SRPM</h3>

<p><a href="https://git.centos.org/rpms/keepalived/tree/c9" rel="nofollow">“Exploded SRPM” at git.centos.org</a> for this package looks like:</p>

<pre><code>.
├── .gitignore
├── .keepalived.metadata  // same as ./sources in dist-git
├── SOURCES
│   ├── bz2028351-fix-dbus-policy-restrictions.patch  // patches
│   ├── bz2102493-fix-variable-substitution.patch
│   ├── bz2134749-fix-memory-leak-https-checks.patch
│   └── keepalived.service  // additional sources
└── SPECS
    └── keepalived.spec  // spec file
</code></pre>

<p>Exploded SRPM git again doesn&#39;t store the upstream tarball in the repository and references the lookaside cache via <code>.keepalived.metadata</code> file.</p>

<p>You can see the same files as included in the SRPM, though they are put into a different directory structure. And none of the additional files (tests, scripts, configs) are available.</p>

<h2 id="take-away" id="take-away">Take away</h2>

<p>dist-git repository is the <strong>original source</strong> of an RPM package build. Fedora, CentOS Stream and RHEL packages are all built directly from dist-git repositories.</p>

<p>SRPM is an artifact of the build process. It is produced from the commit in dist-git and then stored alongside the binary RPM.</p>

<p>Exploded SRPM is an attempt to recover the original git structure from the SRPM in case there is no access to the dist-git repository. It does contain the same source files and spec as in dist-git, but it is not able to recover additional non-packaged data, like configuration files, tests and so on.</p>

<p>We recommend to use dist-git for any collaboration and development purposes.</p>

<hr/>

<p>P.S. You can also take a look at the <a href="https://packit.dev/source-git" rel="nofollow">Source Git</a> initiative which aims to change the approach to RPM sources to make upstream source code more accessible.</p>

<p><a href="https://qi.bookwar.info/tag:ELdevelopment" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">ELdevelopment</span></a></p>
]]></content:encoded>
      <guid>https://qi.bookwar.info/dist-git-and-exploded-srpms-demystified</guid>
      <pubDate>Sun, 23 Jul 2023 20:08:58 +0000</pubDate>
    </item>
    <item>
      <title>Continuity of Linux distributions</title>
      <link>https://qi.bookwar.info/continuously-built-linux-distributions?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[I know people who imagine distribution development as the process of piling up the code in the git repository for 6 months and then building it all in one go at the end of those 6 months, so that it can finally be shipped. This is very far from reality. And it is impossible to explain things like CentOS Stream without addressing this confusion.&#xA;&#xA;!--more--&#xA;&#xA;Linux distributions are not just developed continuously, they are built continuously.&#xA;&#xA;When you have your generic application, you have your sources. You contribute changes to sources, integrating them into the main branch. And then you decide to build the tip of the branch and you get an artifact - a binary. When later you make changes to the sources, you throw away the previous binary, and build yourself a new one.&#xA;&#xA;Linux distributions are different.&#xA;&#xA;When you change a distribution, you apply a change to a one part of the sources, then you build those sources into a package and add the package to a shared pool of latest packages. And then this shared pool of packages (we call it buildroot) is used to build a next change in the distribution.&#xA;&#xA;Linux distribution is &#34;self-hosted&#34;), it grows by updating its buildroot and using its new state to build its next updates. And updates are applied individually per package.&#xA;&#xA;Why am I focusing on this? Because it has practical consequences.&#xA;&#xA;Packaged Linux distribution is not a single binary, it is a “compound” artifact, where different parts of it (packages) are built at different times using different states of the buildroot.&#xA;&#xA;Imagine we have two packages A and B in the distribution. Package A is more static, it doesn’t get that many updates, so in four weeks it got updated once. While package B is more actively developed and gets updates every week.&#xA;&#xA;This will look somewhat like this:&#xA;&#xA;Time      | Week 1 | Week 2 | Week 3 | Week 4 |&#xA;Package A | v1.0.0 | v1.0.1                   |  ---  A-v1.0.1, B-v18&#xA;Package B | v15    | v16    | v17    | v18    |&#xA;&#xA;So if you look at the result of the 4-weeks development, you see that package A has been updated from v1.0.0 to v1.0.1 and package B has been updated from v15 to v18. Yet package A was not built on week 4. It was built on week 2 using the state of the buildroot available at that week 2. If that package A has a build dependency on Package B, then it was using that v16 version of the dependency. And it was not updated after the change to v17 in B.&#xA;&#xA;There are several points to take from here.&#xA;&#xA;First point: packaged distributions do not appear out of nowhere.&#xA;&#xA;Linux distributions are either continuously developed from some origin, like Fedora Rawhide is developed for 20 years from its original Fedora 1 state (I&#39;ll ask people more knowledgeable than me to explain how that original state was created). Or they are branched (aka forked) from another distribution. Or they are bootstrapped (forked, but with much more work) using another distribution.&#xA;&#xA;Second point: packaged distribution is not fully defined by the static snapshot of its sources.&#xA;&#xA;If on week 4 you use the latest git sources of the distribution, check them out and build packages from them, you will get package A of version v1.0.1 built using a build dependency on the package B of v18. Which may or may not lead to a different result.&#xA;&#xA;And if this doesn’t scare you, please read again.&#xA;&#xA;You can not reproduce the exact state of the Linux distribution from a snapshot of its sources. And not because something is hidden from the sources (dist-git repository state has more information about the package than SRPM of that package does, and we&#39;ll talk about it another day). The issue is that distribution is not just its sources. Distribution is its sources and its buildroot with all its complex history.&#xA;&#xA;In my opinion it is a big fail for the entire industry to think about a Linux distribution as a fixed set of RPMs and SRPMs on a DVD(or the iso image). I understand where it comes from, but it is a fail anyway.&#xA;&#xA;When I think about a distribution, I think about the buildroot of a distribution as a sort of git repository: it has history, it has merge requests_. When we update a package, we add a new binary package (RPM) to the buildroot. In other words, we make a new commit to the buildroot state.&#xA;&#xA;And it is not just an abstraction, I think we can literally implement the changes to the distribution buildroot as merge requests to a git repository with the list of packages (And if you are interested and want to try and help make it happen - let&#39;s talk about it).&#xA;&#xA;Third point: branching of a Linux distribution is not just branching of the sources, it is branching of its binaries.&#xA;&#xA;Again this is something that application developers won&#39;t expect. When we create a branch of the distribution we don&#39;t just create a branch in every git source of every package included in the distribution. We also create a &#34;branch&#34; of the buildroot. All binary packages built till a certain day in the mainline of a distribution are copied into a branch. They form the buildroot of the branch, which is then can be updated via a standard update procedure.&#xA;&#xA;We do not rebuild a package after branching, unless there is a new change which we want to land in this specific package.&#xA;&#xA;---&#xA;&#xA;This is a heavy-weight article, and thank you for getting this far.&#xA;&#xA;But let me reiterate the main message:&#xA;&#xA;Packaged Linux distribution is not built from scratch from the snapshot of its sources.&#xA;&#xA;We accumulate changes as they happen in different packages, and we inherit, merge and branch the pool of binary packages the same way we inherit, merge and branch their sources.&#xA;&#xA;We will look into how this applies to RHEL and CentOS conversation in next articles.&#xA;&#xA;---&#xA;&#xA;As folks pointed out, the process described in this article applies to packaged Linux distributions like Fedora, Debian or RHEL. There are other ways to build a distribution and you can check the article by Colin Walters, where he discusses the alternatives.&#xA;&#xA;ELdevelopment]]&gt;</description>
      <content:encoded><![CDATA[<p>I know people who imagine distribution development as the process of piling up the code in the git repository for 6 months and then building it all in one go at the end of those 6 months, so that it can finally be shipped. This is very far from reality. And it is impossible to explain things like CentOS Stream without addressing this confusion.</p>



<p>Linux distributions are not just developed continuously, they are <strong>built continuously</strong>.</p>

<p>When you have your generic application, you have your sources. You contribute changes to sources, integrating them into the main branch. And then you decide to <em>build</em> the tip of the branch and you get an artifact – a binary. When later you make changes to the sources, you throw away the previous binary, and build yourself a new one.</p>

<p>Linux distributions are different.</p>

<p>When you change a distribution, you apply a change to a one part of the sources, then you build those sources into a package and add the package to a shared pool of latest packages. And then this shared pool of packages (we call it <em>buildroot</em>) is used to build a next change in the distribution.</p>

<p>Linux distribution is <a href="https://en.wikipedia.org/wiki/Self-hosting_(compilers)" rel="nofollow">“self-hosted”</a>, it grows by updating its buildroot and using its new state to build its next updates. And updates are applied individually per package.</p>

<p>Why am I focusing on this? Because it has practical consequences.</p>

<p>Packaged Linux distribution is not a single binary, it is a “compound” artifact, where different parts of it (packages) are built at different times using different states of the buildroot.</p>

<p>Imagine we have two packages A and B in the distribution. Package A is more static, it doesn’t get that many updates, so in four weeks it got updated once. While package B is more actively developed and gets updates every week.</p>

<p>This will look somewhat like this:</p>

<pre><code>Time      | Week 1 | Week 2 | Week 3 | Week 4 |
Package A | v1.0.0 | v1.0.1                   |  ---&gt;    A-v1.0.1, B-v18
Package B | v15    | v16    | v17    | v18    |
</code></pre>

<p>So if you look at the result of the 4-weeks development, you see that package A has been updated from v1.0.0 to v1.0.1 and package B has been updated from v15 to v18. Yet package A was not built on week 4. It was built on week 2 using the state of the buildroot available at that week 2. If that package A has a build dependency on Package B, then it was using that v16 version of the dependency. And it was not updated after the change to v17 in B.</p>

<p>There are several points to take from here.</p>

<p><strong>First point:</strong> packaged distributions do not appear out of nowhere.</p>

<p>Linux distributions are either continuously developed from some origin, like Fedora Rawhide is developed for 20 years from its original Fedora 1 state (I&#39;ll ask people more knowledgeable than me to explain how that original state was created). Or they are branched (aka forked) from another distribution. Or they are bootstrapped (forked, but with much more work) using another distribution.</p>

<p><strong>Second point:</strong> packaged distribution is not fully defined by the static snapshot of its sources.</p>

<p>If on week 4 you use the latest git sources of the distribution, check them out and build packages from them, you will get package A of version v1.0.1 built using a build dependency on the package B of v18. Which may or may not lead to a different result.</p>

<p>And if this doesn’t scare you, please read again.</p>

<p>You can not reproduce the exact state of the Linux distribution from a snapshot of its sources. And not because something is hidden from the sources (dist-git repository state has more information about the package than SRPM of that package does, and we&#39;ll talk about it <a href="https://quantum-integration.org/dist-git-and-exploded-srpms-demystified" rel="nofollow">another day</a>). The issue is that distribution is not just its sources. Distribution is its sources and its buildroot with all its complex history.</p>

<p>In my opinion it is a big fail for the entire industry to think about a Linux distribution as a fixed set of RPMs and SRPMs on a DVD(or the iso image). I understand where it comes from, but it is a fail anyway.</p>

<p>When I think about a distribution, I think about the buildroot of a distribution as a sort of git repository: it has history, it has <em>merge requests</em>. When we update a package, we add a new binary package (RPM) to the buildroot. In other words, we make a new commit to the buildroot state.</p>

<p>And it is not just an abstraction, I think we can literally implement the changes to the distribution buildroot as merge requests to a git repository with the list of packages (And if you are interested and want to try and help make it happen – let&#39;s talk about it).</p>

<p><strong>Third point:</strong> branching of a Linux distribution is not just branching of the sources, it is branching of its binaries.</p>

<p>Again this is something that application developers won&#39;t expect. When we create a branch of the distribution we don&#39;t just create a branch in every git source of every package included in the distribution. We also create a “branch” of the buildroot. All binary packages built till a certain day in the mainline of a distribution are copied into a branch. They form the buildroot of the branch, which is then can be updated via a standard update procedure.</p>

<p>We do not rebuild a package after branching, unless there is a new change which we want to land in this specific package.</p>

<hr/>

<p>This is a heavy-weight article, and thank you for getting this far.</p>

<p>But let me reiterate the main message:</p>

<p>Packaged Linux distribution is not built from scratch from the snapshot of its sources.</p>

<p>We accumulate changes as they happen in different packages, and we inherit, merge and branch the pool of binary packages the same way we inherit, merge and branch their sources.</p>

<p>We will look into how this applies to RHEL and CentOS conversation in next articles.</p>

<hr/>

<p>As folks pointed out, the process described in this article applies to packaged Linux distributions like Fedora, Debian or RHEL. There are other ways to build a distribution and you can check <a href="https://blog.verbum.org/2012/10/13/building-everything-from-source-vs-self-hosting/" rel="nofollow">the article</a> by Colin Walters, where he discusses the alternatives.</p>

<p><a href="https://qi.bookwar.info/tag:ELdevelopment" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">ELdevelopment</span></a></p>
]]></content:encoded>
      <guid>https://qi.bookwar.info/continuously-built-linux-distributions</guid>
      <pubDate>Sat, 22 Jul 2023 16:10:49 +0000</pubDate>
    </item>
    <item>
      <title>EL-development</title>
      <link>https://qi.bookwar.info/el-development?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[When you live in the world of ever changing development tools and frameworks, disrupting technologies and freshly generated buzzwords it is tempting to look down at a stable Linux distribution as a static, boring thing, which you install and forget.&#xA;&#xA;Hopefully you don’t forget it completely and at least try to be up to date with the latest updates. But let’s be honest, everyone working in this field has an example of a machine which worked long past the official End Of Life of its operating system.&#xA;&#xA;And that’s OK. Many people can live a happy and exciting life without worrying too much about the depths of the Enterprise Linux-development.&#xA;&#xA;Yet if you are in the business of long-term planning, in the business of development of services which are built to last and in the business of supporting environments too sensitive to change, you have to accept that the stable Linux distribution is a living thing. It has its own development, own lifecycle, its own dependencies and even its own stable branches. It also has some unique challenges people don’t meet while carelessly sliding on the surface.&#xA;&#xA;Also I personally find it interesting and exciting too, but I don’t expect everyone to share the interest.&#xA;&#xA;Anyways, whatever your reasons to come here, welcome on board, buckle up and let’s dive in.&#xA;&#xA;As I am unable to write everything I want to write in one go, I am going to use this page to collect the notes which I (or maybe someone else too, send me links) have written on the topic. You can also send me (@bookwar@fosstodon.org) questions, opinions, corrections. And I will mention you in ~my will~ the credits of the book if I ever write it.&#xA;&#xA;We will see how far it goes.&#xA;&#xA;Local articles&#xA;&#xA;dist-git and exploded SRPMS – demystified&#xA;  SRPMs, exploded SRPMs and dist-git - what is it all about?  &#xA;&#xA;Continuity of Linux distributions&#xA;  I know people who imagine distribution development as the process of piling up the code in the git repository for 6 months and then building it all in one go at the end of those 6 months, so that it can finally be shipped. This is very far from reality. And it is impossible to explain things like CentOS Stream without addressing this confusion.&#xA;&#xA;The Curse Of Bug To Bug Compatibility&#xA;  The chase for “bug-to-bug compatibility” hurts community, hurts RHEL customers and hurts the industry as a whole. The real innovation behind the CentOS Stream is the attempt to change it.&#xA;&#xA;Links to externals sites&#xA;&#xA;Joe Brockmeier&#xA;&#xA;https://dissociatedpress.net/2023/06/24/red-hat-and-the-clone-wars/&#xA;  &#34;Red Hat and the Clone Wars&#34; - saga in many chapters. Not necessarily required for technical understanding, but provides historical context.&#xA;&#xA;Gordon Messmer&#xA;&#xA;https://medium.com/@gordon.messmer/in-favor-of-centos-stream-e5a8a43bdcf8&#xA;  On CentOS Stream vs minor releases of RHEL &#xA;&#xA;https://medium.com/@gordon.messmer/if-you-dont-understand-its-purpose-you-can-t-improve-the-process-4e48260c3887&#xA;  On CentOS Stream vs CentOS Linux&#xA;&#xA;ELdevelopment&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>When you live in the world of ever changing development tools and frameworks, disrupting technologies and freshly generated buzzwords it is tempting to look down at a stable Linux distribution as a static, boring thing, which you install and forget.</p>

<p>Hopefully you don’t forget it completely and at least try to be up to date with the latest updates. But let’s be honest, everyone working in this field has an example of a machine which worked long past the official End Of Life of its operating system.</p>

<p>And that’s OK. Many people can live a happy and exciting life without worrying too much about the depths of the Enterprise Linux-development.</p>

<p>Yet if you are in the business of long-term planning, in the business of development of services which are built to last and in the business of supporting environments too sensitive to change, you have to accept that the stable Linux distribution is a living thing. It has its own development, own lifecycle, its own dependencies and even its own stable branches. It also has some unique challenges people don’t meet while carelessly sliding on the surface.</p>

<p>Also I personally find it interesting and exciting too, but I don’t expect everyone to share the interest.</p>

<p>Anyways, whatever your reasons to come here, welcome on board, buckle up and let’s dive in.</p>

<p>As I am unable to write everything I want to write in one go, I am going to use this page to collect the notes which I (or maybe someone else too, send me links) have written on the topic. You can also send me (<code><a href="/@/bookwar@fosstodon.org" class="u-url mention" rel="nofollow">@<span>bookwar@fosstodon.org</span></a></code>) questions, opinions, corrections. And I will mention you in ~my will~ the credits of the book if I ever write it.</p>

<p>We will see how far it goes.</p>

<h2 id="local-articles" id="local-articles">Local articles</h2>
<ul><li><p><a href="https://qi.bookwar.info/dist-git-and-exploded-srpms-demystified" rel="nofollow">dist-git and exploded SRPMS – demystified</a>
SRPMs, exploded SRPMs and dist-git – what is it all about?</p></li>

<li><p><a href="https://qi.bookwar.info/continuously-built-linux-distributions" rel="nofollow">Continuity of Linux distributions</a>
<em>I know people who imagine distribution development as the process of piling up the code in the git repository for 6 months and then building it all in one go at the end of those 6 months, so that it can finally be shipped. This is very far from reality. And it is impossible to explain things like CentOS Stream without addressing this confusion.</em></p></li>

<li><p><a href="https://qi.bookwar.info/the-curse-of-bug-to-bug-compatibility" rel="nofollow">The Curse Of Bug To Bug Compatibility</a>
<em>The chase for “bug-to-bug compatibility” hurts community, hurts RHEL customers and hurts the industry as a whole. The real innovation behind the CentOS Stream is the attempt to change it.</em></p></li></ul>

<h2 id="links-to-externals-sites" id="links-to-externals-sites">Links to externals sites</h2>

<p>Joe Brockmeier</p>
<ul><li><a href="https://dissociatedpress.net/2023/06/24/red-hat-and-the-clone-wars/" rel="nofollow">https://dissociatedpress.net/2023/06/24/red-hat-and-the-clone-wars/</a>
“Red Hat and the Clone Wars” – saga in many chapters. Not necessarily required for technical understanding, but provides historical context.</li></ul>

<p>Gordon Messmer</p>
<ul><li><p><a href="https://medium.com/@gordon.messmer/in-favor-of-centos-stream-e5a8a43bdcf8" rel="nofollow">https://medium.com/@gordon.messmer/in-favor-of-centos-stream-e5a8a43bdcf8</a>
On CentOS Stream vs minor releases of RHEL</p></li>

<li><p><a href="https://medium.com/@gordon.messmer/if-you-dont-understand-its-purpose-you-can-t-improve-the-process-4e48260c3887" rel="nofollow">https://medium.com/@gordon.messmer/if-you-dont-understand-its-purpose-you-can-t-improve-the-process-4e48260c3887</a>
On CentOS Stream vs CentOS Linux</p></li></ul>

<p><a href="https://qi.bookwar.info/tag:ELdevelopment" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">ELdevelopment</span></a></p>
]]></content:encoded>
      <guid>https://qi.bookwar.info/el-development</guid>
      <pubDate>Sat, 22 Jul 2023 13:23:14 +0000</pubDate>
    </item>
    <item>
      <title>The curse of bug-to-bug compatibility</title>
      <link>https://qi.bookwar.info/the-curse-of-bug-to-bug-compatibility?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[Disclaimer: I am a Senior Principal Engineer in Red Hat. I was a member of the RHEL 9/CentOS Stream 9 Bootstrap team. Opinions are my own.&#xA;&#xA;Tl;dr&#xA;&#xA;The chase for &#34;bug-to-bug compatibility&#34; hurts community, hurts RHEL customers and hurts the industry as a whole. The real innovation behind the CentOS Stream is the attempt to change it.&#xA;&#xA;!--more--&#xA;&#xA;What is ABI compatibility?&#xA;&#xA;ABI compatibility is a requirement for certain interfaces to not change for a certain length of time, so that you can safely rely on the availability of a certain function and certain library which behaves in a predictable way.&#xA;&#xA;It is important to know that RHEL ABI compatibility doesn&#39;t say &#34;all ABIs and APIs are stable forever&#34;. The real ABI compatibility of RHEL is described in details in the official ABI Compatibility guidelines:&#xA;&#xA;https://access.redhat.com/articles/rhel9-abi-compatibility&#xA;&#xA;I recommend to take a look and check which compatibility level is assigned to your favorite library according to this guide.&#xA;&#xA;What is bug to bug compatibility?&#xA;&#xA;The term bug-to-bug compatibility when applied in isolation means that for this specific issue when we implement a new system we carry the bug over to a new implementation. Your users rely on the broken behavior so much that they require it on the new system, see xkcd/Workflow.&#xA;&#xA;The way the term is applied to RHEL conversation is very generic, and therefore has much less sense. It implies that one Linux distribution has the same bugs as the another.&#xA;&#xA;Linux distribution is not a static thing though. Linux distribution is a pool of package builds, each versioned on its own, and updated on its own, which are then combined into different subsets based on different rules. It is both the power and the weakness of a Linux distribution. The power as the ability to combine and mix and match packages allows you to create solutions to a large range of tasks. The weakness as different combinations of components may lead to different behavior.&#xA;&#xA;Add the branching structure of RHEL to it, with all of its powerful minor-stream complexity, and you&#39;ll realize that there is simply no single state of RHEL, which you can be bug-to-bug compatible to.&#xA;&#xA;Thus, at the distribution level the &#34;bug-to-bug compatibility&#34; concept does not exist. It is an overhyped buzzword people use without putting too much thought into it.&#xA;&#xA;Why does it hurt&#xA;&#xA;ABI compatibility guidelines is the open formal standard for the RHEL-compatible ecosystem. It is the .odt kind of specification for Linux distributions. On the other hand, the mythical bug-to-bug compatibility is the .docx. You chase the always moving target which you can not control or predict.&#xA;&#xA;The huge amount of issues coming to RHEL support, and the demand from RHEL customers for longer and more extensive and never-ending support cycles, come from the fact that the ecosystem doesn&#39;t follow the standard, and relies on &#34;undefined behavior&#34; of the specific implementation of it.&#xA;&#xA;Think about it: Even a single RHEL minor release, as the most stable and most restricted flow of updates we have at hand, is not bug-to-bug compatible to itself. Yes, we change things and we fix bugs. That&#39;s what updates do. &#xA;&#xA;More to that, even a static snapshot of a RHEL minor release is not a good reference for anything. Paying RHEL customers never have a system deployed exactly in the same state how RHEL engineers test it. Every single customer changes the system so that they cherry-pick certain updates, freeze some other and install custom compatible versions of certain things. And that is generally OK. Until it isn&#39;t and generates the issue and a support case.&#xA;&#xA;The ABI-compatibility standard, which we enforce, gives us both - the limits which we shouldn&#39;t cross, but also the flexibility to adjust within those limits. And any kind of &#34;pinning&#34; to the undefined behavior of a specific shapshot of RHEL at a specific point in time implemented by a third-party or ourselves creates an issue for future updates not knowing about that hidden requirement. &#xA;&#xA;So yes, relying on undefined behavior is bad for business. For all businesses. As well as for community. It is simply bad for all people on Earth who use whatever those businesses and non-businesses create.&#xA;&#xA;What is CentOS Stream really?&#xA;&#xA;CentOS Stream is sort of &#34;RHEL Stable Proposed Updates&#34;. Yes, Red Hat Marketing and Branding folks do not want it to be explained this way, and probably cringe at this very moment. Thus, instead of looking at labels, look at the tech side: It is an ABI-stable and continuous Linux distribution, the mainline of RHEL, from which we branch RHEL minor releases.&#xA;&#xA;But CentOS Stream also represents an open reference implementation of the ABI compatibility standard of the RHEL-compatible ecosystem.&#xA;&#xA;If your RHEL-compatible application or service doesn&#39;t work on CentOS Stream, you do it wrong.&#xA;&#xA;And I&#39;ll rephrase it: people think that they need a RHEL &#34;clone&#34;, because it gives them the access to vendors who develop and test for RHEL. The point though is that to get access to RHEL ecosystem community needs vendors to start develop and test for CentOS Stream. And this is where Red Hat&#39;s interest and community interest overlap.&#xA;&#xA;----&#xA;&#xA;Now some may ask,&#xA;&#xA;but what if my requirements are not covered by that standard?&#xA;&#xA;Then let&#39;s adjust the standard. Bring those requirements in. Do not assume that the requirements, which do not work on CentOS Stream, will somehow magically be fullfilled by RHEL. Because they won&#39;t.&#xA;&#xA;And some may say,&#xA;&#xA;ok, it is interesting, but all this talk about standards and requirements looks really complicated and time-consuming.&#xA;&#xA;Then bring your tests. The easy way to write a standard is to turn it into a distribution-agnostic test.&#xA;&#xA;If you are worried that CentOS Stream will break a certain behavior, write a test and let&#39;s gate all CentOS Stream updates with it (And while we are at it, we can also gate all Fedora updates and even upstream updates using the same test, see Packit )&#xA;&#xA;And then some may say,&#xA;&#xA;but what if my requirements are so special and custom that they can not be a standard for all.&#xA;&#xA;Then you don&#39;t need bug-to-bug compatibility. You need the power of remixing.&#xA;&#xA;Do your own customization via a Special Interest Group SIG, see for example Hyperscale SIG. Make a version which fits your goals, your schedule, your workflow and your quality requirement, but based on the open shared standard of the ecosystem.&#xA;&#xA;Eldevelopment]]&gt;</description>
      <content:encoded><![CDATA[<p><em>Disclaimer: I am a Senior Principal Engineer in Red Hat. I was a member of the RHEL 9/CentOS Stream 9 Bootstrap team. Opinions are my own.</em></p>

<h2 id="tl-dr" id="tl-dr">Tl;dr</h2>

<p>The chase for “bug-to-bug compatibility” hurts community, hurts RHEL customers and hurts the industry as a whole. The real innovation behind the CentOS Stream is the attempt to change it.</p>



<h2 id="what-is-abi-compatibility" id="what-is-abi-compatibility">What is ABI compatibility?</h2>

<p>ABI compatibility is a requirement for certain interfaces to not change for a certain length of time, so that you can safely rely on the availability of a certain function and certain library which behaves in a predictable way.</p>

<p>It is important to know that RHEL ABI compatibility doesn&#39;t say “all ABIs and APIs are stable forever”. The real ABI compatibility of RHEL is described in details in the official ABI Compatibility guidelines:</p>

<p><a href="https://access.redhat.com/articles/rhel9-abi-compatibility" rel="nofollow">https://access.redhat.com/articles/rhel9-abi-compatibility</a></p>

<p>I recommend to take a look and check which compatibility level is assigned to your favorite library according to this guide.</p>

<h2 id="what-is-bug-to-bug-compatibility" id="what-is-bug-to-bug-compatibility">What is bug to bug compatibility?</h2>

<p>The term <em>bug-to-bug compatibility</em> when applied in isolation means that for this specific issue when we implement a new system we carry the bug over to a new implementation. Your users rely on the broken behavior so much that they require it on the new system, see <a href="https://xkcd.com/1172/" rel="nofollow">xkcd/Workflow</a>.</p>

<p>The way the term is applied to RHEL conversation is very generic, and therefore has much less sense. It implies that one Linux distribution has the same bugs as the another.</p>

<p>Linux distribution is not a static thing though. Linux distribution is a pool of package builds, each versioned on its own, and updated on its own, which are then combined into different subsets based on different rules. It is both the power and the weakness of a Linux distribution. The power as the ability to combine and mix and match packages allows you to create solutions to a large range of tasks. The weakness as different combinations of components may lead to different behavior.</p>

<p>Add the branching structure of RHEL to it, with all of its powerful minor-stream complexity, and you&#39;ll realize that there is simply no single state of RHEL, which you can be <em>bug-to-bug compatible to</em>.</p>

<p>Thus, at the distribution level the “bug-to-bug compatibility” concept does not exist. It is an overhyped buzzword people use without putting too much thought into it.</p>

<h2 id="why-does-it-hurt" id="why-does-it-hurt">Why does it hurt</h2>

<p>ABI compatibility guidelines is the open formal standard for the RHEL-compatible ecosystem. It is the <code>.odt</code> kind of specification for Linux distributions. On the other hand, the mythical bug-to-bug compatibility is the <code>.docx</code>. You chase the always moving target which you can not control or predict.</p>

<p>The huge amount of issues coming to RHEL support, and the demand from RHEL customers for longer and more extensive and never-ending support cycles, come from the fact that the ecosystem doesn&#39;t follow the standard, and relies on “undefined behavior” of the specific implementation of it.</p>

<p>Think about it: Even a single RHEL minor release, as the most stable and most restricted flow of updates we have at hand, is not bug-to-bug compatible to itself. Yes, we change things and we fix bugs. That&#39;s what updates do.</p>

<p>More to that, even a static snapshot of a RHEL minor release is not a good reference for anything. Paying RHEL customers never have a system deployed exactly in the same state how RHEL engineers test it. Every single customer changes the system so that they cherry-pick certain updates, freeze some other and install custom <em>compatible</em> versions of certain things. And that is generally OK. Until it isn&#39;t and generates the issue and a support case.</p>

<p>The ABI-compatibility standard, which we enforce, gives us both – the limits which we shouldn&#39;t cross, but also the flexibility to adjust within those limits. And any kind of “pinning” to the undefined behavior of a specific shapshot of RHEL at a specific point in time implemented by a third-party or ourselves creates an issue for future updates not knowing about that hidden requirement.</p>

<p>So yes, relying on undefined behavior is bad for business. For all businesses. As well as for community. It is simply bad for all people on Earth who use whatever those businesses and non-businesses create.</p>

<h2 id="what-is-centos-stream-really" id="what-is-centos-stream-really">What is CentOS Stream really?</h2>

<p>CentOS Stream is sort of “RHEL Stable Proposed Updates”. Yes, Red Hat Marketing and Branding folks do not want it to be explained this way, and probably cringe at this very moment. Thus, instead of looking at labels, look at the tech side: It is an <a href="https://archive.fosdem.org/2022/schedule/event/centos_stream_stable_and_continuous/" rel="nofollow"><em>ABI-stable</em> and <em>continuous</em></a> Linux distribution, the mainline of RHEL, from which we branch RHEL minor releases.</p>

<p>But CentOS Stream also represents an open <strong>reference implementation</strong> of the ABI compatibility standard of the RHEL-compatible ecosystem.</p>

<p>If your RHEL-compatible application or service doesn&#39;t work on CentOS Stream, you do it wrong.</p>

<p>And I&#39;ll rephrase it: people think that they need a RHEL “clone”, because it gives them the access to vendors who develop and test for RHEL. The point though is that to get access to RHEL ecosystem community needs vendors to start develop and test for CentOS Stream. And this is where Red Hat&#39;s interest and community interest overlap.</p>

<hr/>

<p>Now some may ask,</p>
<ul><li>but what if my requirements are not covered by that standard?</li></ul>

<p>Then let&#39;s adjust the standard. Bring those requirements in. Do not assume that the requirements, which do not work on CentOS Stream, will somehow magically be fullfilled by RHEL. Because they won&#39;t.</p>

<p>And some may say,</p>
<ul><li>ok, it is interesting, but all this talk about standards and requirements looks really complicated and time-consuming.</li></ul>

<p>Then bring <em>your</em> <em>tests</em>. The easy way to write a standard is to turn it into a distribution-agnostic test.</p>

<p>If you are worried that CentOS Stream will break a certain behavior, write a test and let&#39;s gate all CentOS Stream updates with it (And while we are at it, we can also gate all Fedora updates and even upstream updates using the same test, see <a href="https://packit.dev/" rel="nofollow">Packit</a> )</p>

<p>And then some may say,</p>
<ul><li>but what if my requirements are so special and custom that they can not be a standard for all.</li></ul>

<p>Then you don&#39;t need bug-to-bug compatibility. You need the power of remixing.</p>

<p>Do your own customization via a Special Interest Group <a href="https://sigs.centos.org/guide/" rel="nofollow">SIG</a>, see for example <a href="https://wiki.centos.org/SpecialInterestGroup/Hyperscale" rel="nofollow">Hyperscale SIG</a>. Make a version which fits your goals, your schedule, your workflow and your quality requirement, but based on the open shared standard of the ecosystem.</p>

<p><a href="https://qi.bookwar.info/tag:Eldevelopment" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">Eldevelopment</span></a></p>
]]></content:encoded>
      <guid>https://qi.bookwar.info/the-curse-of-bug-to-bug-compatibility</guid>
      <pubDate>Tue, 11 Jul 2023 14:14:06 +0000</pubDate>
    </item>
  </channel>
</rss>