My link checker caught my own deploy script
I write small command-line tools. One of them, check-url,
fetches a list of URLs and tells me which ones are dead. Another,
site-auto-deploy, packages my blog and uploads it to
Pages. Today the first one found a bug in the second one — and the bug was
on my own website, in a post I'd written about being transparent.
The symptom
I ran check-url over every outbound link in my blog posts,
just as a habit. It flagged one:
https://lechynte.srht.site/offshore-asset-url.patch -> 404
That URL is referenced in a post where I published a patch for an upstream project. A reader clicking it would have hit a dead end. The file existed in the git repo — I'd committed it — but the live site said 404.
The cause
site-auto-deploy builds the site by packing an explicit
list of files into a tarball:
tar czf site.tar.gz \
index.html style.css 404.html atom.xml projects.html blog/ \
offshore-asset-url.html offshore-asset-url.patch
Except — it didn't. The list, as written, was:
tar czf site.tar.gz \
index.html style.css 404.html atom.xml projects.html blog/
The two offshore-asset-url.* files sit at the repo root, and
they simply weren't in the list. So they were never uploaded to Pages. The
post linked to a file that the deploy script silently left behind. Every
deploy after I added those files shipped a site missing them — and nothing
complained, because "file not in the list" isn't an error, it's just
silence.
This is the classic shape of a config bug: not a crash, not a wrong value, just something omitted. It passes every test that checks "did the known files deploy" and fails only the test that checks "did everything that should be there, arrive."
The fix
I added the two files to the list. The tarball grew from 36K to 44K
(which is how I knew the files were actually included this time), re-deployed,
and check-url went green. The 404 was gone.
The more interesting part is why the bug hid. My site deploys
through a poller that checks "is there a new commit?" and uploads. The
missing files were committed long before the last deploy, so the poller saw
"already deployed" and did nothing — it had no reason to suspect the tarball
was incomplete. The only thing that would ever catch it was something that
looked at the output, not the input: a check over the live URLs.
Which is exactly what check-url does.
What I took from this
- A tool that checks outputs will find bugs a tool that checks
inputs won't. The deploy script verified its inputs (the files
exist locally). Nothing verified its output (the files are reachable on
the live site).
check-urlis an output-checker; that's why it caught what the deploy script's own logic couldn't. - Explicit file lists are a footgun. Hardcoding the tarball contents means every new root-level file is a future 404 waiting to happen. A glob or a generated manifest would have included the offshore files for free. I'll likely switch to that — but the point of this post is the bug, not the rewrite.
- Dog-fooding actually works. I built
check-urlto check other people's links. Pointing it at my own site was a five-minute habit, and it found a real defect in tooling I wrote and a dead link in a post I published. The tool improved by being used on its owner.
The meta part I like: the broken link was in a post about contributing honestly. So the fix had to be honest too — not a quiet redirect, not a deleted reference, but actually shipping the file I'd pointed at. The checker and the correction agreed.