aboutsummaryrefslogtreecommitdiff
path: root/src/content/tils/2020/11
diff options
context:
space:
mode:
Diffstat (limited to 'src/content/tils/2020/11')
-rw-r--r--src/content/tils/2020/11/08/find-broken-symlink.adoc36
-rw-r--r--src/content/tils/2020/11/12/diy-nix-bash-ci.adoc74
-rw-r--r--src/content/tils/2020/11/12/git-bisect-automation.adoc35
-rw-r--r--src/content/tils/2020/11/12/useful-bashvars.adoc72
-rw-r--r--src/content/tils/2020/11/14/gpodder-media.adoc33
-rw-r--r--src/content/tils/2020/11/30/git-notes-ci.adoc122
6 files changed, 372 insertions, 0 deletions
diff --git a/src/content/tils/2020/11/08/find-broken-symlink.adoc b/src/content/tils/2020/11/08/find-broken-symlink.adoc
new file mode 100644
index 0000000..bc97fc6
--- /dev/null
+++ b/src/content/tils/2020/11/08/find-broken-symlink.adoc
@@ -0,0 +1,36 @@
+---
+
+title: Find broken symlinks with "find"
+
+date: 2020-11-08
+
+layout: post
+
+lang: en
+
+ref: find-broken-symlinks-with-find
+
+eu_categories: shell
+
+---
+
+The `find` command knows how to show broken symlinks:
+
+```shell
+find . -xtype l
+```
+
+This was useful to me when combined with [Git Annex][git-annex]. Its
+[`wanted`][git-annex-wanted] option allows you to have a "sparse" checkout of
+the content, and save space by not having to copy every annexed file locally:
+
+```shell
+git annex wanted . 'exclude=Music/* and exclude=Videos/*'
+```
+
+You can `find` any broken symlinks outside those directories by querying with
+Git Annex itself, but `find . -xtype l` works on other places too, where broken
+symlinks might be a problem.
+
+[git-annex]: https://git-annex.branchable.com/
+[git-annex-wanted]: https://git-annex.branchable.com/git-annex-wanted/
diff --git a/src/content/tils/2020/11/12/diy-nix-bash-ci.adoc b/src/content/tils/2020/11/12/diy-nix-bash-ci.adoc
new file mode 100644
index 0000000..3336482
--- /dev/null
+++ b/src/content/tils/2020/11/12/diy-nix-bash-ci.adoc
@@ -0,0 +1,74 @@
+---
+
+title: DIY bare bones CI server with Bash and Nix
+
+date: 2020-11-12 3
+
+layout: post
+
+lang: en
+
+ref: diy-bare-bones-ci-server-with-bash-and-nix
+
+eu_categories: ci
+
+---
+
+With a server with Nix installed (no need for NixOS), you can leverage its build
+isolation for running CI jobs by adding a [post-receive][post-receive] Git hook
+to the server.
+
+In most of my project I like to keep a `test` attribute which runs the test with
+`nix-build -A test`. This way, a post-receive hook could look like:
+
+```shell
+#!/usr/bin/env bash
+set -Eeuo pipefail
+set -x
+
+LOGS_DIR="/data/static/ci-logs/libedn"
+mkdir -p "$LOGS_DIR"
+LOGFILE="${LOGS_DIR}/$(date -Is)-$(git rev-parse master).log"
+exec &> >(tee -a "${LOGFILE}")
+
+unset GIT_DIR
+CLONE="$(mktemp -d)"
+git clone . "$CLONE"
+pushd "$CLONE"
+
+finish() {
+ printf "\n\n>>> exit status was %s\n" "$?"
+}
+trap finish EXIT
+
+nix-build -A test
+```
+
+We initially (lines #5 to #8) create a log file, named after *when* the run is
+running and for *which* commit it is running for. The `exec` and `tee` combo
+allows the output of the script to go both to `stdout` *and* the log file. This
+makes the logs output show up when you do a `git push`.
+
+Lines #10 to #13 create a fresh clone of the repository and line #20 runs the
+test command.
+
+After using a similar post-receive hook for a while, I now even generate a
+simple HTML file to make the logs available ([example project][ci-logs])
+through the browser.
+
+[post-receive]: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks
+[ci-logs]: https://euandreh.xyz/remembering/ci.html
+
+## Upsides
+
+No vendor lock-in, as all you need is a server with Nix installed.
+
+And if you pin the Nixpkgs version you're using, this very simple setup yields
+extremely sandboxed runs on a very hermetic environment.
+
+## Downsides
+
+Besides the many missing shiny features of this very simplistic CI, `nix-build`
+can be very resource intensive. Specifically, it consumes too much memory. So if
+it has to download too many things, or the build closure gets too big, the
+server might very well run out of memory.
diff --git a/src/content/tils/2020/11/12/git-bisect-automation.adoc b/src/content/tils/2020/11/12/git-bisect-automation.adoc
new file mode 100644
index 0000000..9c34b2a
--- /dev/null
+++ b/src/content/tils/2020/11/12/git-bisect-automation.adoc
@@ -0,0 +1,35 @@
+---
+
+title: Git bisect automation
+
+date: 2020-11-12 2
+
+layout: post
+
+lang: en
+
+ref: git-bisect-automation
+
+eu_categories: git
+
+---
+
+It is good to have an standardized way to run builds and tests on the repository
+of a project, so that you can find when a bug was introduced by using
+`git bisect run`.
+
+I've already been in the situation when a bug was introduced and I didn't know
+how it even was occurring, and running Git bisect over hundreds of commits to
+pinpoint the failing commit was very empowering:
+
+```
+$ GOOD_COMMIT_SHA=e1fd0a817d192c5a5df72dd7422e36558fa78e46
+$ git bisect start HEAD $GOOD_COMMIT_SHA
+$ git bisect run sn -c './build.sh && ./run-failing-case.sh'
+```
+
+Git will than do a binary search between the commits, and run the commands you
+provide it with to find the failing commit.
+
+Instead of being afraid of doing a bisect, you should instead leverage it, and
+make Git help you dig through the history of the repository to find the bad code.
diff --git a/src/content/tils/2020/11/12/useful-bashvars.adoc b/src/content/tils/2020/11/12/useful-bashvars.adoc
new file mode 100644
index 0000000..33a072e
--- /dev/null
+++ b/src/content/tils/2020/11/12/useful-bashvars.adoc
@@ -0,0 +1,72 @@
+---
+
+title: Useful Bash variables
+
+date: 2020-11-12 1
+
+layout: post
+
+lang: en
+
+ref: useful-bash-variables
+
+eu_categories: shell
+
+---
+
+[GNU Bash][gnu-bash] has a few two letter variables that may be useful when
+typing on the terminal.
+
+[gnu-bash]: https://www.gnu.org/software/bash/
+
+## `!!`: the text of the last command
+
+The [`!!` variable][previous-command] refers to the previous command, and I find
+useful when following chains for symlinks:
+
+[previous-command]: https://www.gnu.org/software/bash/manual/bash.html#Event-Designators
+
+```shell
+$ which git
+/run/current-system/sw/bin/git
+$ readlink $(!!)
+readlink $(which git)
+/nix/store/5bgr1xpm4m0r72h9049jbbhagxdyrnyb-git-2.28.0/bin/git
+```
+
+It is also useful when you forget to prefix `sudo` to a command that requires
+it:
+
+```shell
+$ requires-sudo.sh
+requires-sudo.sh: Permission denied
+$ sudo !!
+sudo ./requires-sudo.sh
+# all good
+```
+
+Bash prints the command expansion before executing it, so it is better for you
+to follow along what it is doing.
+
+## `$_`: most recent parameter
+
+The [`$_` variable][recent-parameter] will give you the most recent parameter
+you provided to a previous argument, which can save you typing sometimes:
+
+```shell
+# instead of...
+$ mkdir -p a/b/c/d/
+$ cd a/b/c/d/
+
+# ...you can:
+$ mkdir -p a/b/c/d/
+$ cd $_
+```
+
+[recent-parameter]: https://www.gnu.org/software/bash/manual/bash.html#Special-Parameters
+
+## Conclusion
+
+I wouldn't use those in a script, as it would make the script terser to read, I
+find those useful shortcut that are handy when writing at the interactive
+terminal.
diff --git a/src/content/tils/2020/11/14/gpodder-media.adoc b/src/content/tils/2020/11/14/gpodder-media.adoc
new file mode 100644
index 0000000..a74b225
--- /dev/null
+++ b/src/content/tils/2020/11/14/gpodder-media.adoc
@@ -0,0 +1,33 @@
+---
+
+title: gPodder as a media subscription manager
+
+date: 2020-11-14
+
+layout: post
+
+lang: en
+
+ref: gpodder-as-a-media-subscription-manager
+
+---
+
+As we [re-discover][rss] the value of Atom/RSS feeds, most useful feed clients I
+know of don't support media, specifically audio and video.
+
+[gPodder][gpodder] does.
+
+It is mostly know as a desktop podcatcher. But the thing about podcasts is that
+the feed is provided through an RSS/Atom feed. So you can just use gPodder as
+your media feed client, where you have control of what you look at.
+
+I audio and video providers I know of offer an RSS/Atom view of their content,
+so you can, say, treat any YouTube channel like a feed on its own.
+
+gPodder will then managed your feeds, watched/unwatched, queue downloads, etc.
+
+Being obvious now, it was a big finding for me. If it got you interested, I
+recommend you giving gPodder a try.
+
+[rss]: https://www.charlieharrington.com/unexpected-useless-and-urgent
+[gpodder]: https://gpodder.github.io/
diff --git a/src/content/tils/2020/11/30/git-notes-ci.adoc b/src/content/tils/2020/11/30/git-notes-ci.adoc
new file mode 100644
index 0000000..f8dd063
--- /dev/null
+++ b/src/content/tils/2020/11/30/git-notes-ci.adoc
@@ -0,0 +1,122 @@
+---
+
+title: Storing CI data on Git notes
+
+date: 2020-11-30
+
+layout: post
+
+lang: en
+
+ref: storing-ci-data-on-git-notes
+
+eu_categories: git,ci
+
+---
+
+Extending the bare bones CI server I've [talked about before][previous-article],
+divoplade on Freenode suggested storing CI artifacts on [Git notes][git-notes],
+such as tarballs, binaries, logs, *etc*.
+
+I've written a small script that will put log files and CI job data on Git notes,
+and make it visible on the porcelain log. It is a simple extension of the
+previous article:
+
+```shell
+#!/usr/bin/env bash
+set -Eeuo pipefail
+set -x
+
+PREFIX='/srv/ci/vps'
+mkdir -p "$PREFIX"
+read -r _ SHA _ # oldrev newrev refname
+FILENAME="$(date -Is)-$SHA.log"
+LOGFILE="$PREFIX/$FILENAME"
+exec &> >(tee -a "$LOGFILE")
+
+echo "Starting CI job at: $(date -Is)"
+
+finish() {
+ STATUS="$?"
+ printf "\n\n>>> exit status was %s\n" "$STATUS"
+ echo "Finishing CI job at: $(date -Is)"
+ popd
+ NOTE=$(cat <<EOF
+See CI logs with:
+ git notes --ref=refs/notes/ci-logs show $SHA
+ git notes --ref=refs/notes/ci-data show $SHA
+EOF
+)
+ git notes --ref=refs/notes/ci-data add -f -m "$STATUS $FILENAME"
+ git notes --ref=refs/notes/ci-logs add -f -F "$LOGFILE"
+ git notes add -f -m "$NOTE"
+ printf "\n\n>>> CI logs added as Git note."
+}
+trap finish EXIT
+
+unset GIT_DIR
+CLONE="$(mktemp -d)"
+git clone . "$CLONE"
+pushd "$CLONE"
+git config --global user.email git@euandre.org
+git config --global user.name 'EuAndreh CI'
+
+./container make check site
+./container make publish
+```
+
+The important part is in the `finish()` function:
+- #25 stores the exit status and the generated filename separated by spaces;
+- #26 adds the log file in a note using the `refs/notes/ci-logs` ref;
+- #27 it adds a note to the commit saying how to see the logs.
+
+A commit now has an attached note, and shows it whenever you look at it:
+
+```diff
+$ git show 87c57133abd8be5d7cc46afbf107f59b26066575
+commit 87c57133abd8be5d7cc46afbf107f59b26066575
+Author: EuAndreh <eu@euandre.org>
+Date: Wed Feb 24 21:58:28 2021 -0300
+
+ vps/machines.scm: Change path to cronjob files
+
+Notes:
+ See CI logs with:
+ git notes --ref=refs/notes/ci-logs show 87c57133abd8be5d7cc46afbf107f59b26066575
+ git notes --ref=refs/notes/ci-data show 87c57133abd8be5d7cc46afbf107f59b26066575
+
+diff --git a/servers/vps/machines.scm b/servers/vps/machines.scm
+index d1830ca..a4ccde7 100644
+--- a/servers/vps/machines.scm
++++ b/servers/vps/machines.scm
+@@ -262,8 +262,8 @@ pki " mail-domain " key \"" (tls-priv-for mail-domain) "\""))
+ (service mcron-service-type
+ (mcron-configuration
+ (jobs
+- (list #~(job "30 1 * * 1" "guix gc -d")
+- #~(job "30 0 * * *" "/var/lib/euandreh/backup.sh")))))
++ (list #~(job "30 1 * * 1" "/opt/bin/gc.sh")
++ #~(job "30 0 * * *" "/opt/bin/backup.sh")))))
+ (service dhcp-client-service-type)
+ #;
+ (service opensmtpd-service-type
+```
+
+Other tools such as [cgit][cgit] will also show notes on the web interface:
+<https://euandre.org/git/servers/commit?id=87c57133abd8be5d7cc46afbf107f59b26066575>.
+
+You can go even further: since cgit can serve raw blob directly, you can even
+serve such artifacts (log files, release artifacts, binaries) from cgit itself:
+
+```shell
+$ SHA="$(git notes --ref=refs/notes/ci-logs list 87c57133abd8be5d7cc46afbf107f59b26066575)"
+$ echo "https://euandre.org/git/servers/blob?id=$SHA"
+https://euandre.org/git/servers/blob?id=1707a97bae24e3864fe7943f8dda6d01c294fb5c
+```
+
+And like that you'll have cgit serving the artifacts for you:
+<https://euandre.org/git/servers/blob?id=1707a97bae24e3864fe7943f8dda6d01c294fb5c>.
+
+[previous-article]: {% link _tils/2020-11-12-diy-bare-bones-ci-server-with-bash-and-nix.md %}
+[git-notes]: https://git-scm.com/docs/git-notes
+[cgit]: https://git.zx2c4.com/cgit/