<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>Nameless</title>
 <link href="http://blog.mandre.org/atom.xml" rel="self"/>
 <link href="http://blog.mandre.org/"/>
 <updated>2026-09-08T14:30:49+00:00</updated>
 <id>http://blog.mandre.org</id>
 <author>
   <name>Martin André</name>
   <email></email>
 </author>

 
 <entry>
   <title>GitOps for the Free Cloud: Bridging Kubernetes and OpenStack with ORC</title>
   <link href="http://blog.mandre.org/2026/06/18/gitops_for_the_free_cloud_bridging_kubernetes_and_openstack_with_orc.html"/>
   <updated>2026-06-18T00:00:00+00:00</updated>
   <id>http://blog.mandre.org/2026/06/18/gitops_for_the_free_cloud_bridging_kubernetes_and_openstack_with_orc</id>
   <content type="html">&lt;p&gt;Following up on the &lt;a href=&quot;/2025/10/18/manage_your_openstack_resources_from_kubernetes_with_orc.html&quot;&gt;ORC intro&lt;/a&gt; from last year’s OpenInfra Summit, I &lt;a href=&quot;https://pretalx.devconf.info/devconf-cz-2026/talk/CLHCXW/&quot;&gt;presented at DevConf.cz&lt;/a&gt; how &lt;a href=&quot;https://k-orc.cloud&quot;&gt;ORC&lt;/a&gt; brings true GitOps to OpenStack infrastructure management. Since ORC exposes OpenStack resources as Kubernetes objects, standard GitOps tools like Argo CD or Flux can manage them like any other.&lt;/p&gt;

&lt;center&gt;
  &lt;iframe src=&quot;https://drive.google.com/file/d/1wr3T-zvtGBirbMzcKUoz1ApADmbGxNjb/preview&quot; width=&quot;800&quot; height=&quot;450&quot;&gt;&lt;/iframe&gt;
&lt;/center&gt;

&lt;p&gt;Also check out the &lt;a href=&quot;https://www.youtube.com/watch?v=mCYMpRV4yVw&quot;&gt;recorded demo&lt;/a&gt; and its &lt;a href=&quot;https://github.com/dlaw4608/devconf-orc-demo&quot;&gt;companion repository&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Manage your OpenStack resources from Kubernetes with ORC</title>
   <link href="http://blog.mandre.org/2025/10/18/manage_your_openstack_resources_from_kubernetes_with_orc.html"/>
   <updated>2025-10-18T00:00:00+00:00</updated>
   <id>http://blog.mandre.org/2025/10/18/manage_your_openstack_resources_from_kubernetes_with_orc</id>
   <content type="html">&lt;p&gt;Stephen and I introduced the &lt;a href=&quot;https://k-orc.cloud&quot;&gt;OpenStack Resource Controller (ORC)&lt;/a&gt;, a set of kubernetes CRDs and controller to manage OpenStack resources, at the &lt;a href=&quot;https://summit2025.openinfra.org/&quot;&gt;2025 OpenInfra Summit&lt;/a&gt;.&lt;/p&gt;

&lt;center&gt;
  &lt;iframe src=&quot;https://drive.google.com/file/d/1XTogXoSuVvYzMTOxH8pDN9_T4AWMpO3d/preview&quot; width=&quot;800&quot; height=&quot;450&quot;&gt;&lt;/iframe&gt;
&lt;/center&gt;
</content>
 </entry>
 
 <entry>
   <title>Hello Hubtty 👋</title>
   <link href="http://blog.mandre.org/2021/10/10/hello-hubtty.html"/>
   <updated>2021-10-10T00:00:00+00:00</updated>
   <id>http://blog.mandre.org/2021/10/10/hello-hubtty</id>
   <content type="html">&lt;p&gt;Part of my responsibilities at my day job involves reviewing other people’s
code. There can be a fairly large number of Pull Requests in many different
repositories that I need to monitor. In the past, while I was working on
OpenStack, I was &lt;a href=&quot;/2016/09/20/setting-up-gertty-for-effective-code-review.html&quot;&gt;quite fond of
Gertty&lt;/a&gt; to give
me a quick glance of the new PRs and help me spend my time better. I missed
this tool after I changed teams and most of the code reviews happened on Github
rather than Gerrit.&lt;/p&gt;

&lt;p&gt;About a year ago, I decided to scratch my own itch and looked at how hard it
would be to port Gertty to the Github API and workflow. It turned out to not be
so difficult: Gertty is well designed and it’s a joy to work with its source
code. &lt;a href=&quot;https://github.com/hubtty/hubtty/&quot;&gt;Hubtty&lt;/a&gt; was born.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/public/images/hubtty/hubtty-0.1.png&quot;&gt;&lt;img src=&quot;/public/images/hubtty/hubtty-0.1.png&quot; alt=&quot;Hubtty v0.1&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p class=&quot;image-caption&quot;&gt;&lt;em&gt;Meet Hubtty&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;how-hubtty-came-to-be&quot;&gt;How Hubtty came to be&lt;/h2&gt;

&lt;p&gt;OK, so where do I start? How do I port Gertty from Gerrit to Github?  A quick
look at the Github REST API tells me it should be possible to port most of the
Gertty’s features relatively easily. I considered for a minute using a python
library to talk to the Github API but rapidly put this idea aside as it would
mean rewriting a lot of the sync module: Gertty uses the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requests&lt;/code&gt; library to
talk to the Gerrit REST API directly and I figured I could simply reuse the
same call, but with the Gitub API instead as the two APIs are more or less
compatible.&lt;/p&gt;

