<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://terceiro.xyz/">
  <id>https://terceiro.xyz/</id>
  <title>Antonio Terceiro</title>
  <updated>2025-09-06T09:19:00Z</updated>
  <link rel="alternate" href="https://terceiro.xyz/" type="text/html"/>
  <link rel="self" href="https://terceiro.xyz/feed.xml" type="application/atom+xml"/>
  <author>
    <name>Antonio Terceiro</name>
    <uri>https://terceiro.xyz</uri>
  </author>
  <entry>
    <id>tag:terceiro.xyz,2025-09-06:/2025/09/06/autopkgtest-support-in-debian-a-more-optimistic-view/</id>
    <title type="html">autopkgtest support in Debian: a more optimistic view</title>
    <published>2025-09-06T09:19:00Z</published>
    <updated>2025-09-06T09:19:00Z</updated>
    <link rel="alternate" href="https://terceiro.xyz/2025/09/06/autopkgtest-support-in-debian-a-more-optimistic-view/" type="text/html"/>
    <content type="html">&lt;p&gt;&lt;a href="../../05/past-halfway-there-history-of-autopkgtest-support-in-debian/"&gt;Yesterday I posted&lt;/a&gt;
about the history, in numbers, of the support for &lt;code&gt;autopkgtest&lt;/code&gt; in the Debian
archive. I had analyzed the presence of a &lt;code&gt;Testsuite:&lt;/code&gt; field in source
packages, from wheezy to trixie, and noticed a slowdown in the growth rate of
&lt;code&gt;autopkgtest&lt;/code&gt; support, in proportional terms. In each new release, the
percentage of packages declaring a test suite grew less than in the previous
release, for the last 4 releases.&lt;/p&gt;

&lt;p&gt;A night of sleep and a rainy morning later, I come back with a more optimistic
view, and present to you the following data, expanded from the raw data:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt; Release year &lt;/th&gt;
&lt;th&gt; Release   &lt;/th&gt;
&lt;th&gt; Yes   &lt;/th&gt;
&lt;th&gt;  No    &lt;/th&gt;
&lt;th&gt; Total &lt;/th&gt;
&lt;th&gt; Δ Yes &lt;/th&gt;
&lt;th&gt; Δ No  &lt;/th&gt;
&lt;th&gt; Δ Total &lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt; 2013         &lt;/td&gt;
&lt;td&gt; wheezy    &lt;/td&gt;
&lt;td&gt; 5     &lt;/td&gt;
&lt;td&gt;  17170 &lt;/td&gt;
&lt;td&gt; 17175 &lt;/td&gt;
&lt;td&gt; --    &lt;/td&gt;
&lt;td&gt; --    &lt;/td&gt;
&lt;td&gt; --      &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; 2015         &lt;/td&gt;
&lt;td&gt; jessie    &lt;/td&gt;
&lt;td&gt; 1112  &lt;/td&gt;
&lt;td&gt;  19484 &lt;/td&gt;
&lt;td&gt; 20596 &lt;/td&gt;
&lt;td&gt; 1107  &lt;/td&gt;
&lt;td&gt; 2314  &lt;/td&gt;
&lt;td&gt; 3421    &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; 2017         &lt;/td&gt;
&lt;td&gt; stretch   &lt;/td&gt;
&lt;td&gt; 5110  &lt;/td&gt;
&lt;td&gt;  19735 &lt;/td&gt;
&lt;td&gt; 24845 &lt;/td&gt;
&lt;td&gt; 3998  &lt;/td&gt;
&lt;td&gt; 251   &lt;/td&gt;
&lt;td&gt; 4249    &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; 2019         &lt;/td&gt;
&lt;td&gt; buster    &lt;/td&gt;
&lt;td&gt; 9966  &lt;/td&gt;
&lt;td&gt;  18535 &lt;/td&gt;
&lt;td&gt; 28501 &lt;/td&gt;
&lt;td&gt; 4856  &lt;/td&gt;
&lt;td&gt; -1200 &lt;/td&gt;
&lt;td&gt; 3656    &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; 2021         &lt;/td&gt;
&lt;td&gt; bullseye  &lt;/td&gt;
&lt;td&gt; 13949 &lt;/td&gt;
&lt;td&gt;  16994 &lt;/td&gt;
&lt;td&gt; 30943 &lt;/td&gt;
&lt;td&gt; 3983  &lt;/td&gt;
&lt;td&gt; -1541 &lt;/td&gt;
&lt;td&gt; 2442    &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; 2023         &lt;/td&gt;
&lt;td&gt; bookworm  &lt;/td&gt;
&lt;td&gt; 17868 &lt;/td&gt;
&lt;td&gt;  16473 &lt;/td&gt;
&lt;td&gt; 34341 &lt;/td&gt;
&lt;td&gt; 3919  &lt;/td&gt;
&lt;td&gt; -521  &lt;/td&gt;
&lt;td&gt; 3398    &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; 2025         &lt;/td&gt;
&lt;td&gt; trixie    &lt;/td&gt;
&lt;td&gt; 21527 &lt;/td&gt;
&lt;td&gt;  16143 &lt;/td&gt;
&lt;td&gt; 37670 &lt;/td&gt;
&lt;td&gt; 3659  &lt;/td&gt;
&lt;td&gt; -330  &lt;/td&gt;
&lt;td&gt; 3329    &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;A few observations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Since stretch, we have been consistently adding &lt;code&gt;autopkgtest&lt;/code&gt; support to
close to 4,000 packages on each release, on average.&lt;/li&gt;
&lt;li&gt;Since buster, the number of packages &lt;em&gt;without&lt;/em&gt; &lt;code&gt;autopkgtest&lt;/code&gt; support has
decreased in the hundreds.&lt;/li&gt;
&lt;li&gt;On average, each release has 3,400 packages more than the previous, while
also bringing 4,000 extra packages with &lt;code&gt;autopkgtest&lt;/code&gt; support. I have the
following hypotheses for this:

