<feed
    xmlns="http://www.w3.org/2005/Atom"
    xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xml:lang="en">
  <link rel="self"      type="application/atom+xml" href="https://euandre.org/en/til/feed.ci.xml" />
  <link rel="alternate" type="text/html"            href="https://euandre.org/en/til/" hreflang="en" />
  <title>EuAndreh&apos;s website</title>
  <subtitle>TIL</subtitle>
  <id>https://euandre.org/en/til/feed.ci.xml</id>
  <updated>2026-09-13T12:14:51+00:00</updated>
  <author>
    <name>EuAndreh</name>
    <email>eu@euandre.org</email>
  </author>
  <entry xml:lang="en">
    <title type="html">
      Storing CI data on Git notes
    </title>
    <link type="text/html" rel="alternative" href="https://euandre.org/en/til/2020/11/30/git-notes-ci.html" title="Storing CI data on Git notes" />
    <published>
      2020-11-30T00:00:00+00:00
    </published>
    <id>
      https://euandre.org/en/til/2020/11/30/git-notes-ci.html
    </id>
    <author>
      <name>
        EuAndreh
      </name>
      <email>
        eu@euandre.org
      </email>
    </author>
    <summary type="html">
        &lt;div class=&quot;paragraph&quot;&gt;
          &lt;p&gt;Extending the bare bones CI server I’ve &lt;a href=&quot;../12/diy-nix-bash-ci.html&quot;&gt;talked about before&lt;/a&gt;,
          divoplade on Freenode suggested storing CI artifacts on &lt;a href=&quot;https://git-scm.com/docs/git-notes&quot;&gt;Git
          notes&lt;/a&gt;, such as tarballs, binaries, logs, &lt;em&gt;etc&lt;/em&gt;.&lt;/p&gt;
        &lt;/div&gt;
    </summary>
    <content type="html" xml:base="en/til/2020/11/30/git-notes-ci.html">
        &lt;div class=&quot;paragraph&quot;&gt;
          &lt;p&gt;Extending the bare bones CI server I’ve &lt;a href=&quot;../12/diy-nix-bash-ci.html&quot;&gt;talked about before&lt;/a&gt;,
          divoplade on Freenode suggested storing CI artifacts on &lt;a href=&quot;https://git-scm.com/docs/git-notes&quot;&gt;Git
          notes&lt;/a&gt;, such as tarballs, binaries, logs, &lt;em&gt;etc&lt;/em&gt;.&lt;/p&gt;
        &lt;/div&gt;
        &lt;div class=&quot;paragraph&quot;&gt;
          &lt;p&gt;I’ve written a small script that will put log files and CI job data on Git notes, and make it visible on
          the porcelain log. It is a simple extension of the previous article:&lt;/p&gt;
        &lt;/div&gt;
        &lt;div class=&quot;listingblock&quot;&gt;
          &lt;div class=&quot;content&quot;&gt;
            &lt;table&gt;
              &lt;tbody&gt;
                &lt;tr&gt;
                  &lt;td&gt;
                    &lt;pre class=&quot;lineno&quot;&gt;&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L1&quot;
     href=&quot;#B1-L1&quot;&gt;1&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L2&quot;
     href=&quot;#B1-L2&quot;&gt;2&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L3&quot;
     href=&quot;#B1-L3&quot;&gt;3&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L4&quot;
     href=&quot;#B1-L4&quot;&gt;4&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L5&quot;
     href=&quot;#B1-L5&quot;&gt;5&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L6&quot;
     href=&quot;#B1-L6&quot;&gt;6&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L7&quot;
     href=&quot;#B1-L7&quot;&gt;7&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L8&quot;
     href=&quot;#B1-L8&quot;&gt;8&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L9&quot;
     href=&quot;#B1-L9&quot;&gt;9&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L10&quot;
     href=&quot;#B1-L10&quot;&gt;10&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L11&quot;
     href=&quot;#B1-L11&quot;&gt;11&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L12&quot;
     href=&quot;#B1-L12&quot;&gt;12&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L13&quot;
     href=&quot;#B1-L13&quot;&gt;13&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L14&quot;
     href=&quot;#B1-L14&quot;&gt;14&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L15&quot;
     href=&quot;#B1-L15&quot;&gt;15&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L16&quot;
     href=&quot;#B1-L16&quot;&gt;16&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L17&quot;
     href=&quot;#B1-L17&quot;&gt;17&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L18&quot;
     href=&quot;#B1-L18&quot;&gt;18&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L19&quot;
     href=&quot;#B1-L19&quot;&gt;19&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L20&quot;
     href=&quot;#B1-L20&quot;&gt;20&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L21&quot;
     href=&quot;#B1-L21&quot;&gt;21&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L22&quot;
     href=&quot;#B1-L22&quot;&gt;22&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L23&quot;
     href=&quot;#B1-L23&quot;&gt;23&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L24&quot;
     href=&quot;#B1-L24&quot;&gt;24&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L25&quot;
     href=&quot;#B1-L25&quot;&gt;25&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L26&quot;
     href=&quot;#B1-L26&quot;&gt;26&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L27&quot;
     href=&quot;#B1-L27&quot;&gt;27&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L28&quot;
     href=&quot;#B1-L28&quot;&gt;28&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L29&quot;
     href=&quot;#B1-L29&quot;&gt;29&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L30&quot;
     href=&quot;#B1-L30&quot;&gt;30&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L31&quot;
     href=&quot;#B1-L31&quot;&gt;31&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L32&quot;
     href=&quot;#B1-L32&quot;&gt;32&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L33&quot;
     href=&quot;#B1-L33&quot;&gt;33&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L34&quot;
     href=&quot;#B1-L34&quot;&gt;34&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L35&quot;
     href=&quot;#B1-L35&quot;&gt;35&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L36&quot;
     href=&quot;#B1-L36&quot;&gt;36&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L37&quot;
     href=&quot;#B1-L37&quot;&gt;37&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L38&quot;
     href=&quot;#B1-L38&quot;&gt;38&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L39&quot;
     href=&quot;#B1-L39&quot;&gt;39&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L40&quot;
     href=&quot;#B1-L40&quot;&gt;40&lt;/a&gt;&lt;/pre&gt;
                  &lt;/td&gt;
                  &lt;td&gt;
                    &lt;pre&gt;#!/usr/bin/env bash