&lt;p&gt;After experimenting a bit, I was quickly able to retrieve the list of PRs for
each repositories the user had subscribed to. Excited with this early success
I set myself a goal to send the first review from Hubtty before the end of the
year (it was November) which &lt;a href=&quot;https://github.com/hubtty/hubtty/commit/9d5eb59ec7fb0df4e20553a545232bd87236a648&quot;&gt;I barely
did&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;At this time, Hubtty was still relying on an existing authorization token that
you had to create manually from the Github UI or “borrow” from another
application. Next step was to implement the &lt;a href=&quot;https://docs.github.com/en/developers/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps#device-flow&quot;&gt;device
flow&lt;/a&gt;
so that Hubtty could create Authorization tokens on the user’s behalf. This
part was
&lt;a href=&quot;https://github.com/hubtty/hubtty/commit/8ceac425dc05c726941b09906b8fb76e61305058&quot;&gt;straightforward&lt;/a&gt;
but I realized it now forces the organizations to explicitely approve Hubtty
when they have enabled third-party application restrictions otherwise it
wouldn’t be able to submit reviews. This is &lt;a href=&quot;https://github.com/hubtty/hubtty/issues/20&quot;&gt;still an
issue&lt;/a&gt; to this day.&lt;/p&gt;

&lt;p&gt;After I started subscribing to more repositories I ran into issues with the
Github API rate limiting. The issue was rather obvious and quickly fixed.
A less obvious issue gave me a hard time and only manifested when I got back to
using Hubtty after some time – think PTO – where it would only sync part of the
PRs. It was an problem with how I handled the pagination for &lt;em&gt;some&lt;/em&gt; queries,
leading to this nasty synchronization issue.&lt;/p&gt;

&lt;p&gt;Another big part was to port the search syntax to the Github search. As of
today, I’ve implemented the &lt;a href=&quot;https://github.com/hubtty/hubtty/issues/48&quot;&gt;most important search
operators&lt;/a&gt; and left out things we
do not yet synchronize with Hubtty.&lt;/p&gt;

&lt;p&gt;Finally, I’ve also made Hubtty consistently use the Github terminology. For
example, it now uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Repository&lt;/code&gt; over &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Project&lt;/code&gt; (which means something
entirely different for Github), and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pull Request&lt;/code&gt; over &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Change&lt;/code&gt; to list the
most obvious. This was quite painful.&lt;/p&gt;

&lt;p&gt;I used Hubtty as my inbox for PRs for the major part of this year and it was
getting more stable, to the point I’m no longer ashamed of recommending it to
others.&lt;/p&gt;

&lt;h2 id=&quot;what-it-looks-like-now&quot;&gt;What it looks like now&lt;/h2&gt;

&lt;p&gt;On Friday I released the first version of Hubtty, v0.1. It has reached a state
where it has feature parity with Gertty, or close enough, and is also stable
enough to be used by other developers.&lt;/p&gt;

&lt;p&gt;It’s available through the cheese shop, install it with:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pip install hubtty
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Take a look:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/public/images/hubtty/01-Repositories-list.png&quot;&gt;&lt;img src=&quot;/public/images/hubtty/01-Repositories-list.png&quot; alt=&quot;Repositories list&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p class=&quot;image-caption&quot;&gt;&lt;em&gt;List of subscribed repositories&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/public/images/hubtty/02-PRs-list.png&quot;&gt;&lt;img src=&quot;/public/images/hubtty/02-PRs-list.png&quot; alt=&quot;PRs list&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p class=&quot;image-caption&quot;&gt;&lt;em&gt;List of PRs in a subscribed repository&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/public/images/hubtty/03-PR-view.png&quot;&gt;&lt;img src=&quot;/public/images/hubtty/03-PR-view.png&quot; alt=&quot;PR view&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p class=&quot;image-caption&quot;&gt;&lt;em&gt;Opening a PR&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/public/images/hubtty/04-Diff-view.png&quot;&gt;&lt;img src=&quot;/public/images/hubtty/04-Diff-view.png&quot; alt=&quot;Diff view&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p class=&quot;image-caption&quot;&gt;&lt;em&gt;Viewing code changes&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;plans-ahead&quot;&gt;Plans ahead&lt;/h2&gt;

&lt;p&gt;In the coming versions, I’d like to have it integrate better with the Github
features and improve UX. There is a lot to do, among other things:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Markdown rendering&lt;/li&gt;
  &lt;li&gt;Highlight PR with merge conflicts&lt;/li&gt;
  &lt;li&gt;Highlight draft PRs&lt;/li&gt;
  &lt;li&gt;Sync draft reviews&lt;/li&gt;
  &lt;li&gt;Autocompletion for usernames&lt;/li&gt;
  &lt;li&gt;Cherry-pick PRs&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.github.com/en/rest/reference/reactions&quot;&gt;Reactions&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I would also like to have hubtty packaged for the major distros. This should be
relatively straightforward considering gertty has already done the work for us.&lt;/p&gt;

&lt;p&gt;I hope it’s going to be as useful to you as it is to me.&lt;/p&gt;