&lt;ol&gt;
&lt;li&gt;a large part of new packages are added already with &lt;code&gt;autopkgtest&lt;/code&gt;s;&lt;/li&gt;
&lt;li&gt;a smaller but reasonably large number of existing packages get
&lt;code&gt;autopkgtest&lt;/code&gt;s added on each release.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;All in all, I think this data show that Debian maintainers recognize the
usefulness of automated testing and are engaged in improving our QA process.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:terceiro.xyz,2025-09-05:/2025/09/05/past-halfway-there-history-of-autopkgtest-support-in-debian/</id>
    <title type="html">Past halfway there: history of autopkgtest support in Debian</title>
    <published>2025-09-05T20:22:00Z</published>
    <updated>2025-09-05T20:22:00Z</updated>
    <link rel="alternate" href="https://terceiro.xyz/2025/09/05/past-halfway-there-history-of-autopkgtest-support-in-debian/" type="text/html"/>
    <content type="html">&lt;p&gt;The Release of Debian 13 ("Trixie") last month marked another milestone on the
effort to provide automated test support for Debian packages in their installed
form. We have achieved the mark of 57% of the source packages in the archive
declaring support for &lt;code&gt;autopkgtest&lt;/code&gt;.&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt; &lt;strong&gt;Release&lt;/strong&gt; &lt;/th&gt;
&lt;th&gt; &lt;strong&gt;Packages with tests&lt;/strong&gt; &lt;/th&gt;
&lt;th&gt; &lt;strong&gt;Total number of packages&lt;/strong&gt; &lt;/th&gt;
&lt;th&gt; &lt;strong&gt;% of packages with tests&lt;/strong&gt; &lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt; wheezy &lt;/td&gt;
&lt;td&gt; 5 &lt;/td&gt;
&lt;td&gt; 17175 &lt;/td&gt;
&lt;td&gt; 0% &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; jessie &lt;/td&gt;
&lt;td&gt; 1112 &lt;/td&gt;
&lt;td&gt; 20596 &lt;/td&gt;
&lt;td&gt; 5% &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; stretch &lt;/td&gt;
&lt;td&gt; 5110 &lt;/td&gt;
&lt;td&gt; 24845 &lt;/td&gt;
&lt;td&gt; 20% &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; buster &lt;/td&gt;
&lt;td&gt; 9966 &lt;/td&gt;
&lt;td&gt; 28501 &lt;/td&gt;
&lt;td&gt; 34% &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; bullseye &lt;/td&gt;
&lt;td&gt; 13949 &lt;/td&gt;
&lt;td&gt; 30943 &lt;/td&gt;
&lt;td&gt; 45% &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; bookworm &lt;/td&gt;
&lt;td&gt; 17868 &lt;/td&gt;
&lt;td&gt; 34341 &lt;/td&gt;
&lt;td&gt; 52% &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; trixie &lt;/td&gt;
&lt;td&gt; 21527 &lt;/td&gt;
&lt;td&gt; 37670 &lt;/td&gt;
&lt;td&gt; 57% &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;The code that generated this table is provided &lt;a href="#code"&gt;at the bottom&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The growth rate has been consistently decreasing at each release after stretch.
That probably means that the low hanging fruit -- adding support &lt;em&gt;en masse&lt;/em&gt; for
large numbers of similar packages, such as team-maintained packages for a given
programming language -- has been picked, and from now on the work gets slightly
harder. Perhaps there is a significant long tail of packages that will never
get &lt;code&gt;autopkgtest&lt;/code&gt; support.&lt;/p&gt;