set -Eeuo pipefail
set -x

PREFIX=&apos;/srv/ci/vps&apos;
mkdir -p &quot;$PREFIX&quot;
read -r _ SHA _ # oldrev newrev refname
FILENAME=&quot;$(date -Is)-$SHA.log&quot;
LOGFILE=&quot;$PREFIX/$FILENAME&quot;
exec &amp;amp;&amp;gt; &amp;gt;(tee -a &quot;$LOGFILE&quot;)

echo &quot;Starting CI job at: $(date -Is)&quot;

finish() {
  STATUS=&quot;$?&quot;
  printf &quot;\n\n&amp;gt;&amp;gt;&amp;gt; exit status was %s\n&quot; &quot;$STATUS&quot;
  echo &quot;Finishing CI job at: $(date -Is)&quot;
  popd
  NOTE=$(cat &amp;lt;&amp;lt;EOF
See CI logs with:
  git notes --ref=refs/notes/ci-logs show $SHA
  git notes --ref=refs/notes/ci-data show $SHA
EOF
)
  git notes --ref=refs/notes/ci-data add -f -m &quot;$STATUS $FILENAME&quot;
  git notes --ref=refs/notes/ci-logs add -f -F &quot;$LOGFILE&quot;
  git notes add -f -m &quot;$NOTE&quot;
  printf &quot;\n\n&amp;gt;&amp;gt;&amp;gt; CI logs added as Git note.&quot;
}
trap finish EXIT

unset GIT_DIR
CLONE=&quot;$(mktemp -d)&quot;
git clone . &quot;$CLONE&quot;
pushd &quot;$CLONE&quot;
git config --global user.email git@euandre.org
git config --global user.name &apos;EuAndreh CI&apos;