&lt;p&gt;Test it, give feedback, and report issues and feature requests on the &lt;a href=&quot;https://github.com/hubtty/hubtty/issues/&quot;&gt;Github
project page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy hacking!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Flashing Qualcomm-powered Android device from Linux</title>
   <link href="http://blog.mandre.org/2020/09/27/flashing-qualcomm-powered-android-device-from-linux.html"/>
   <updated>2020-09-27T00:00:00+00:00</updated>
   <id>http://blog.mandre.org/2020/09/27/flashing-qualcomm-powered-android-device-from-linux</id>
   <content type="html">&lt;p&gt;Today I got fed up with the stock Android ROM – and the lack of security
updates – that came with my tablet and decided to switch to a &lt;a href=&quot;https://lineageos.org/&quot;&gt;better
alternative&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The instruction for my device said to use
&lt;a href=&quot;https://androidmtk.com/use-qualcomm-flash-image-loader-qfil&quot;&gt;QFIL&lt;/a&gt; to flash
it. However, this is a Windows program and none of my computers run Windows.
The instruction had a few steps with the word &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;important&lt;/code&gt; written in red
&lt;strong&gt;bold&lt;/strong&gt; UPPERCASE, probably as a mean to discourage you experimenting and risk
bricking your device. The forum thread wasn’t also very helpful to provide
instruction for Linux.&lt;/p&gt;

&lt;p&gt;A quick Internet search later, I was on the
&lt;a href=&quot;https://www.96boards.org/documentation/consumer/guides/qdl.md.html&quot;&gt;qdl&lt;/a&gt; page
where the tool description says:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;As open source tool (for Linux) that implements the Qualcomm Sahara and
Firehose protocols has been developed by Linaro, and can be used for program
(or unbrick) MSM based devices, such as Dragonboard 410c or Dragonboard 820c.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This seems like it! However, no mention of QPST or QFIL, the two tools I read
about earlier. I decided to trust the nice folks at Linaro and indeed, this was
exactly the tool that I needed.&lt;/p&gt;

&lt;p&gt;As of today, there are no distribution packages available so we’ll have to
build from source:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone https://git.linaro.org/landing-teams/working/qualcomm/qdl.git
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;qdl
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;libxml2-devel libudev-devel
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When in EDL mode, the device identifies itself as a Qualcomm modem and we need
to turn off &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ModemManager&lt;/code&gt; to prevent it from interfering:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo systemctl stop ModemManager
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From there, I would change to directory where I unzipped the
&lt;a href=&quot;https://twrp.me/&quot;&gt;TWRP&lt;/a&gt; archive and run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qdl&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; ./qdl/qdl &lt;span class=&quot;nt&quot;&gt;--debug&lt;/span&gt; prog_emmc_firehose_8953_ddr.mbn rawprogram0.xml patch0.xml
Waiting &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;EDL device
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After getting my device into EDL 9008 mode, in my case connecting it to my
computer while being powered off and holding the volume up button, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qdl&lt;/code&gt;
noticed the device and started flashing it:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;HELLO version: 0x2 compatible: 0x1 max_len: 1024 mode: 0
READ image: 13 offset: 0x0 length: 0x34
READ image: 13 offset: 0x34 length: 0x120
...
READ image: 13 offset: 0x53504 length: 0x720
END OF IMAGE image: 13 status: 0
DONE status: 0
qdl: failed to read: Connection timed out
FIREHOSE WRITE: &amp;lt;?xml version=&quot;1.0&quot;?&amp;gt;
...
[PROGRAM] flashed &quot;recovery&quot; successfully at 15323kB/s
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I could then follow the rest of the instruction and finish rooting my device.&lt;/p&gt;

&lt;p&gt;After installing the custom ROM from TWRP and fixing a bootloop because
I stupidly forgot to install the &lt;a href=&quot;https://opengapps.org/&quot;&gt;gapps&lt;/a&gt;, I got
everything working and am ready to enjoy using my tabled again.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Bringing Kano to non-English speakers</title>
   <link href="http://blog.mandre.org/2019/05/05/bringing-kano-to-non-english-speakers.html"/>
   <updated>2019-05-05T00:00:00+00:00</updated>
   <id>http://blog.mandre.org/2019/05/05/bringing-kano-to-non-english-speakers</id>
   <content type="html">&lt;h2 id=&quot;what-is-kano&quot;&gt;What is Kano?&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://kano.me/&quot;&gt;Kano&lt;/a&gt; is a small educational Linux distribution to teach
computers to kids. Kano is great: if you have kids, definitely check it out.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/public/images/kano-dashboard.png&quot;&gt;&lt;img src=&quot;/public/images/kano-dashboard.png&quot; alt=&quot;Kano dashboard&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It runs on a cheap &lt;a href=&quot;https://www.raspberrypi.org/&quot;&gt;Raspberry Pi&lt;/a&gt;, the system is
&lt;a href=&quot;https://hello.kano.me/downloads/&quot;&gt;free&lt;/a&gt;. It’s perfect. Or almost…  It’s only
available in English or Spanish and the company behind Kano, despite a few
promises in that sense, hasn’t yet made it available to other languages.&lt;/p&gt;

&lt;p&gt;However because Kano is Open Source, meaning you can modify it to your liking,
we do not rely on them to provide us with localized builds to enjoy the distro
in another language. With a few tweaks, you can do it yourself. Here is how.&lt;/p&gt;

&lt;h2 id=&quot;make-the-system-available-in-your-language&quot;&gt;Make the system available in your language&lt;/h2&gt;