&lt;p&gt;Looking for common prefixes among the packages missing a &lt;code&gt;Testsuite:&lt;/code&gt; field
gives me us the largest groups of packages missing &lt;code&gt;autopkgtest&lt;/code&gt; support:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ grep-dctrl -v -F Testsuite --regex -s Package -n . trixie | cut -d - -f 1 | uniq -c | sort -n| tail -20
     50 apertium
     50 kodi
     51 lomiri
     53 maven
     55 libjs
     57 globus
     66 cl
     67 pd
     72 lua
     79 php
     88 puppet
     91 r
    111 gnome
    124 ruby
    140 ocaml
    152 rust
    178 golang
    341 fonts
    557 python
   1072 haskell
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There seems to be a fair amount of Haskell and Python. If someone could figure
out a way of testing installed fonts in a meaningful way, this would a be a
good niche where we can cover 300+ packages.&lt;/p&gt;

&lt;p&gt;There is a another analysis that can be made, which I didn't: which percentage
of &lt;em&gt;new&lt;/em&gt; packages introduced in a given release have declared &lt;code&gt;autopkgtest&lt;/code&gt;
support, compared with the total of new packages in that release? My data only
counts the totals, so we start with the technical debt of the almost all of the
17,000 packages with no tests in wheezy, which was the &lt;em&gt;stable&lt;/em&gt; at the time I
started &lt;a href="https://ci.debian.net/"&gt;Debian CI&lt;/a&gt;. How many of those got tests since
then?&lt;/p&gt;

&lt;p&gt;Note that not supporting &lt;code&gt;autopkgtest&lt;/code&gt; does not mean that a package is not
tested at all: it can run build-time tests, which are also useful. Not
supporting &lt;code&gt;autopkgtest&lt;/code&gt;, though, means that their binaries in the archive
can't be automatically tested in their installed, but then there is a entire
horde of volunteers running &lt;em&gt;testing&lt;/em&gt; and &lt;em&gt;unstable&lt;/em&gt; on a daily basis who test
Debian and report bugs.&lt;/p&gt;

&lt;p&gt;&lt;a name="code"&gt;&lt;/a&gt;
This is the script that produced the table in the beginning of this post:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-bash"&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-eu&lt;/span&gt;