./container make check site
./container make publish&lt;/pre&gt;
                  &lt;/td&gt;
                &lt;/tr&gt;
              &lt;/tbody&gt;
            &lt;/table&gt;
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&quot;paragraph plaintext&quot;&gt;
          &lt;p&gt;&lt;a href=&quot;git-notes-ci.html.0.txt&quot;&gt;plaintext&lt;/a&gt;&lt;/p&gt;
        &lt;/div&gt;
        &lt;div class=&quot;paragraph&quot;&gt;
          &lt;p&gt;The important part is in the &lt;code&gt;finish()&lt;/code&gt; function: - #25 stores the exit status and the
          generated filename separated by spaces; - #26 adds the log file in a note using the
          &lt;code&gt;refs/notes/ci-logs&lt;/code&gt; ref; - #27 it adds a note to the commit saying how to see the logs.&lt;/p&gt;
        &lt;/div&gt;
        &lt;div class=&quot;paragraph&quot;&gt;
          &lt;p&gt;A commit now has an attached note, and shows it whenever you look at it:&lt;/p&gt;
        &lt;/div&gt;
        &lt;div class=&quot;listingblock&quot;&gt;
          &lt;div class=&quot;content&quot;&gt;
            &lt;table&gt;
              &lt;tbody&gt;
                &lt;tr&gt;
                  &lt;td&gt;
                    &lt;pre class=&quot;lineno&quot;&gt;&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L1&quot;
     href=&quot;#B2-L1&quot;&gt;1&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L2&quot;
     href=&quot;#B2-L2&quot;&gt;2&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L3&quot;
     href=&quot;#B2-L3&quot;&gt;3&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L4&quot;
     href=&quot;#B2-L4&quot;&gt;4&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L5&quot;
     href=&quot;#B2-L5&quot;&gt;5&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L6&quot;
     href=&quot;#B2-L6&quot;&gt;6&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L7&quot;
     href=&quot;#B2-L7&quot;&gt;7&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L8&quot;
     href=&quot;#B2-L8&quot;&gt;8&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L9&quot;
     href=&quot;#B2-L9&quot;&gt;9&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L10&quot;
     href=&quot;#B2-L10&quot;&gt;10&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L11&quot;
     href=&quot;#B2-L11&quot;&gt;11&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L12&quot;
     href=&quot;#B2-L12&quot;&gt;12&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L13&quot;
     href=&quot;#B2-L13&quot;&gt;13&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L14&quot;
     href=&quot;#B2-L14&quot;&gt;14&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L15&quot;
     href=&quot;#B2-L15&quot;&gt;15&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L16&quot;
     href=&quot;#B2-L16&quot;&gt;16&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L17&quot;
     href=&quot;#B2-L17&quot;&gt;17&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L18&quot;
     href=&quot;#B2-L18&quot;&gt;18&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L19&quot;
     href=&quot;#B2-L19&quot;&gt;19&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L20&quot;
     href=&quot;#B2-L20&quot;&gt;20&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L21&quot;
     href=&quot;#B2-L21&quot;&gt;21&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L22&quot;
     href=&quot;#B2-L22&quot;&gt;22&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L23&quot;
     href=&quot;#B2-L23&quot;&gt;23&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L24&quot;
     href=&quot;#B2-L24&quot;&gt;24&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L25&quot;
     href=&quot;#B2-L25&quot;&gt;25&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L26&quot;
     href=&quot;#B2-L26&quot;&gt;26&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B2-L27&quot;
     href=&quot;#B2-L27&quot;&gt;27&lt;/a&gt;&lt;/pre&gt;
                  &lt;/td&gt;
                  &lt;td&gt;
                    &lt;pre&gt;$ git show 87c57133abd8be5d7cc46afbf107f59b26066575
commit 87c57133abd8be5d7cc46afbf107f59b26066575
Author: EuAndreh &amp;lt;eu@euandre.org&amp;gt;
Date:   Wed Feb 24 21:58:28 2021 -0300

    vps/machines.scm: Change path to cronjob files

Notes:
    See CI logs with:
      git notes --ref=refs/notes/ci-logs show 87c57133abd8be5d7cc46afbf107f59b26066575
      git notes --ref=refs/notes/ci-data show 87c57133abd8be5d7cc46afbf107f59b26066575