&lt;p&gt;Turn on your Kano computer and make sure it has network connectivity. Go to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Advanced&lt;/code&gt; and enable SSH. Then you can connect to it via SSH and change the
language of the system:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo dpkg-reconfigure locales
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Select which locales you want to enable. For instance for French, I’m enabling
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fr_FR.UTF-8&lt;/code&gt;. It’s usually a good idea to always build &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;en_US.UTF-8&lt;/code&gt;.
On the next screen you’ll be able to select which locale will be the default one.&lt;/p&gt;

&lt;p&gt;To make your change take effect, log out and log in again. If you don’t know
what that means, simply restart your Kano computer.&lt;/p&gt;

&lt;p&gt;Now that you’re back in Kano you’ll notice that the interface is… still in
English. What happened? Didn’t we just changed the system locales? Yes we did.
In fact if you open an application such as the file browser or the calculator,
you’ll see it applied your language preference. These applications are
originated from the wider Open Source community and include translation files,
contrary to the Kano developed applications.&lt;/p&gt;

&lt;p&gt;We need to create those files. This is where you can help.&lt;/p&gt;

&lt;h2 id=&quot;translating-kano-applications&quot;&gt;Translating Kano applications&lt;/h2&gt;

&lt;p&gt;Translating software can be fun and doesn’t require any particular technical
knowledge. All the sentences or words from the original software are extracted
into a file that serves as a template for new translation files.&lt;/p&gt;

&lt;p&gt;There are several services that allow translating files online. Transifex,
Pootle, and Zanata are among the most well known.&lt;/p&gt;

&lt;p&gt;I took the liberty to upload the Kano template files to Zanata because it is
free and offers a public instance. So far, I’ve created translation projects for:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://translate.zanata.org/project/view/make-snake/&quot;&gt;Make Snake&lt;/a&gt; - the snake game&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://translate.zanata.org/project/view/terminal-quest/&quot;&gt;Terminal Quest&lt;/a&gt; - teach the use of the terminal&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://translate.zanata.org/project/view/kano-overworld/&quot;&gt;Kano Overworld&lt;/a&gt; - the application behind the Story Mode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For these projects I uploaded the existing translation files I could find on
the Internet and started contributing French translations.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://translate.zanata.org/account/register&quot;&gt;Create yourself an account&lt;/a&gt;,
join the projects, and &lt;a href=&quot;http://docs.zanata.org/en/release/user-guide/translator-guide/&quot;&gt;start
translating&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;apply-the-changes&quot;&gt;Apply the changes&lt;/h2&gt;

&lt;p&gt;This is where it gets more complex. In an ideal world, the translation files
are included with the software and shipped with the next release. In this case
however, we’ll have to upload the files to the Kano computer. This location is
different for each soft.&lt;/p&gt;

&lt;h3 id=&quot;for-make-snake&quot;&gt;For Make Snake&lt;/h3&gt;

&lt;p&gt;Clone the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make-snake&lt;/code&gt; repository:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone git@github.com:KanoComputing/make-snake.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Download the .po file, for example &lt;a href=&quot;https://translate.zanata.org/rest/file/translation/make-snake/3.14.0-0.20171205/fr/po?docId=messages&quot;&gt;for
French&lt;/a&gt;,
and copy it to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;po&lt;/code&gt; directory as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fr.po&lt;/code&gt;. The file name has to match the
language code. Finally run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make&lt;/code&gt; from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;po&lt;/code&gt; directory:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cd po
make
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Copy the resulting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;locale/fr/LC_MESSAGES/make-snake.mo&lt;/code&gt; file to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/share/locale/fr/LC_MESSAGES/make-snake.mo&lt;/code&gt; on the Kano computer.&lt;/p&gt;

&lt;h3 id=&quot;for-terminal-quest&quot;&gt;For Terminal Quest&lt;/h3&gt;

&lt;p&gt;For Terminal Quest, you’ll follow the same process:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone git@github.com:KanoComputing/terminal-quest.git
# Add the translated .po file to the po directory
cd po
make
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then copy the resulting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;terminal-quest.mo&lt;/code&gt; to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/share/locale/YOUR_LOCAL/LC_MESSAGES/&lt;/code&gt; on the Kano computer.&lt;/p&gt;

&lt;h3 id=&quot;for-story-mode&quot;&gt;For Story Mode&lt;/h3&gt;

&lt;p&gt;Kano-overworld is a different beast. It’s a &lt;a href=&quot;https://love2d.org/&quot;&gt;LÖVE&lt;/a&gt;
application built using the lua programming language.
The translation template comes from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kano-overworld-i18n-orig&lt;/code&gt; package, but
I have yet to figure a way to turn the translated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.po&lt;/code&gt; files back into a lua
dict that the application expects. So what I did instead was to copy the
original language resource and edit it in place.&lt;/p&gt;

&lt;p&gt;The “Story Mode” files live in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/share/kano-overworld/build/kanoOverworld.love&lt;/code&gt;. It’s simply a zip
archive.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt-get install zip
mkdir kano-overworld
cd kano-overworld
unzip /usr/share/kano-overworld/build/kanoOverworld.love
cp -r res/locales/en_US/ res/locales/fr_FR/
vi res/locales/fr_FR/lang.lua
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then you can update the resources with:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;zip -9 -r /usr/share/kano-overworld/build/kanoOverworld.love res/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here is how it looks in French:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/public/images/kano-overworld-fr.png&quot;&gt;&lt;img src=&quot;/public/images/kano-overworld-fr.png&quot; alt=&quot;Kano Story Mode in French&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;and-now-what&quot;&gt;And now what?&lt;/h2&gt;