extract&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;release
  &lt;span class="nb"&gt;local &lt;/span&gt;url
  &lt;span class="nv"&gt;release&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;release&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;release&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.gz"&lt;/span&gt;
    curl &lt;span class="nt"&gt;--silent&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;release&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;.gz &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;gunzip&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;release&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.gz"&lt;/span&gt;
  &lt;span class="k"&gt;fi

  &lt;/span&gt;&lt;span class="nb"&gt;local &lt;/span&gt;with_tests
  &lt;span class="nb"&gt;local &lt;/span&gt;total
  &lt;span class="nv"&gt;with_tests&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;grep-dctrl &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt; Testsuite &lt;span class="nt"&gt;--regex&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$release&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nv"&gt;total&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;grep-dctrl &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt; Package &lt;span class="nt"&gt;--regex&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$release&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"| &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;release&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; | &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;with_tests&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; | &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;total&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; | &lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;with_tests/total&lt;span class="k"&gt;))&lt;/span&gt;&lt;span class="s2"&gt;% |"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"| **Release** | **Packages with tests** | **Total number of packages** | **% of packages with tests** |"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"|-------------|-------------------------|------------------------------|------------------------------|"&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;release &lt;span class="k"&gt;in &lt;/span&gt;wheezy jessie stretch buster&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;extract &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;release&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"http://archive.debian.org/debian/dists/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;release&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/main/source/Sources.gz"&lt;/span&gt;
&lt;span class="k"&gt;done
for &lt;/span&gt;release &lt;span class="k"&gt;in &lt;/span&gt;bullseye bookworm trixie&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;extract &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;release&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"http://ftp.br.debian.org/debian/dists/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;release&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/main/source/Sources.gz"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
</content>
  </entry>
  <entry>
    <id>tag:terceiro.xyz,2024-09-08:/2024/09/08/gotcha-using-ccache-in-debian-package-builds/</id>
    <title type="html">gotcha: using ccache in Debian package builds</title>
    <published>2024-09-08T12:18:00Z</published>
    <updated>2024-09-08T12:18:00Z</updated>
    <link rel="alternate" href="https://terceiro.xyz/2024/09/08/gotcha-using-ccache-in-debian-package-builds/" type="text/html"/>
    <content type="html">&lt;p&gt;Before I upload packages to Debian, I always do a full build from source under
&lt;a href="https://packages.debian.org/sid/sbuild"&gt;sbuild&lt;/a&gt;. This ensures that the package
can build from source on a clean environment, implying that the set of build
dependencies is complete.&lt;/p&gt;

&lt;p&gt;But when iterating on a non-trivial package locally, I will usually build the
package directly on my Debian testing system, and I want to take advantage of
&lt;a href="https://ccache.dev/"&gt;ccache&lt;/a&gt; to cache native (C/C++) code compilation to speed
things up. In Debian, the easiest way to enable &lt;code&gt;ccache&lt;/code&gt; is to add
&lt;code&gt;/usr/lib/ccache&lt;/code&gt; to your &lt;code&gt;$PATH&lt;/code&gt;. I do this by doing something similar to the
following in my &lt;code&gt;~/.bashrc&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-bash"&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/lib/ccache:&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I noticed, however, that my Debian package builds were not using the cache.
When building the same small package manually using make, the cache was used,
but not when the build was wrapped with &lt;code&gt;dpkg-buildpackage&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I tracked it down to the fact that in compatibility level 13+, &lt;code&gt;debhelper&lt;/code&gt; will
set &lt;code&gt;$HOME&lt;/code&gt; to a temporary directory. For what's it worth, I think that's a
good thing: you don't want package builds reaching for your home directory as
that makes it harder to make builds reproducible, among other things.&lt;/p&gt;

&lt;p&gt;This behavior, however, breaks &lt;code&gt;ccache&lt;/code&gt;. The default cache directory is
&lt;code&gt;$HOME/.ccache&lt;/code&gt;, but that only gets resolved when &lt;code&gt;ccache&lt;/code&gt; is actually used. So
we end up starting with an empty cache on each build, get a 100% cache miss
rate, and still pay for the overhead of populating the cache.&lt;/p&gt;