diff --git a/servers/vps/machines.scm b/servers/vps/machines.scm
index d1830ca..a4ccde7 100644
--- a/servers/vps/machines.scm
+++ b/servers/vps/machines.scm
@@ -262,8 +262,8 @@ pki &quot; mail-domain &quot; key  \&quot;&quot; (tls-priv-for mail-domain) &quot;\&quot;&quot;))
             (service mcron-service-type
                      (mcron-configuration
                       (jobs
-                       (list #~(job &quot;30 1 * * 1&quot; &quot;guix gc -d&quot;)
-                             #~(job &quot;30 0 * * *&quot; &quot;/var/lib/euandreh/backup.sh&quot;)))))
+                       (list #~(job &quot;30 1 * * 1&quot; &quot;/opt/bin/gc.sh&quot;)
+                             #~(job &quot;30 0 * * *&quot; &quot;/opt/bin/backup.sh&quot;)))))
             (service dhcp-client-service-type)
             #;
             (service opensmtpd-service-type&lt;/pre&gt;
                  &lt;/td&gt;
                &lt;/tr&gt;
              &lt;/tbody&gt;
            &lt;/table&gt;
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&quot;paragraph plaintext&quot;&gt;
          &lt;p&gt;&lt;a href=&quot;git-notes-ci.html.1.txt&quot;&gt;plaintext&lt;/a&gt;&lt;/p&gt;
        &lt;/div&gt;
        &lt;div class=&quot;paragraph&quot;&gt;
          &lt;p&gt;Other tools such as &lt;a href=&quot;https://git.zx2c4.com/cgit/&quot;&gt;cgit&lt;/a&gt; will also show notes on the web
          interface: &lt;a href=&quot;https://euandre.org/git/servers/commit?id=87c57133abd8be5d7cc46afbf107f59b26066575&quot;
             class=&quot;bare&quot;&gt;https://euandre.org/git/servers/commit?id=87c57133abd8be5d7cc46afbf107f59b26066575&lt;/a&gt;.&lt;/p&gt;
        &lt;/div&gt;
        &lt;div class=&quot;paragraph&quot;&gt;
          &lt;p&gt;You can go even further: since cgit can serve raw blob directly, you can even serve such artifacts (log
          files, release artifacts, binaries) from cgit itself:&lt;/p&gt;
        &lt;/div&gt;
        &lt;div class=&quot;listingblock&quot;&gt;
          &lt;div class=&quot;content&quot;&gt;
            &lt;table&gt;
              &lt;tbody&gt;
                &lt;tr&gt;
                  &lt;td&gt;
                    &lt;pre class=&quot;lineno&quot;&gt;&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B3-L1&quot;
     href=&quot;#B3-L1&quot;&gt;1&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B3-L2&quot;
     href=&quot;#B3-L2&quot;&gt;2&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B3-L3&quot;
     href=&quot;#B3-L3&quot;&gt;3&lt;/a&gt;&lt;/pre&gt;
                  &lt;/td&gt;
                  &lt;td&gt;
                    &lt;pre&gt;$ SHA=&quot;$(git notes --ref=refs/notes/ci-logs list 87c57133abd8be5d7cc46afbf107f59b26066575)&quot;
$ echo &quot;https://euandre.org/git/servers/blob?id=$SHA&quot;
https://euandre.org/git/servers/blob?id=1707a97bae24e3864fe7943f8dda6d01c294fb5c&lt;/pre&gt;
                  &lt;/td&gt;
                &lt;/tr&gt;
              &lt;/tbody&gt;
            &lt;/table&gt;
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&quot;paragraph plaintext&quot;&gt;
          &lt;p&gt;&lt;a href=&quot;git-notes-ci.html.2.txt&quot;&gt;plaintext&lt;/a&gt;&lt;/p&gt;
        &lt;/div&gt;
        &lt;div class=&quot;paragraph&quot;&gt;
          &lt;p&gt;And like that you’ll have cgit serving the artifacts for you: &lt;a href=
          &quot;https://euandre.org/git/servers/blob?id=1707a97bae24e3864fe7943f8dda6d01c294fb5c&quot;
             class=&quot;bare&quot;&gt;https://euandre.org/git/servers/blob?id=1707a97bae24e3864fe7943f8dda6d01c294fb5c&lt;/a&gt;.&lt;/p&gt;
        &lt;/div&gt;
    </content>
  </entry>
  <entry xml:lang="en">
    <title type="html">
      DIY bare bones CI server with Bash and Nix
    </title>
    <link type="text/html" rel="alternative" href="https://euandre.org/en/til/2020/11/12/diy-nix-bash-ci.html" title="DIY bare bones CI server with Bash and Nix" />
    <published>
      2020-11-12T00:00:00+00:00
    </published>
    <id>
      https://euandre.org/en/til/2020/11/12/diy-nix-bash-ci.html
    </id>
    <author>
      <name>
        EuAndreh
      </name>
      <email>
        eu@euandre.org
      </email>
    </author>
    <summary type="html">
        &lt;div id=&quot;preamble&quot;&gt;
          &lt;div class=&quot;sectionbody&quot;&gt;
            &lt;div class=&quot;paragraph&quot;&gt;
              &lt;p&gt;With a server with Nix installed (no need for NixOS), you can leverage its build isolation for running
              CI jobs by adding a &lt;a href=&quot;https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks&quot;&gt;post-receive&lt;/a&gt;
    </summary>
    <content type="html" xml:base="en/til/2020/11/12/diy-nix-bash-ci.html">
        &lt;div id=&quot;preamble&quot;&gt;
          &lt;div class=&quot;sectionbody&quot;&gt;
            &lt;div class=&quot;paragraph&quot;&gt;
              &lt;p&gt;With a server with Nix installed (no need for NixOS), you can leverage its build isolation for running
              CI jobs by adding a &lt;a href=&quot;https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks&quot;&gt;post-receive&lt;/a&gt;
              Git hook to the server.&lt;/p&gt;
            &lt;/div&gt;
            &lt;div class=&quot;paragraph&quot;&gt;
              &lt;p&gt;In most of my project I like to keep a &lt;code&gt;test&lt;/code&gt; attribute which runs the test with
              &lt;code&gt;nix-build -A test&lt;/code&gt;. This way, a post-receive hook could look like:&lt;/p&gt;
            &lt;/div&gt;
            &lt;div class=&quot;listingblock&quot;&gt;
              &lt;div class=&quot;content&quot;&gt;
                &lt;table&gt;
                  &lt;tbody&gt;
                    &lt;tr&gt;
                      &lt;td&gt;
                        &lt;pre class=&quot;lineno&quot;&gt;&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L1&quot;
     href=&quot;#B1-L1&quot;&gt;1&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L2&quot;
     href=&quot;#B1-L2&quot;&gt;2&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L3&quot;
     href=&quot;#B1-L3&quot;&gt;3&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L4&quot;
     href=&quot;#B1-L4&quot;&gt;4&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L5&quot;
     href=&quot;#B1-L5&quot;&gt;5&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L6&quot;
     href=&quot;#B1-L6&quot;&gt;6&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L7&quot;
     href=&quot;#B1-L7&quot;&gt;7&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L8&quot;
     href=&quot;#B1-L8&quot;&gt;8&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L9&quot;
     href=&quot;#B1-L9&quot;&gt;9&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L10&quot;
     href=&quot;#B1-L10&quot;&gt;10&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L11&quot;
     href=&quot;#B1-L11&quot;&gt;11&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L12&quot;
     href=&quot;#B1-L12&quot;&gt;12&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L13&quot;
     href=&quot;#B1-L13&quot;&gt;13&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L14&quot;
     href=&quot;#B1-L14&quot;&gt;14&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L15&quot;
     href=&quot;#B1-L15&quot;&gt;15&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L16&quot;
     href=&quot;#B1-L16&quot;&gt;16&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L17&quot;
     href=&quot;#B1-L17&quot;&gt;17&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L18&quot;
     href=&quot;#B1-L18&quot;&gt;18&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L19&quot;
     href=&quot;#B1-L19&quot;&gt;19&lt;/a&gt;
&lt;a class=&quot;code-line-anchor&quot;
     id=&quot;B1-L20&quot;
     href=&quot;#B1-L20&quot;&gt;20&lt;/a&gt;&lt;/pre&gt;
                      &lt;/td&gt;
                      &lt;td&gt;
                        &lt;pre&gt;#!/usr/bin/env bash
set -Eeuo pipefail
set -x

LOGS_DIR=&quot;/data/static/ci-logs/libedn&quot;
mkdir -p &quot;$LOGS_DIR&quot;
LOGFILE=&quot;${LOGS_DIR}/$(date -Is)-$(git rev-parse master).log&quot;
exec &amp;amp;&amp;gt; &amp;gt;(tee -a &quot;${LOGFILE}&quot;)

unset GIT_DIR
CLONE=&quot;$(mktemp -d)&quot;
git clone . &quot;$CLONE&quot;
pushd &quot;$CLONE&quot;

finish() {
  printf &quot;\n\n&amp;gt;&amp;gt;&amp;gt; exit status was %s\n&quot; &quot;$?&quot;
}
trap finish EXIT

nix-build -A test&lt;/pre&gt;
                      &lt;/td&gt;
                    &lt;/tr&gt;
                  &lt;/tbody&gt;
                &lt;/table&gt;
              &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;paragraph plaintext&quot;&gt;
              &lt;p&gt;&lt;a href=&quot;diy-nix-bash-ci.html.0.txt&quot;&gt;plaintext&lt;/a&gt;&lt;/p&gt;
            &lt;/div&gt;
            &lt;div class=&quot;paragraph&quot;&gt;
              &lt;p&gt;We initially (lines #5 to #8) create a log file, named after &lt;em&gt;when&lt;/em&gt; the run is running and for
              &lt;em&gt;which&lt;/em&gt; commit it is running for. The &lt;code&gt;exec&lt;/code&gt; and &lt;code&gt;tee&lt;/code&gt; combo allows the
              output of the script to go both to &lt;code&gt;stdout&lt;/code&gt; &lt;em&gt;and&lt;/em&gt; the log file. This makes the logs
              output show up when you do a &lt;code&gt;git push&lt;/code&gt;.&lt;/p&gt;
            &lt;/div&gt;
            &lt;div class=&quot;paragraph&quot;&gt;
              &lt;p&gt;Lines #10 to #13 create a fresh clone of the repository and line #20 runs the test command.&lt;/p&gt;
            &lt;/div&gt;
            &lt;div class=&quot;paragraph&quot;&gt;
              &lt;p&gt;After using a similar post-receive hook for a while, I now even generate a simple HTML file to make
              the logs available (&lt;a href=&quot;https://euandreh.xyz/remembering/ci.html&quot;&gt;example project&lt;/a&gt;) through the
              browser.&lt;/p&gt;
            &lt;/div&gt;
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&quot;sect1&quot;&gt;
          &lt;h2 id=&quot;upsides&quot;&gt;Upsides&lt;a class=&quot;anchor&quot;
             href=&quot;#upsides&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
          &lt;div class=&quot;sectionbody&quot;&gt;
            &lt;div class=&quot;paragraph&quot;&gt;
              &lt;p&gt;No vendor lock-in, as all you need is a server with Nix installed.&lt;/p&gt;
            &lt;/div&gt;
            &lt;div class=&quot;paragraph&quot;&gt;
              &lt;p&gt;And if you pin the Nixpkgs version you’re using, this very simple setup yields extremely sandboxed
              runs on a very hermetic environment.&lt;/p&gt;
            &lt;/div&gt;
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&quot;sect1&quot;&gt;
          &lt;h2 id=&quot;downsides&quot;&gt;Downsides&lt;a class=&quot;anchor&quot;
             href=&quot;#downsides&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
          &lt;div class=&quot;sectionbody&quot;&gt;
            &lt;div class=&quot;paragraph&quot;&gt;
              &lt;p&gt;Besides the many missing shiny features of this very simplistic CI, &lt;code&gt;nix-build&lt;/code&gt; can be very
              resource intensive. Specifically, it consumes too much memory. So if it has to download too many things,
              or the build closure gets too big, the server might very well run out of memory.&lt;/p&gt;
            &lt;/div&gt;
          &lt;/div&gt;
        &lt;/div&gt;
    </content>
  </entry>
</feed>