&lt;p&gt;This is only the beginning. I’m hoping that people will jump on board and help
translate the Kano applications in their languages.&lt;/p&gt;

&lt;p&gt;I’ll certainly push scripts to make this whole experience less hacky and make
is easier to update the distribution with the latest translations.&lt;/p&gt;

&lt;p&gt;It’s a bit unfortunate the Kano developers don’t take i18n too seriously.
I understand they have business imperative and may not want to deal with
support for non-English users but that shouldn’t prevent them from sharing the
tools they use internally and make it easier for the community to provide
translation files.&lt;/p&gt;

&lt;p&gt;Perhaps one day Kano – the company – will integrate these language files in
their projects and finally open Kano – the distribution – to more users?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Toggle Debug for containerized OpenStack services</title>
   <link href="http://blog.mandre.org/2018/03/28/toggle_debug_for_containerized_openstack_services.html"/>
   <updated>2018-03-28T00:00:00+00:00</updated>
   <id>http://blog.mandre.org/2018/03/28/toggle_debug_for_containerized_openstack_services</id>
   <content type="html">&lt;h2 id=&quot;the-general-case-with-kolla-based-containers&quot;&gt;The general case with kolla based containers&lt;/h2&gt;

&lt;p&gt;The configuration file is generally bind-mounted to a staging directory in the
container then copied via the
&lt;a href=&quot;https://github.com/openstack/kolla/blob/master/docker/base/set_configs.py&quot;&gt;set_configs.py&lt;/a&gt;
script to the place as specified in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/lib/kolla/config_files/config.json&lt;/code&gt;
file when the container starts. This means that changes to the config files on
the host will not affect the running containers, ensuring better isolation. You
would have to take a conscious decision and restart the container for the
config change to take effect. This is for example how Kolla-ansible and TripleO
proceed.&lt;/p&gt;

&lt;p&gt;Say we want to bump the verbosity for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nova_scheduler&lt;/code&gt; service. In
a TripleO deployment, we would do:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;crudini &lt;span class=&quot;nt&quot;&gt;--set&lt;/span&gt; /var/lib/config-data/puppet-generated/nova/etc/nova/nova.conf DEFAULT debug &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt; 
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;docker restart nova_scheduler
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we’re getting the DEBUG messages:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo grep &lt;/span&gt;DEBUG /var/log/containers/nova/nova-scheduler.log | &lt;span class=&quot;nb&quot;&gt;wc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;
325
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To revert back, we need to do the inverse change:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;crudini &lt;span class=&quot;nt&quot;&gt;--set&lt;/span&gt; /var/lib/config-data/puppet-generated/nova/etc/nova/nova.conf DEFAULT debug &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt; 
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;docker restart nova_scheduler
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;reload-config-at-runtime&quot;&gt;Reload config at runtime&lt;/h2&gt;

&lt;p&gt;Another – and better – option would be to take advantage of the oslo.config
&lt;a href=&quot;https://docs.openstack.org/oslo.config/latest/reference/mutable.html&quot;&gt;mutable config
mechanism&lt;/a&gt;
that allows changing service settings at runtime. This has the big advantage
that we’re only changing the configuration in the container and we can easily
revert back by restarting the container.&lt;/p&gt;