&lt;p&gt;The fix is to explicitly set &lt;code&gt;$CCACHE_DIR&lt;/code&gt; upfront, so that by the time &lt;code&gt;$HOME&lt;/code&gt;
gets overriden, it doesn't matter anymore for &lt;code&gt;ccache&lt;/code&gt;. I did this in my
&lt;code&gt;~/.bashrc&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-bash"&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CCACHE_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;/.ccache&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This way, &lt;code&gt;$HOME&lt;/code&gt; will be expanded right there when the shell starts, and by
the time &lt;code&gt;ccache&lt;/code&gt; is called, it will use the persistent cache in my home
directory even though &lt;code&gt;$HOME&lt;/code&gt; will, at that point, refer to a temporary
directory.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:terceiro.xyz,2023-12-28:/2023/12/28/debian-ci-10-years-later/</id>
    <title type="html">Debian CI: 10 years later</title>
    <published>2023-12-28T15:00:00Z</published>
    <updated>2023-12-28T15:00:00Z</updated>
    <link rel="alternate" href="https://terceiro.xyz/2023/12/28/debian-ci-10-years-later/" type="text/html"/>
    <content type="html">&lt;p&gt;It was 2013, and I was on a break from work between Christmas and New Year of
2013. I had been working at &lt;a href="https://www.linaro.org/"&gt;Linaro&lt;/a&gt; for well over a year, on the &lt;a href="https://www.lavasoftware.org/"&gt;LAVA
project&lt;/a&gt;. I was living and breathing automated testing infrastructure,
mostly for testing low-level components such as kernels and bootloaders, on
real hardware.&lt;/p&gt;

&lt;p&gt;At this point I was also a Debian contributor for quite some years, and had
become an official project members two years prior. Most of my involvement was
in the Ruby team, where we were already consistently running upstream test
suites during package builds.&lt;/p&gt;

&lt;p&gt;During that break, I put these two contexts together, and came to the
conclusion that Debian needed a dedicated service that would test the contents
of the Debian archive. I was aware of the existance of
&lt;a href="https://packages.debian.org/sid/autopkgtest"&gt;autopkgtest&lt;/a&gt;, and started working on a very simple service that
would later become &lt;a href="https://ci.debian.net/"&gt;Debian CI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In January 2014, &lt;code&gt;debci&lt;/code&gt; was initially announced on that month's &lt;a href="https://lists.debian.org/debian-devel-announce/2014/01/msg00007.html"&gt;Misc
Developer News&lt;/a&gt;, and later &lt;a href="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=736416"&gt;uploaded to Debian&lt;/a&gt;. It's been
continuously developed for the last 10 years, evolved from a single shell
script running tests in a loop into a distributed system with 47
geographically-distributed machines as of writing this piece, became part of
the official Debian release process gating migrations to testing, had 5 Summer
of Code and Outrechy interns working on it, and processed beyond 40 million
test runs.&lt;/p&gt;

&lt;p&gt;In there years, Debian CI has received contributions from a lot of people, but
I would like to give special credits to the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ian Jackson - created autopkgtest.&lt;/li&gt;
&lt;li&gt;Martin Pitt - was the maintainer of autopkgtest when Debian CI launched and
helped a lot for some time.&lt;/li&gt;
&lt;li&gt;Paul Gevers - decided that he wanted Debian CI test runs to control testing
migration. While at it, became a member of the Debian Release Team and the
other half of the permanent Debian CI team together with me.&lt;/li&gt;
&lt;li&gt;Lucas Kanashiro - Google Summer of Code intern, 2014.&lt;/li&gt;
&lt;li&gt;Brandon Fairchild - Google Summer of Code intern, 2014.&lt;/li&gt;
&lt;li&gt;Candy Tsai - Outreachy intern, 2019.&lt;/li&gt;
&lt;li&gt;Pavit Kaur - Google Summer of Code intern, 2021&lt;/li&gt;
&lt;li&gt;Abiola Ajadi - Outreachy intern, December 2021-2022.&lt;/li&gt;
&lt;/ul&gt;

