Automation Pipeline4 min read

My review monitor was watching 21 of 44 apps

The bot ran on schedule every two hours, exited 0, and reported 'no changes' — all of it true. What was wrong wasn't the verdict but the watch list: 21 hand-typed lines that had stopped halfway through the account.

#monitoring#automation#reality-check#gotchas
Left: a hand-typed list of 21 apps inside the monitor with an exit 0 log. Right: the 44 apps actually on the account, 23 of them watched by nobody
The green light was honest. It just covered half the fleet.

Where does your monitoring bot read its watch list from — the code, or the source of truth?

I have a bot that watches App Store review status. Every two hours it pulls each app's pending versions, in-app events, and custom product pages, diffs them against the previous snapshot, fires a notification on any state change, and appends a line to that day's log. It had been running quietly for months.

Yesterday, while wiring up a new app release — landing page, directory, sitemap, manifest, one after another — I opened the bot's source. And counted the list.

APPS = [
    ("aurnia",    "6764247734"), ("biasly",    "6762536099"),
    ...  # 21 hand-typed lines
]

The account has 44 apps.

Twenty-three of them were watched by nobody

Pulling the full list from the API and diffing it against the code turned up 23 missing apps. A GPS territory game, a naming app, a hanja study app, a tinnitus tracker, a word-chain game… and the app I had submitted for review the day before. Approved or rejected, I would not have been notified.

The important part: the bot never lied.

  • It ran exactly on schedule, every two hours.
  • Its exit code was always 0.
  • It printed "no changes," and that was true — for 21 apps.

Exit 0 wasn't the liar. The question was just narrow. I once wrote about a dashboard that was all green with zero outcomes; back then the metrics measured the wrong thing. This time they measured too little. That failure is quieter, because nothing on screen goes blank.

What would you do?

Type the remaining 23 lines, or delete the 21?

I deleted them. Adding one more line is the moment you guarantee the same thing happens with the next release. As long as the list is maintained by hand, the list will fall behind. The problem wasn't 21 — it was hardcoding.

Deleting the list, reading the source

Four changes:

1. Read the list from the API. One GET /v1/apps returns every app on the account. New apps now need no code edit at all.

2. Preserve the existing keys. Logs and the state file refer to apps by short keys like aurnia and zone2. Applying the new key rule (last segment of the bundle ID) to everything would have made all 21 apps look brand new and blown up the notification feed. So I kept an ID→key map for the existing 21 and generated keys automatically for the rest.

3. Diff over the union of both snapshots, not the static list. The old code looped for key in APPS. If a key wasn't in the list, its data was never compared even when present. Now it walks the union of the previous and current snapshot keys.

4. Prime the state file quietly. Left to the next run, every version and event for the 23 newly watched apps would arrive as "newly discovered." A few hundred notification lines bury the next real signal all by themselves. So I wrote the new apps' current state into the snapshot first and let real changes start from the following poll.

I found the same disease again the same day

While fixing that bot I was also editing the public app directory page. The page said "40 apps." There were 41 cards.

Same cause. Weeks earlier I had dropped an app onto the top of the list as a "NEW" badge row and never updated the numbers below it. The per-category counts were off by one too. Numbers maintained by a person go wrong when the person is busy. So the counts are now computed from the rows.

Three things to check

  1. Is your watch list a constant in code, or a query against the source? If it's a constant, run git log on it and see when an entry was last added.
  2. Do you have a single line comparing the number watched with the number that exists? If those two numbers never appear together, nobody notices when they diverge.
  3. Do you have a way to widen coverage without a notification flood? Without it, the noise of widening once will stop you from widening again.

The honest part

The bot behaved exactly as designed. The bug wasn't in the code — it was in my wrist: the promise to add one line here on every release, broken 23 times. Wherever automation still asks for human diligence, that spot eventually becomes the failure point.

Count what your monitor watches right now. Then query the source for the real count. If the two numbers differ, that's today's bug.

Related