&lt;p&gt;Toggling the debug option at runtime was accepted as a &lt;a href=&quot;https://governance.openstack.org/tc/goals/rocky/enable-mutable-configuration.html&quot;&gt;community goal for
Rocky&lt;/a&gt;
meaning that all services should support it in the near future. This is already
the case for nova to let’s see how it works in practice to turn debug on with
our previous &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nova_scheduler&lt;/code&gt; example. This time, we’re editing the config file
directly in the container and send it a signal telling it to reload the
configuration:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;docker &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; root nova_scheduler &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-ie&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/^[# ]*debug=false/debug=true/I&apos;&lt;/span&gt; /etc/nova/nova.conf
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;docker &lt;span class=&quot;nb&quot;&gt;kill&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; SIGHUP nova_scheduler
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After we’re done debugging, turning the log severity back to normal is just
a matter of restarting the container:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;docker restart nova_scheduler
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Essential tools of an OpenStack contributor</title>
   <link href="http://blog.mandre.org/2017/12/01/essential_tools_of_an_openstack_contributor.html"/>
   <updated>2017-12-01T00:00:00+00:00</updated>
   <id>http://blog.mandre.org/2017/12/01/essential_tools_of_an_openstack_contributor</id>
   <content type="html">&lt;p&gt;This year again, I had the chance to attend the &lt;a href=&quot;https://openstackdayfrance.fr/&quot;&gt;OpenStack Day
France&lt;/a&gt; one day event in Paris and present
about the tools we use in the OpenStack community to contribute to the project.&lt;/p&gt;

&lt;p&gt;My talk covered the different kinds of contribution and highlighted some of the
lesser known – but essential – tools available, giving tips and tricks learned
from years of practice. I hope both the casual contributor and the more
experienced one can find useful nuggets of information in this presentation.&lt;/p&gt;

&lt;center&gt;
  &lt;iframe src=&quot;https://drive.google.com/file/d/1a3R4C-iVC8i2PaC3ckIB96f80ZT_O-WL/preview&quot; width=&quot;640&quot; height=&quot;403&quot;&gt;&lt;/iframe&gt;
&lt;/center&gt;

&lt;p&gt;This time, all the sessions were recorded and the videos should be available
shortly. Overall, I found this event was very well organized with a nice crowd
of around 400 attendants. Kudos to the &lt;a href=&quot;http://openstack.fr/&quot;&gt;OpenStack-fr&lt;/a&gt;
team for making this second edition a success. See you there next year!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Cleanup local git branches - the Gerrit case</title>
   <link href="http://blog.mandre.org/2017/10/22/cleanup_local_git_branches_gerrit_case.html"/>
   <updated>2017-10-22T00:00:00+00:00</updated>
   <id>http://blog.mandre.org/2017/10/22/cleanup_local_git_branches_gerrit_case</id>
   <content type="html">&lt;p&gt;If you’ve been working with git for long enough you’ve probably noticed the
local branches tend to accumulate. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git branch&lt;/code&gt; command provides a handy
option to filter branches where the tip commits also belongs to the current
branch:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git branch --merged
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is great and works fine in the majority of case and is often found in
oneliners to cleanup local branches but this is not enough when working with
workflows where the commits are often rewritten a few times before they
eventually make it in tree, for example the Gerrit workflow we use in
OpenStack. Gerrit uniquely identifies the commit with the
&lt;a href=&quot;https://review.openstack.org/Documentation/user-changeid.html#_description&quot;&gt;Change-Id&lt;/a&gt;,
a small label it inserts in the commit message and we can make advantage of
this to check if a commit has been merged or not and delete the local branch.&lt;/p&gt;

&lt;p&gt;First we need to get the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Change-Id&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Get Change-Id of $commit&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;change_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;git log &lt;span class=&quot;nt&quot;&gt;-n1&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--pretty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;format:%b &lt;span class=&quot;nv&quot;&gt;$commit&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/Change-Id:/ {print $0}&apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Change-Id&lt;/code&gt; we can now verify if it was merged or not in the current
branch:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Check that commit was merged into $current_branch&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;merged_commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;git log &lt;span class=&quot;nt&quot;&gt;--pretty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;format:%h &lt;span class=&quot;nt&quot;&gt;--grep&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$change_id&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;current_branch&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$merged_commit&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# This change is missing from $current_branch&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Great, so now we can find commits that have not yet been merged in the current
branch. But what about the ones that were merged? It is entirely possible
someone pushed a new version of the patch in Gerrit, or maybe I made local
changes to a patch I haven’t yet submitted for review and the change was merged
in the meantime. So if I blindly delete the branch I may lose important local
changes. How can I check the two versions of the patch are the same? The
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;interdiff&lt;/code&gt; tool compares diff files and we can assume they’re the same when
the output is empty:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;interdiff &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;git show &lt;span class=&quot;nv&quot;&gt;$commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;git show &lt;span class=&quot;nv&quot;&gt;$merged_commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 2&amp;gt;&amp;amp;1&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# The patch that was merged differs from what I have in local branch&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Putting it all together:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;prompt_for_missing_commit &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;branch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;current_branch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$3&lt;/span&gt;
    git log &lt;span class=&quot;nt&quot;&gt;--oneline&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$commit&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Commit &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$commit&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; in &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$branch&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; is missing from &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$current_branch&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;. Inspect? [Yn] &quot;&lt;/span&gt; answer
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;answer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~ ^&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;n|no&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
        &lt;/span&gt;git show &lt;span class=&quot;nv&quot;&gt;$commit&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;prompt_for_commit_diff &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;local_commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;merged_commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;local_branch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$3&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;current_branch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$4&lt;/span&gt;
    git log &lt;span class=&quot;nt&quot;&gt;--oneline&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$commit&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Commit &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$local_commit&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; in &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$local_branch&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; and &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$merged_commit&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; in &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$current_branch&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; differ. Inspect? [Yn] &quot;&lt;/span&gt; answer
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;answer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~ ^&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;n|no&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
        &lt;/span&gt;interdiff &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;git show &lt;span class=&quot;nv&quot;&gt;$local_commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;git show &lt;span class=&quot;nv&quot;&gt;$merged_commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; | colordiff
    &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;current_branch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;git symbolic-ref &lt;span class=&quot;nt&quot;&gt;--short&lt;/span&gt; HEAD&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;branch &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;git &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-each-ref&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;%(refname:short)&apos;&lt;/span&gt; refs/heads/&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
    if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$branch&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$current_branch&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
        continue
    fi
    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo
    echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Checking branch &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$branch&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;branch_differs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0
    &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;commit &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;git log &lt;span class=&quot;nt&quot;&gt;--no-merges&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--pretty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;format:&lt;span class=&quot;s2&quot;&gt;&quot;%h&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;current_branch&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;..&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;branch&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
        &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;change_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;git log &lt;span class=&quot;nt&quot;&gt;-n1&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--pretty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;format:%b &lt;span class=&quot;nv&quot;&gt;$commit&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/Change-Id:/ {print $0}&apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$change_id&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
            &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;branch_differs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
            prompt_for_missing_commit &lt;span class=&quot;nv&quot;&gt;$commit&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$branch&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$current_branch&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;continue
        fi
        &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;merged_commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;git log &lt;span class=&quot;nt&quot;&gt;--pretty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;format:%h &lt;span class=&quot;nt&quot;&gt;--grep&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$change_id&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;current_branch&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$merged_commit&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
            &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;branch_differs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
            prompt_for_missing_commit &lt;span class=&quot;nv&quot;&gt;$commit&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$branch&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$current_branch&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;continue
        else&lt;/span&gt;
            &lt;span class=&quot;c&quot;&gt;# Check that the merged patch is similar to what is in local branch&lt;/span&gt;
            &lt;span class=&quot;c&quot;&gt;# NOTE needs interdiff from patchutils and colordiff&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;interdiff &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;git show &lt;span class=&quot;nv&quot;&gt;$commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;git show &lt;span class=&quot;nv&quot;&gt;$merged_commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 2&amp;gt;&amp;amp;1&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
                &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;branch_differs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
                prompt_for_commit_diff &lt;span class=&quot;nv&quot;&gt;$commit&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$merged_commit&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$branch&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$current_branch&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;fi
        fi
    done
    if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$branch_differs&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-eq&lt;/span&gt; 0 &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
        &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$branch&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; fully merged. Delete? [yN] &quot;&lt;/span&gt; answer
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;answer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~ ^&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;y|yes&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
            &lt;/span&gt;git branch &lt;span class=&quot;nt&quot;&gt;-D&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$branch&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;fi
    else
        &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$branch&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; differs from &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$current_branch&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;. Delete anyway? [yN] &quot;&lt;/span&gt; answer
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;answer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~ ^&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;y|yes&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
            &lt;/span&gt;git branch &lt;span class=&quot;nt&quot;&gt;-D&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$branch&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;fi
    fi
done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Challenges in containerizing OpenStack</title>
   <link href="http://blog.mandre.org/2016/12/12/challenges-in-containerizing-openstack.html"/>
   <updated>2016-12-12T00:00:00+00:00</updated>
   <id>http://blog.mandre.org/2016/12/12/challenges-in-containerizing-openstack</id>
   <content type="html">&lt;p&gt;A presentation I made for the first edition of &lt;a href=&quot;https://openstackdayfrance.fr/&quot;&gt;OpenStack Day
France&lt;/a&gt; in Paris end of November that covers
some of the challenges faced by the Kolla project in its effort to containerize
OpenStack:&lt;/p&gt;

&lt;center&gt;
  &lt;iframe src=&quot;https://drive.google.com/file/d/0B4fQIxKt4Sz9b1BVZ1lRdHUtaDg/preview?resourcekey=0-dylFJgpv1GfF2dBu4PxyHg&quot; width=&quot;640&quot; height=&quot;480&quot;&gt;&lt;/iframe&gt;
&lt;/center&gt;
</content>
 </entry>
 
 <entry>
   <title>Setting up Gertty for effective code review</title>
   <link href="http://blog.mandre.org/2016/09/20/setting-up-gertty-for-effective-code-review.html"/>
   <updated>2016-09-20T00:00:00+00:00</updated>
   <id>http://blog.mandre.org/2016/09/20/setting-up-gertty-for-effective-code-review</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://github.com/openstack/gertty/&quot;&gt;Gertty&lt;/a&gt; is a console-based client for
the &lt;a href=&quot;https://www.gerritcodereview.com/&quot;&gt;Gerrit code review tool&lt;/a&gt;. 
Once you start doing a lot of code reviews as part of your daily work,
gertty proves to be an excellent alternative to the Gerrit web interface. For
one, it can work offline so it means it’s possible to review code while on the
move. It also means the interface is more reactive since everything is cached
locally. Plus the fact that it’s a console tool is really appealing to
programmers who spend their life in the terminal.&lt;/p&gt;

&lt;p&gt;However, like all great tools, it needs a bit of configuration it in order to
deliver its full potential. I’m going to document here a few of the settings I’m
using in the context of OpenStack.&lt;/p&gt;

&lt;h2 id=&quot;vim-key-bindings&quot;&gt;Vim key bindings&lt;/h2&gt;

&lt;p&gt;If like me you like using the vim key bindings whenever possible, then you’re
in luck. Gertty ships with a vi keymap and allows you to remap most of the
controls. To enable the vi bindings simply set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keymap: vi&lt;/code&gt; in your
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gertty.yaml&lt;/code&gt; file. However, don’t stop here or you’ll be heading for serious
disappointment. The default vi keymap is rudimentary with only the four
direction keys &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hjkl&lt;/code&gt; and you’ll need to redefine most of the combinations to
feel at home.&lt;/p&gt;

&lt;p&gt;Gertty supports key sequences in the form of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[key1, key2]&lt;/code&gt; so you can easily
emulate a leader key or a command like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:q&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is the configuration I am using for reference:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;keymaps&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;vi&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;cursor-down&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;j&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;down&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;vi&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;cursor-up&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;k&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;up&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;vi&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;cursor-left&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;h&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;left&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;vi&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;cursor-right&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;l&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;right&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;vi&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;cursor-page-up&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ctrl&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;u&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;up&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;vi&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;cursor-page-down&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ctrl&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;d&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;down&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;vi&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;cursor-max-left&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;^&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;home&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ctrl&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;a&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;vi&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;cursor-max-right&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;$&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;end&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ctrl&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;e&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;vi&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;quit&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;:&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;q&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ctrl&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;q&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;vi&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;interactive-search&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;vi&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;toggle-hidden&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;t&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;h&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]]&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;vi&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;toggle-star&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;t&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;*&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]]&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;vi&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;toggle-reviewed&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;t&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;r&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]]&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;vi&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;toggle-list-reviewed&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;t&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;R&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]]&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;vi&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;toggle-subscribed&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;t&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;s&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]]&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;vi&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;toggle-list-subscribed&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;t&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;S&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Right now, the only thing I’m missing are the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;G&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gg&lt;/code&gt; movements to go to
the bottom or top of the panel. They are apparently missing from the underlying
&lt;a href=&quot;http://urwid.org/&quot;&gt;urwid library&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;dashboards&quot;&gt;Dashboards&lt;/h2&gt;