</content>
  </entry>
  <entry>
    <id>tag:terceiro.xyz,2021-10-12:/2021/10/12/triaging-debian-build-failure-logs-with-collab-qa-tools/</id>
    <title type="html">Triaging Debian build failure logs with collab-qa-tools</title>
    <published>2021-10-12T08:30:00Z</published>
    <updated>2021-10-12T08:30:00Z</updated>
    <link rel="alternate" href="https://terceiro.xyz/2021/10/12/triaging-debian-build-failure-logs-with-collab-qa-tools/" type="text/html"/>
    <content type="html">&lt;p&gt;The Ruby team is working now on transitioning to ruby 3.0. Even though most
packages will work just fine, there is substantial amount of packages that
require some work to adapt. We have been doing test rebuilds for a while during
transitions, but usually triaged the problems manually.&lt;/p&gt;

&lt;p&gt;This time I decided to try
&lt;a href="https://salsa.debian.org/lucas/collab-qa-tools"&gt;collab-qa-tools&lt;/a&gt;, a set of
scripts Lucas Nussbaum uses when he does archive-wide rebuilds. I'm really glad
that I did, because those tols save a lot of time when processing a large
number of build failures. In this post, I will go through how to triage a set
of build logs using collab-qa-tools.&lt;/p&gt;

&lt;p&gt;I have
&lt;a href="https://salsa.debian.org/lucas/collab-qa-tools/-/merge_requests/13"&gt;made&lt;/a&gt;
&lt;a href="https://salsa.debian.org/lucas/collab-qa-tools/-/merge_requests/14"&gt;some&lt;/a&gt;
&lt;a href="https://salsa.debian.org/lucas/collab-qa-tools/-/merge_requests/15"&gt;improvements&lt;/a&gt;
to the code. Given my last merge request is very new and was not merged yet,
a few of the things I mention here may apply only to
&lt;a href="https://salsa.debian.org/terceiro/collab-qa-tools/-/tree/ruby3.0"&gt;my own &lt;code&gt;ruby3.0&lt;/code&gt; branch&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;collab-qa-tools also contains a few tools do perform the builds in the
cloud, but since we already had the builds done, I will not be mentioning that
part and will write exclusively about the triaging tools.&lt;/p&gt;

&lt;h2&gt;Installing collab-qa-tools&lt;/h2&gt;

&lt;p&gt;The first step is to clone the git repository.  Make sure you have the
dependencies from &lt;code&gt;debian/control&lt;/code&gt; installed (a few Ruby libraries).&lt;/p&gt;

&lt;p&gt;One of the patches I sent, and was already accepted, is the ability to run it
without the need to install:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;source /path/to/collab-qa-tools/activate.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will add the tools to your $PATH.&lt;/p&gt;

&lt;h2&gt;Preparation&lt;/h2&gt;

&lt;p&gt;The first think you need to do is getting all your build logs in a directory.
The tools assume &lt;code&gt;.log&lt;/code&gt; file extension, and they can be named
&lt;code&gt;${PACKAGE}_*.log&lt;/code&gt; or just &lt;code&gt;${PACKAGE}.log&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;Creating a TODO file&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;cqa-scanlogs | grep -v OK  | sed -e 's/$/ -- TODO/' &amp;gt; todo
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;todo&lt;/code&gt; will contain one line for each log with a summary of the failure, if
it's able to find one. collab-qa-tools has a large set of regular expressions
for finding errors in the build logs&lt;/p&gt;

&lt;p&gt;It's a good idea to split the TODO file in multiple ones. This can easily be
done with &lt;code&gt;split(1)&lt;/code&gt;, and can be used to delimit triaging sessions, and/or to
split the triaging between multiple people. For example this will create
&lt;code&gt;todo&lt;/code&gt; into &lt;code&gt;todo00&lt;/code&gt;, &lt;code&gt;todo01&lt;/code&gt;, ..., each containing 30 lines:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;split --lines=30 --numeric-suffixes todo todo
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Triaging&lt;/h2&gt;

