by Eduardo Trujillo

Phabulous is a server written in Go capable of receiving event notifications from Phabricator, a suite of developer tools and forward them to a Slack community, while also providing additional functionality through a bot interface.

You can interact with Phabulous over chat messages
You can interact with Phabulous over chat messages

The project started while I was working at Seller Labs and Phabricator was their repository hosting tool. We mainly wanted to have better integration with Slack, just like GitHub and Bitbucket had.

Over time, Seller Labs migrated to GitHub and other tools, so development on Phabulous slowed down a bit since I wasn’t using it on a daily basis any more.

However, this does not mean the project is dead, I’ve quietly been finding some spare time to work on improving Phabulous, and it has received a few contributions through pull requests.

I recently landed a large refactor of the project which should make future contribution and extensions easier. I’ve reorganized how the code is structured to make better use of Go interfaces.

In a perfect world, I would have enough time to write an extensive test suite for the project, but given my limited time, I’ve only been able to cover certain simple part of the project. The transition to interfaces has allowed me to improve the coverage of the project since dependencies can now be easily mocked.

Another side effect that came naturally from this transition was the increased modularity of the code. Want to implement a connector for a different chat protocol? Or do you want to add a new command? Just implement the interfaces.

While still technically in beta, I’m happy to say that Phabulous has reached v3.0.0. With this new release, you can expect the following new features:

  • Experimental support for IRC: The bot is now able to connect and work over IRC networks. Functionality is almost on-par with what is available on Slack.
  • Modules: Commands and functionality are now split into modules. You can enable/disable them in the configuration file, as well as implementing your own modules when forking the project.
  • Improved integration between Slack and Phabricator: Phabricator added a new authentication provider that allows you to sign in with your Slack account. Phabulous makes use of this new integration with a new extension. This extension allows the bot to lookup Slack account IDs over the Conduit API, which means the bot can properly mention users on the chat by using their Slack username rather than their Phabricator username.
  • Summon improvements: The summon command can now expand project members if a project is assigned as a reviewer of a revision. Additionally, the lookup algorithm has been optimized to perform less requests on the Conduit API.
  • Many other small fixes and improvements.

You can get the latest version of the bot by using Docker or by downloading the latest release on GitHub.

by Eduardo Trujillo

If you have a Linux laptop or desktop with a solid-state drive, and happen to have disk encryption enabled through a LUKS/LVM combo, getting TRIM support enabled isn’t a very straightforward process. It has to be enabled on every IO layer.

In their blog post, How to properly activate TRIM for your SSD on Linux: fstrim, lvm and dm-crypt, Carlos Lopez gives a brief introduction on what TRIM is, and explains why it is beneficial to enable it. The article also describes the steps needed to enable this functionality on each IO layer (dm-crypt, LVM, and the filesystem).

I followed most of this guide for one my own systems, and while I followed their advice and avoided enabling the discard flag on the filesystem, I never set up a cron job for running the trim operation periodically. So I found myself manually executing fstrim every now and then by hand.

This quickly became slightly repetitive, so I began looking into setting up the automation part. The guide above had an example setup using cron. However, I never set up a cron daemon on my system. So I wondered if it was possible to achieve the same result using systemd.

After reading some documentation on systemd unit files, I learned that is possible to setup timers for your service units, which effectively achieves the same result as a cron daemon.

Below I’m including a fstrim service and timer. The service mainly specifies which command to run and the timer defines how often it should be executed. Note that the service unit does not have a WantedBy option and its Type is oneshot. This means it won’t be automatically executed, and that it is intended to be a one off command, not a daemon. The timer does have a WantedBy option, which will result on it being started at boot.

I can check the status of the timer by using systemctl list-times and also run the operation on demands by starting the service unit: systemctl start fstrim. The logs are stored on the journal, which can be queried with journalctl -u fstrim.

/etc/systemd/system/fstrim.service

This is the service file. Here you can customize how fstrim is invoked. I use the a and v options, which tell fstrim to automatically run on every drive and print verbose output. Additionally, this assumes fstrim is installed at /sbin/fstrim.

[Unit]
Description=Run fstrim on all drives

[Service]
Type=oneshot
ExecStart=/sbin/fstrim -av
User=root
/etc/systemd/system/fstrim.timer

In this configuration, the fstrim command is executed by root 15 minutes after booting the machine and weekly afterwards.

[Unit] Description=Run fstrim on boot and weekly afterwards

[Timer]
OnBootSec=15min
OnUnitActiveSec=1w 

[Install]
WantedBy=timers.target
by Eduardo Trujillo

On a previous post, I covered how to setup continuous integration for Haskell projects using a combination of Stack, Travis CI, and Docker. But what about documentation?

Sweet auto-generated docs!
Sweet auto-generated docs!

If you already have CI setup for your project with Stack and Travis CI, it is actually pretty easy. In fact, you can make use of GitHub’s Pages feature, which hosts statics sites based on the content of the gh-pages branch to host your documentation for free.

The following is a bash script I’ve been using on a couple of projects on GitHub. It takes care of collecting the documentation and coverage reports generated while building the application, triggered using Stack’s --haddock and --coverage respectively.

#!/bin/bash

# .travis/assemble-docs.sh
#
# Make sure you install the Travis CLI and encrypt a GitHub API token with
# access to the repository: `travis encrypt GH_TOKEN=xxxxxxx --add`.
#
# This script is meant to be run during the `after_success` build step.

# Copy haddocks to a separate directory.
mkdir -p ../gh-pages
cp -R "$(stack path --local-doc-root)" ../gh-pages
cp -R "$(stack path --local-hpc-root)" ../gh-pages
cd ../gh-pages

# Set identity.
git config --global user.email "travis@travis-ci.org"
git config --global user.name "Travis"

# Add branch.
git init
git remote add origin https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git > /dev/null
git checkout -B gh-pages

# Push generated files.
git add .
git commit -m "Haddocks updated" git push origin gh-pages -fq > /dev/null

To do its job, the script relies on some neat tricks/hacks to keep the process as simple as possible:

  • Stack: When using --haddock and --coverage flags, Stack will place documentation and coverage reports on specific paths. You can query these paths using stack path. On the script above, we use special flags so the output of the program is a single line with the requested path. This avoids having to think about or trying to find where the compiler placed the documentation and related files.

  • GitHub API Tokens: Managing SSH keys inside a build job is probably something doable but probably not easy. Thankfully, GitHub allows you to push commits to a repository using just an API token.

  • Travis CI encrypted variables: This allows us to conveniently store the aforementioned token in a secure manner and easily access it as an environment variable while the job runs. We do have to use > /dev/null on a couple of places so the key is not leaked on build logs.

  • Bare Git branch: Given that keeping track of history is not a priority and could break the build process if somebody else pushed to the documentation branch, we simply keep a single commit on the gh-pages branch. One can easily do this by initializing a new repository, committing, and force-pushing into the branch.

If you would like to see a public working example, checkout this repository and its build logs on Travis CI. The resulting documentation is available as a GitHub pages website and coverage reports can be found under /hpc on the site.

…or you can find more in the archives.