&lt;p&gt;In the spirit of the web interface, gertty also allows you to define your own
&lt;a href=&quot;https://gerrit-review.googlesource.com/Documentation/user-dashboards.html&quot;&gt;dashboards&lt;/a&gt;.
The syntax is a bit different though, and as a consequence the &lt;a href=&quot;http://gerrit-dash-creator.readthedocs.io/en/latest/dashboards/index.html#openstack-gerrit-dashboards&quot;&gt;official
OpenStack
dashboards&lt;/a&gt;
can’t be imported directly and need to be adapted slightly. Unfortunately,
I couldn’t find documentation for gertty’s query interface, so until someone
finds the courage and time to write it down, the
&lt;a href=&quot;https://github.com/openstack/gertty/blob/master/gertty/search/parser.py&quot;&gt;source&lt;/a&gt;
&lt;a href=&quot;https://github.com/openstack/gertty/blob/master/gertty/search/tokenizer.py&quot;&gt;code&lt;/a&gt;
remains your best resource.&lt;/p&gt;

&lt;p&gt;Here is for example what I’m using for the Kolla project:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;dashboards&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;My&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;changes&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;owner:self&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;status:open&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;f2&quot;&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Incoming&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;reviews&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;is:open&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;is:reviewer&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;f3&quot;&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Kolla:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Needs&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;feedback&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;project:^openstack/kolla.*&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;status:open&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;NOT&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;owner:self&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;label:Workflow&amp;gt;=0&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;NOT&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;(label:Code-Review&amp;lt;=-1&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;label:Code-Review&amp;gt;=1)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;age:2d&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;f4&quot;&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Kolla:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Needs&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Approval&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;project:^openstack/kolla.*&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;status:open&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;NOT&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;owner:self&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;label:Workflow&amp;gt;=0&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;(label:Verified&amp;gt;=1,jenkins&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;label:Verified&amp;gt;=1,zuul)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;label:Code-Review=2&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;NOT&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;label:Code-Review&amp;lt;=-1&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;f5&quot;&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Kolla:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;No&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;negative&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;feedback&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;project:^openstack/kolla.*&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;status:open&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;NOT&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;owner:self&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;(label:Verified&amp;gt;=1,jenkins&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;label:Verified&amp;gt;=1,zuul)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;NOT&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;(label:Code-Review&amp;lt;=-1&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;label:Code-Review&amp;gt;=1)&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;f6&quot;&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Kolla:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Backports&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;project:^openstack/kolla.*&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;status:open&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;NOT&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;owner:self&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;branch:stable/mitaka&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;OR&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;branch:stable/liberty&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;f7&quot;&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Kolla:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Disagreement&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;project:^openstack/kolla.*&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;status:open&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;(label:Verified&amp;gt;=1,jenkins&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;label:Verified&amp;gt;=1,zuul)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;label:Code-Review&amp;lt;=-1&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;label:Code-Review&amp;gt;=1&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;f8&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;keyword-replacement&quot;&gt;Keyword replacement&lt;/h2&gt;