&lt;p&gt;You can now do the triaging. Let's say we split the TODO files, and will start
with &lt;code&gt;todo01&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The first step is calling &lt;code&gt;cqa-fetchbugs&lt;/code&gt; (it does what it says on the tin):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cqa-fetchbugs --TODO=todo01
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then, &lt;code&gt;cqa-annotate&lt;/code&gt; will guide you through the logs and allow you to report
bugs:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cqa-annotate --TODO=todo01
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I wrote myself a &lt;code&gt;process.sh&lt;/code&gt; wrapper script for &lt;code&gt;cqa-fetchbugs&lt;/code&gt; and
&lt;code&gt;cqa-annotate&lt;/code&gt; that looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-bash"&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-eu&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;todo &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c"&gt;# force downloading bugs&lt;/span&gt;
  &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print(".bugs." $1)}'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;todo&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | xargs &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt;
  cqa-fetchbugs &lt;span class="nt"&gt;--TODO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;todo&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

  cqa-annotate &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--template&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;template.txt.jinja2 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--TODO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;todo&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;--template&lt;/code&gt; option is a recent contribution of mine. This is a template
for the bug reports you will be sending. It uses
&lt;a href="https://github.com/Shopify/liquid/wiki/Liquid-for-Designers"&gt;Liquid templates&lt;/a&gt;,
which is very similar to Jinja2 for Python. You will notice that I am even
pretending it &lt;em&gt;is&lt;/em&gt; Jinja2 to trick vim into doing syntax highlighting
for me. The template I'm using looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-jinja"&gt;From: &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;fullname&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;email&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
To: submit@bugs.debian.org
Subject: &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;package&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;: FTBFS with ruby3.0: &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;summary&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;

Source: &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;package&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
Version: &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;version&lt;/span&gt; &lt;span class="o"&gt;| &lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="s1"&gt;'+rebuild'&lt;/span&gt; &lt;span class="o"&gt;| &lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
Severity: serious
Justification: FTBFS
Tags: bookworm sid ftbfs
User: debian-ruby@lists.debian.org
Usertags: ruby3.0

Hi,

We are about to enable building against ruby3.0 on unstable. During a test
rebuild, &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;package&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt; was found to fail to build in that situation.

To reproduce this locally, you need to install ruby-all-dev from experimental
on an unstable system or build chroot.

Relevant part (hopefully):
&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;extract&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;&amp;gt; &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;line&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;endfor&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;

The full build log is available at
https://people.debian.org/~kanashiro/ruby3.0/round2/builds/3/&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;package&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;/&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;| &lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;".log"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;".build.txt"&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;The cqa-annotate loop&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;cqa-annotate&lt;/code&gt; will parse each log file, display an extract of what it found as
possibly being the relevant part, and wait for your input:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;######## ruby-cocaine_0.5.8-1.1+rebuild1633376733_amd64.log ########
--------- Error:
     Failure/Error: undef_method :exitstatus

     FrozenError:
       can't modify frozen object: pid 2351759 exit 0
     # ./spec/support/unsetting_exitstatus.rb:4:in `undef_method'
     # ./spec/support/unsetting_exitstatus.rb:4:in `singleton class'
     # ./spec/support/unsetting_exitstatus.rb:3:in `assuming_no_processes_have_been_run'
     # ./spec/cocaine/errors_spec.rb:55:in `block (2 levels) in &amp;lt;top (required)&amp;gt;'

Deprecation Warnings:

Using `should` from rspec-expectations' old `:should` syntax without explicitly enabling the syntax is deprecated. Use the new `:expect` syntax or explicitly enable `:should` with `config.expect_with(:rspec) { |c| c.syntax = :should }` instead. Called from /&amp;lt;&amp;lt;PKGBUILDDIR&amp;gt;&amp;gt;/spec/cocaine/command_line/runners/backticks_runner_spec.rb:19:in `block (2 levels) in &amp;lt;top (required)&amp;gt;'.


