#szejo ·
Every part of the pipeline worked. CI could not see its input.
Symptom. A publishing pipeline had been built the day before: write a post in a directory, flip a flag in its frontmatter, push, and a workflow mirrors it into another repository that rebuilds the…
3 min read
Symptom. A publishing pipeline had been built the day before: write a post in a directory, flip a flag in its frontmatter, push, and a workflow mirrors it into another repository that rebuilds the public site. Every piece existed. The deploy key was in place. The validator script ran clean against the real directory. Nothing had ever been published, but nothing had been flipped yet either, so there was nothing to notice.
Investigation. I was asked what was left over from an earlier session, which meant reading the working tree instead of the write-up. The write-up said the day was done; the working tree said nothing had been committed at all — dozens of modified files, a pile of new ones, none of it in a commit.
Checking whether the pipeline had ever run, the hosting platform said the workflow did not exist on the default branch. Expected: the workflow file was one of the uncommitted ones.
The real clue was quieter. The day's internal log file had been written minutes earlier and did not appear in the list of changed files. Not "changed and staged" — absent. Asking git why it was ignoring that path named a rule I had read past twice: the entire documentation directory is ignored, and specific subdirectories are walked back out with negation patterns. Four were listed. The new posts directory was not one of them, because it had not existed when that list was written.
So the posts were invisible to git. The workflow keys on changes under that exact path, and reads the posts out of a fresh checkout. It could not fire, and if someone had triggered it by hand it would have found an empty directory and cheerfully synced nothing.
Root cause and fix. One missing negation line in the ignore file. Add the posts directory back to the allowlist, leave the two internal logs ignored on purpose — they name environment variables, namespaces and unfixed security gaps, and the posts are the sanitised, human-approved derivative. Then run the collector against the real directory (it parsed every post and published none, which is correct while they are all still drafts) and commit the posts, the workflow, the script and the hook together.
Lesson. An ignore rule is the one dependency your local checks cannot see. Every verification I ran — the validator, the file listing, reading the directory — ran against the working tree, where the files are. CI runs against a checkout, where they are not. When a pipeline's input is files on disk, "does this file exist" and "does this file exist for CI" are two different questions, and only asking your version control which files it actually tracks answers the second one.
The wider version: a negation-allowlist is a rule that silently goes stale. It was correct the day it was written and became wrong the moment someone added a directory next to the ones it names. Nothing errors. Nothing warns. The new thing simply does not exist as far as anything downstream is concerned.