&lt;p&gt;The OpenStack Gerrit instance conveniently replaces the &lt;a href=&quot;https://wiki.openstack.org/wiki/GitCommitMessages&quot;&gt;git commit message
tags it understands&lt;/a&gt; with
links to Launchpad issues or blueprints. Gertty offers that feature through
keyword replacements.&lt;/p&gt;

&lt;p&gt;Here is for instance how to mimic that behavior:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;commentlinks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Match external references to bugs on Launchpad&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;(?P&amp;lt;bug_str&amp;gt;(?:[Cc]loses|[Pp]artial|[Rr]elated)-[Bb]ug&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;*:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;*#?(?P&amp;lt;bug_id&amp;gt;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;d+))&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;replacements&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{bug_str}&quot;&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;https://launchpad.net/bugs/{bug_id}&quot;&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Match external references to blueprints on Launchpad&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;(?P&amp;lt;bp_str&amp;gt;(?:[Bb]lueprint|bp)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;+(?P&amp;lt;blueprint&amp;gt;[&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-.]+))&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;replacements&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{bp_str}&quot;&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;https://blueprints.launchpad.net/openstack/?searchtext={blueprint}&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;filter-job-results-by-pipelines&quot;&gt;Filter job results by pipelines&lt;/h2&gt;

&lt;p&gt;That last one &lt;a href=&quot;https://review.openstack.org/#/c/334578/&quot;&gt;hasn’t yet made it&lt;/a&gt; to
gertty. This is somewhat specific to OpenStack gerrit instance and how it works
with Zuul. The above commit lets you filter the job results by pipeline and
displays useful information like the date or the number of rechecks.&lt;/p&gt;

&lt;p&gt;See what gertty looks like with the patch applied:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/public/images/gertty.png&quot;&gt;&lt;img src=&quot;/public/images/gertty.png&quot; alt=&quot;Gertty in action&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 

</feed>