If you need more of the backtrace for any of these deprecations to
identify where to make the necessary changes, you can configure
`config.raise_errors_for_deprecations!`, and it will turn the
deprecation warnings into errors, giving you the full backtrace.

1 deprecation warning total

Finished in 6.87 seconds (files took 2.68 seconds to load)
67 examples, 1 failure

Failed examples:

rspec ./spec/cocaine/errors_spec.rb:54 # When an error happens does not blow up if running the command errored before execution

/usr/bin/ruby3.0 -I/usr/share/rubygems-integration/all/gems/rspec-support-3.9.3/lib:/usr/share/rubygems-integration/all/gems/rspec-core-3.9.2/lib /usr/share/rubygems-integration/all/gems/rspec-core-3.9.2/exe/rspec --pattern ./spec/\*\*/\*_spec.rb --format documentation failed
ERROR: Test "ruby3.0" failed:
----------------
ERROR: Test "ruby3.0" failed:      Failure/Error: undef_method :exitstatus
----------------
package: ruby-cocaine
lines: 30
------------------------------------------------------------------------
s: skip
i: ignore this package permanently
r: report new bug
f: view full log
------------------------------------------------------------------------
Action [s|i|r|f]:
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can then choose one of the options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;s&lt;/code&gt; - skip this package and do nothing. You can run &lt;code&gt;cqa-annotate&lt;/code&gt; again
later and come back to it.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;i&lt;/code&gt; - ignore this package completely. New runs of &lt;code&gt;cqa-annotate&lt;/code&gt; won't ask
about it again.&lt;/p&gt;

&lt;p&gt;This is useful if the package only fails in your rebuilds due to another
package, and would just work when that other package gets fixes. In the Ruby
transition this happens when A depends on B, while B builds a C extension and
failed to build against the new Ruby. So once B is fixed, A should
just work (in principle). But even if A would even have problems of its own,
we can't really know before B is fixed so we can retry A.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;r&lt;/code&gt; - report a bug. &lt;code&gt;cqa-annotate&lt;/code&gt; will expand the template with the data
from the current log, and feed it to mutt. This is currently a limitation:
you have to use mutt to report bugs.&lt;/p&gt;

&lt;p&gt;After you report the bug, &lt;code&gt;cqa-annotate&lt;/code&gt; will ask if it should edit the TODO
file. In my opinion it's best to not do this, and annotate the package with a
bug number when you have one (see below).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;f&lt;/code&gt; - view the full log. This is useful when the extract displayed doesn't
have enough info, or you want to inspect something that happened earlier (or
later) during the build.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;When there are existing bugs in the package, &lt;code&gt;cqa-annotate&lt;/code&gt; will list them
among the options. If you choose a bug number, the TODO file will be annotated
with that bug number and new runs of &lt;code&gt;cqa-annotate&lt;/code&gt; will not ask about that
package anymore. For example after I reported a bug for &lt;code&gt;ruby-cocaine&lt;/code&gt; for the
issue listed above, I aborted with a &lt;code&gt;ctrl-c&lt;/code&gt;, and when I run my &lt;code&gt;process.sh&lt;/code&gt;
script again I then get this prompt:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;----------------
ERROR: Test "ruby3.0" failed:      Failure/Error: undef_method :exitstatus
----------------
package: ruby-cocaine
lines: 30
------------------------------------------------------------------------
s: skip
i: ignore this package permanently
1: 996206 serious ruby-cocaine: FTBFS with ruby3.0: ERROR: Test "ruby3.0" failed:      Failure/Error: undef_method :exitstatus ||
r: report new bug
f: view full log
------------------------------------------------------------------------
Action [s|i|1|r|f]:
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Chosing &lt;code&gt;1&lt;/code&gt; will annotate the TODO file with the bug number, and I'm done with
this package. Only a few other hundreds to go.&lt;/p&gt;
</content>
  </entry>
</feed>

