<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>deterministic &amp;mdash; csantosb</title>
    <link>https://infosec.press/csantosb/tag:deterministic</link>
    <description>Random thoughts</description>
    <pubDate>Tue, 16 Jun 2026 03:50:44 +0000</pubDate>
    <item>
      <title>ci (gitlab/hub)</title>
      <link>https://infosec.press/csantosb/ci-gitlab-hub</link>
      <description>&lt;![CDATA[img br/&#xA;Remote #ci is the way to go in #modernhw digital design testing. In this #ciseries, let’s see it in practice with some detail using two of the most popular forges out there. !--more-- br/&#xA;&#xA;Gitlab&#xA;&#xA;The gitlab #gitforge includes tones of features. Among these, a facility called the container registry, which stores per project container images. Guix pack allows the creation of custom #reproductible environments as images. In particular, it is possible to create a docker image out of our manifest and channels files with br/&#xA;&#xA;guix time-machine -C channels.scm -- pack --compression=xz --save-provenance -f docker -m manifest.scm&#xA;&#xA;Check the documentation for options. br/&#xA;Remember that there are obviously alternative methods to produce docker images. The point on using guix resides on its reproducibility capabilities: you’ll be able to create a new, identical docker image, out of the manifest and channels files at any point in time. Even more: you’ll have the capacity to retrieve your manifest file out of the binary image in case your manifest file gets lost. br/&#xA;Then, this image must be loaded into the local docker store with br/&#xA;&#xA;docker load &lt; IMAGE&#xA;&#xA;and renamed to something meaningful br/&#xA;&#xA;docker tag IMAGE:latest gitlab-registry.whatever.fr/domain/group/NAME:TAG&#xA;&#xA;go remote&#xA;&#xA;img br/&#xA;Finally, pushed to the remote container registry of your project with br/&#xA;&#xA;docker push gitlab-registry.whatever.fr/domain/group/NAME:TAG&#xA;&#xA;At this point, you have an environment where you’ll run your tests using gitlab&#39;s ci features. You’ll set up your gitlab’s runners and manifest files to use this container to execute your jobs. br/&#xA;As an alternative, you could use a ssh executor running on your own fast and powerful hardware resources (dedicated machine, shared cluster, etc.). In this case, you’d rather produce an apptainer  container image with: br/&#xA;&#xA;guix time-machine -C channels.scm -- pack -f squashfs ...&#xA;&#xA;scp this container file to your computing resources and call it from the #gitlab runner. br/&#xA;&#xA;Github&#xA;&#xA;The github is probably the most popular #gitforge out there. It follows a similar to #gitlab in its conception (pull requests and merge requests, you catch the idea ?). It also includes a container registry, and the set of features if offers may be exchanged with ease with any other #gitforge following the same paradigm. No need to go into more details. br/&#xA;There is a couple of interesting tips about using #github, though. It happens more usually than not that users encounter frequently problems of #reproducibility when using container images hosted on ghcr.io, the hosting service for user images. These images are usually employed for running #ci testing pipelines, and they usually break as upstream changes happen: updates, image definition changes, image packages upgrades, etc. If you read my dependencies hell post, this should ring a bell. br/&#xA;What can be done about in what concerns #modernhw ? Well, we have #guix. Let’s try a differente approach: building an image locally, and pushing it to #github registry. Let’s see how. br/&#xA;&#xA;in practice&#xA;&#xA;An example repository shows tha way to proceed. Its contents allow to create a docker container image to be hosted remotely. It includes all that’s necessary to perform remote #ci testing of a #modernhw #vhdl design. br/&#xA;&#xA;docker pull ghcr.io/csantosb/hdl&#xA;docker images # check $ID&#xA;docker run -ti $ID bash&#xA;&#xA;It includes a couple of #plaintext files to produce a #deterministic container. First, the channels.scm file with the list of guix chanels to use to pull packages from. Then, a manifest.scm, with the list of packages to be install within the container. br/&#xA;The image container may be build with br/&#xA;&#xA;image=$(guix time-machine --channels=channels.scm -- \&#xA;             pack -f docker \&#xA;             -S /bin=bin \&#xA;             --save-provenance \&#xA;             -m manifest.scm)&#xA;&#xA;At this point, it is to be load to the docker store with br/&#xA;&#xA;docker load &lt; $image&#xA;docker images&#xA;&#xA;Now it is time to tag the image br/&#xA;&#xA;docker tag IMID ghcr.io/USER/REPO:RELEASE&#xA;&#xA;and login to ghcr.io br/&#xA;&#xA;docker login -u USER -p PASSWORD ghcr.io&#xA;&#xA;Finally, the image is to be push remotely br/&#xA;&#xA;docker push ghcr.io/USER/HDL:RELEASE&#xA;&#xA;test&#xA;&#xA;You’ll may test this image using the neorv32 project, for example, with: br/&#xA;&#xA;docker pull ghcr.io/csantosb/hdl&#xA;docker run -ti ID bash&#xA;git clone --depth=1 https://github.com/stnolting/neorv32&#xA;cd neorv32&#xA;git clone --depth=1 https://github.com/stnolting/neorv32-vunit test&#xA;cd test&#xA;rm -rf neorv32&#xA;ln -sf ../../neorv32 neorv32&#xA;python3 sim/run.py --ci-mode -v&#xA;`]]&gt;</description>
      <content:encoded><![CDATA[<p><img src="https://git.sr.ht/~csantosb/csbwiki/blob/master/pics/gitlab.png" alt="img"> <br/>
Remote <a href="/csantosb/tag:ci" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">ci</span></a> is the <a href="https://infosec.press/csantosb/tag:ciseries" rel="nofollow">way to go</a> in <a href="/csantosb/tag:modernhw" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">modernhw</span></a> digital design testing. In this <a href="/csantosb/tag:ciseries" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">ciseries</span></a>, let’s see it in practice with some detail using two of the most popular forges out there.  <br/></p>

<h1 id="gitlab">Gitlab</h1>

<p>The <a href="https://gitlab.com/" rel="nofollow">gitlab</a> <a href="/csantosb/tag:gitforge" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">gitforge</span></a> includes tones of features. Among these, a facility called the <a href="https://docs.gitlab.com/ee/user/packages/container_registry/" rel="nofollow">container registry</a>, which stores per project container images. <a href="https://infosec.press/csantosb/guix-crash-course#packs" rel="nofollow">Guix pack</a> allows the creation of custom <a href="/csantosb/tag:reproductible" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">reproductible</span></a> environments as images. In particular, it is possible to create a docker image out of our <a href="https://infosec.press/csantosb/guix-crash-course#manifest-channels" rel="nofollow">manifest and channels files</a> with <br/></p>

<pre><code class="language-sh">guix time-machine -C channels.scm -- pack --compression=xz --save-provenance -f docker -m manifest.scm
</code></pre>

<p>Check the <a href="https://guix.gnu.org/manual/en/html_node/Invoking-guix-pack.html" rel="nofollow">documentation</a> for options. <br/>
Remember that there are obviously alternative methods to produce docker images. The point on using guix resides on its <a href="https://infosec.press/csantosb/use-guix#reproducibility" rel="nofollow">reproducibility</a> capabilities: you’ll be able to create a new, identical docker image, out of the <a href="https://infosec.press/csantosb/guix-crash-course#manifest-channels" rel="nofollow">manifest and channels files</a> at any point in time. Even more: you’ll have the capacity to retrieve your manifest file out of the binary image in case your manifest file gets lost. <br/>
Then, this image must be loaded into the local docker store with <br/></p>

<pre><code class="language-shell">docker load &lt; IMAGE
</code></pre>

<p>and renamed to something meaningful <br/></p>

<pre><code class="language-shell">docker tag IMAGE:latest gitlab-registry.whatever.fr/domain/group/NAME:TAG
</code></pre>

<h2 id="go-remote">go remote</h2>

<p><img src="https://git.sr.ht/~csantosb/csbwiki/blob/master/pics/ci2.png" alt="img"> <br/>
Finally, pushed to the remote container registry of your project with <br/></p>

<pre><code class="language-shell">docker push gitlab-registry.whatever.fr/domain/group/NAME:TAG
</code></pre>

<p>At this point, you have an environment where you’ll run your tests using <a href="https://docs.gitlab.com/ee/ci/" rel="nofollow">gitlab&#39;s ci</a> features. You’ll set up your gitlab’s <a href="https://docs.gitlab.com/runner/" rel="nofollow">runners</a> and <a href="https://docs.gitlab.com/ee/ci/#step-1-create-a-gitlab-ciyml-file" rel="nofollow">manifest files</a> to use this container to execute your jobs. <br/>
As an alternative, you could use a <a href="https://docs.gitlab.com/runner/executors/ssh.html" rel="nofollow">ssh executor</a> running on your own fast and powerful hardware resources (dedicated machine, shared cluster, etc.). In this case, you’d rather produce an apptainer  container image with: <br/></p>

<pre><code class="language-sh">guix time-machine -C channels.scm -- pack -f squashfs ...
</code></pre>

<p><code>scp</code> this container file to your computing resources and call it from the <a href="/csantosb/tag:gitlab" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">gitlab</span></a> runner. <br/></p>

<h1 id="github">Github</h1>

<p>The <a href="https://github.com/" rel="nofollow">github</a> is probably the most popular <a href="/csantosb/tag:gitforge" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">gitforge</span></a> out there. It follows a similar to <a href="/csantosb/tag:gitlab" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">gitlab</span></a> in its conception (pull requests and merge requests, you catch the idea ?). It also includes a <a href="https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry" rel="nofollow">container registry</a>, and the set of features if offers may be exchanged with ease with any other <a href="/csantosb/tag:gitforge" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">gitforge</span></a> following the same paradigm. No need to go into more details. <br/>
There is a couple of interesting tips about using <a href="/csantosb/tag:github" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">github</span></a>, though. It happens more usually than not that users encounter frequently problems of <a href="/csantosb/tag:reproducibility" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">reproducibility</span></a> when using container images hosted on <code>ghcr.io</code>, the hosting service for user images. These images are usually employed for running <a href="/csantosb/tag:ci" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">ci</span></a> testing pipelines, and they <a href="https://github.com/stnolting/neorv32/issues/1116#issuecomment-2532796271" rel="nofollow">usually break</a> as upstream changes happen: updates, image definition changes, image packages upgrades, etc. If you read my <a href="https://infosec.press/csantosb/on-dependencies" rel="nofollow">dependencies hell</a> post, this should ring a bell. <br/>
What can be done about in what concerns <a href="/csantosb/tag:modernhw" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">modernhw</span></a> ? Well, we have <a href="/csantosb/tag:guix" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">guix</span></a>. Let’s try a differente approach: building an image locally, and pushing it to <a href="/csantosb/tag:github" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">github</span></a> registry. Let’s see how. <br/></p>

<h2 id="in-practice">in practice</h2>

<p>An <a href="https://github.com/csantosb/hdl-image.git" rel="nofollow">example repository</a> shows tha way to proceed. Its contents allow to create a docker container image to be hosted remotely. It includes <a href="https://raw.githubusercontent.com/csantosb/hdl-image/refs/heads/master/manifest.scm" rel="nofollow">all that’s necessary</a> to perform remote <a href="/csantosb/tag:ci" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">ci</span></a> testing of a <a href="/csantosb/tag:modernhw" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">modernhw</span></a> <a href="/csantosb/tag:vhdl" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">vhdl</span></a> design. <br/></p>

<pre><code class="language-sh">docker pull ghcr.io/csantosb/hdl
docker images # check $ID
docker run -ti $ID bash
</code></pre>

<p>It includes a couple of <a href="/csantosb/tag:plaintext" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">plaintext</span></a> <a href="https://infosec.press/csantosb/guix-crash-course#manifest-channels" rel="nofollow">files</a> to produce a <a href="/csantosb/tag:deterministic" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">deterministic</span></a> container. First, the <a href="https://github.com/csantosb/hdl-image/blob/master/channels.scm" rel="nofollow">channels.scm</a> file with the list of guix chanels to use to pull packages from. Then, a <a href="https://github.com/csantosb/hdl-image/blob/master/manifest.scm" rel="nofollow">manifest.scm</a>, with the list of packages to be install within the container. <br/>
The image container may be <a href="https://git.sr.ht/~csantosb/hdl-image/tree/b1ab9a56802e56e3326c8985bd1b61c93173c5ab/readme.org#L3" rel="nofollow">build</a> with <br/></p>

<pre><code class="language-sh">image=$(guix time-machine --channels=channels.scm -- \
             pack -f docker \
             -S /bin=bin \
             --save-provenance \
             -m manifest.scm)
</code></pre>

<p>At this point, it is to be load to the docker store with <br/></p>

<pre><code class="language-sh">docker load &lt; $image
# docker images
</code></pre>

<p>Now it is time to tag the image <br/></p>

<pre><code class="language-sh">docker tag IMID ghcr.io/USER/REPO:RELEASE
</code></pre>

<p>and login to <code>ghcr.io</code> <br/></p>

<pre><code class="language-sh">docker login -u USER -p PASSWORD ghcr.io
</code></pre>

<p>Finally, the image is to be push remotely <br/></p>

<pre><code class="language-sh">docker push ghcr.io/USER/HDL:RELEASE
</code></pre>

<h2 id="test">test</h2>

<p>You’ll may test this image using the <a href="https://github.com/stnolting/neorv32" rel="nofollow">neorv32</a> project, for example, with: <br/></p>

<pre><code class="language-sh">docker pull ghcr.io/csantosb/hdl
docker run -ti ID bash
git clone --depth=1 https://github.com/stnolting/neorv32
cd neorv32
git clone --depth=1 https://github.com/stnolting/neorv32-vunit test
cd test
rm -rf neorv32
ln -sf ../../neorv32 neorv32
python3 sim/run.py --ci-mode -v
</code></pre>
]]></content:encoded>
      <guid>https://infosec.press/csantosb/ci-gitlab-hub</guid>
      <pubDate>Wed, 11 Dec 2024 12:50:04 +0000</pubDate>
    </item>
    <item>
      <title>ci (intro)</title>
      <link>https://infosec.press/csantosb/ci-intro</link>
      <description>&lt;![CDATA[img br/&#xA;How to seek, detect, be notified, analyze logs, understand and react to the different possible kind of issues one may encounter in a digital design is a vast topic of research, well beyond the scope of this modest post. But there are a couple of things we may state about here, though: automatizing issue detection is the way to go. Continuous integration (#ci) testing is a practice to adopt in #modernhw as a way to ensure that our design complies with its constraints. Let’s see this in more detail. !--more-- br/&#xA;&#xA;git&#xA;&#xA;We said #git, then, as mandatory when tracking changes (in documentation, project development, taking notes, etc.). Meaningful changes imply new commits (and good commit messages, for what it takes), but this comes along with a risk of introducing issues. Some kind of mechanism is necessary to automatize the execution of a checkout list to be run per new commit. The list is project aware, for sure, but may also be different following the git branch, and even the kind of commit (merges are to be considered differently to regular commits in topic branches, for example). We need to consider what an issue exactly is, and then you’ll need to adopt a different perspective on kinds of checkout lists. br/&#xA;&#xA;verification&#xA;&#xA;First (ideally), one starts with clear specifications about the goals of current development effort (in practice this never happens in research, and if you ever have it, they’ll evolve with time). These specifications (you’ll figure out where to find them somehow) will define the tests to run. For example, if you need to implement in firmware a deep neural network, you’ll probably have access to a test data set to verify the outcomes are correct. You may tune, improve or even completely change the architecture of your network, at the very end, you’ll have to verify your design with help of the test data set. Additionally, you may define more sophisticated tests: consumption, area, resources, etc. These all fall into the category of verification testing. br/&#xA;&#xA;unit tests&#xA;&#xA;Secondly, you’ll be running unit tests during your whole design cycle (and they’ll evolve along with it), and target tests (the one we mentioned just before). Does this addition perform correctly ? What if we stress a module with random inputs ? Are we going through all code in a given design unit ? Do we cover all values of some input/output signal in this important module ? These are all unit testing checkouts, and they’ll help us to detect issues in an early stage of design. br/&#xA;&#xA;codesign&#xA;&#xA;Codesign falls somewhere in between the two previous: as a testing methodology, it includes concepts of verification and unit testing (and can be combined with them). It is way more ambitious and complex, but also more powerful. No matter your testing strategy, the point here is that you’ll be running these tests (fully or partially) automatically at the several different stages of your development cycle. If they fail, you’ll have to be warned. br/&#xA;&#xA;guix&#xA;&#xA;img br/&#xA;Guix, as a package manager, provides all necessary software to deploy our tests (and can be extended with additional tooling). It also includes all that&#39;s necessary to create a running environment where we will execute our tests. Most importantly, #guix does so in a #deterministic and #reproductible way: we will be able to reproduce our tests in the future under exactly the same conditions. Shell containers, profiles and the time machine mechanism allow the degree of #reproducibility we need here. All it takes is a couple of text files. br/&#xA;&#xA;---&#xA;&#xA;Most usually, we will focus on two strategies to seek for issues: local, and remote. Local strategies are greatly based on git hooks, and will be topic of another post. Let’s see now in practice what can be done with help of remote tools, based on #ci, understood as a methodology consisting on automatically executing a set of tests procedures on a digital design. br/&#xA;ciseries br/]]&gt;</description>
      <content:encoded><![CDATA[<p><img src="https://git.sr.ht/~csantosb/csbwiki/blob/master/pics/ci.png" alt="img"> <br/>
How to seek, detect, be notified, analyze logs, understand and react to the <a href="https://infosec.press/csantosb/on-testing" rel="nofollow">different possible kind of issues</a> one may encounter in a digital design is a vast topic of research, well beyond the scope of this modest post. But there are a couple of things we may state about here, though: automatizing issue detection is the way to go. <a href="https://en.wikipedia.org/wiki/Continuous_integration" rel="nofollow">Continuous integration</a> (<a href="/csantosb/tag:ci" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">ci</span></a>) testing is a practice to adopt in <a href="/csantosb/tag:modernhw" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">modernhw</span></a> as a way to ensure that our design complies with its constraints. Let’s see this in more detail.  <br/></p>

<h1 id="git">git</h1>

<p>We said <a href="/csantosb/tag:git" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">git</span></a>, then, as mandatory when <a href="https://infosec.press/csantosb/on-dependencies" rel="nofollow">tracking changes</a> (in documentation, project development, taking notes, etc.). Meaningful changes imply new commits (and good <a href="https://www.freecodecamp.org/news/how-to-write-better-git-commit-messages/" rel="nofollow">commit messages</a>, for what it takes), but this comes along with a risk of introducing issues. Some kind of mechanism is necessary to automatize the execution of a checkout list to be run per new commit. The list is project aware, for sure, but may also be different following the git branch, and even the kind of commit (merges are to be considered differently to regular commits in topic branches, for example). We need to consider what an issue exactly is, and then you’ll need to adopt a different perspective on kinds of checkout lists. <br/></p>

<h1 id="verification">verification</h1>

<p>First (ideally), one starts with clear specifications about the goals of current development effort (in practice this never happens in research, and if you ever have it, they’ll evolve with time). These specifications (you’ll figure out where to find them somehow) will define the tests to run. For example, if you need to implement in firmware a deep neural network, you’ll probably have access to a test data set to verify the outcomes are correct. You may tune, improve or even completely change the architecture of your network, at the very end, you’ll <a href="https://infosec.press/csantosb/on-testing#osvvm" rel="nofollow">have to verify your design</a> with help of the test data set. Additionally, you may define more sophisticated tests: consumption, area, resources, etc. These all fall into the category of <strong>verification testing</strong>. <br/></p>

<h1 id="unit-tests">unit tests</h1>

<p>Secondly, you’ll be running <a href="https://infosec.press/csantosb/on-testing#vunit" rel="nofollow">unit tests</a> during your whole design cycle (and they’ll evolve along with it), and target tests (the one we mentioned just before). Does this addition perform correctly ? What if we stress a module with random inputs ? Are we going through all code in a given design unit ? Do we cover all values of some input/output signal in this important module ? These are all <strong>unit testing</strong> checkouts, and they’ll help us to detect issues in an early stage of design. <br/></p>

<h1 id="codesign">codesign</h1>

<p><a href="https://infosec.press/csantosb/on-testing#cocotb" rel="nofollow">Codesign</a> falls somewhere in between the two previous: as a testing methodology, it includes concepts of verification and unit testing (and can be combined with them). It is way more ambitious and complex, but also more powerful. No matter your testing strategy, the point here is that you’ll be running these tests (fully or partially) automatically at the several different stages of your development cycle. If they fail, you’ll have to be warned. <br/></p>

<h1 id="guix">guix</h1>

<p><img src="https://git.sr.ht/~csantosb/csbwiki/blob/master/pics/guix.png" alt="img"> <br/>
<a href="https://infosec.press/csantosb/use-guix" rel="nofollow">Guix</a>, as a package manager, provides all necessary software to deploy our tests (and can be <a href="https://infosec.press/csantosb/guix-channels" rel="nofollow">extended</a> with additional tooling). It also includes <a href="https://infosec.press/csantosb/guix-crash-course" rel="nofollow">all that&#39;s necessary</a> to create a running environment where we will execute our tests. Most importantly, <a href="/csantosb/tag:guix" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">guix</span></a> does so in a <a href="/csantosb/tag:deterministic" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">deterministic</span></a> and <a href="/csantosb/tag:reproductible" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">reproductible</span></a> way: we will be able to reproduce our tests in the future under exactly the same conditions. <a href="https://infosec.press/csantosb/guix-crash-course#shell-containers" rel="nofollow">Shell containers</a>, <a href="https://infosec.press/csantosb/guix-crash-course#profiles-and-generations" rel="nofollow">profiles</a> and the <a href="https://infosec.press/csantosb/guix-crash-course#time-machine" rel="nofollow">time machine mechanism</a> allow the degree of <a href="/csantosb/tag:reproducibility" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">reproducibility</span></a> we need here. All it takes is <a href="https://infosec.press/csantosb/guix-crash-course#manifest-channels" rel="nofollow">a couple of text files</a>. <br/></p>

<hr>

<p>Most usually, we will focus on two strategies to seek for issues: local, and remote. Local strategies are greatly based on <a href="https://git-scm.com/book/ms/v2/Customizing-Git-Git-Hooks" rel="nofollow">git hooks</a>, and will be topic of another post. <a href="https://infosec.press/csantosb/tag:ciseries" rel="nofollow">Let’s see now in practice</a> what can be done with help of remote tools, based on <a href="/csantosb/tag:ci" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">ci</span></a>, understood as a methodology consisting on automatically executing a set of tests procedures on a digital design. <br/>
<a href="/csantosb/tag:ciseries" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">ciseries</span></a> <br/></p>
]]></content:encoded>
      <guid>https://infosec.press/csantosb/ci-intro</guid>
      <pubDate>Sun, 08 Dec 2024 21:19:43 +0000</pubDate>
    </item>
  </channel>
</rss>