When TODOs Start Lying: Building a Flake8 Plugin to Keep Azure DevOps References Honest
Developers love TODO comments. It’s our natural coping mechanism:
“I’ll fix it later.”
Teams hate TODO comments. Because “later” usually means “never”.
And then there’s the third type of TODO — the one that pretends to reference a work item but actually points to nothing. Maybe someone mistyped the number. Maybe the ticket was deleted. Maybe the person was simply too lazy to check. Whatever the reason, your codebase slowly fills with comments that look correct but are completely useless.
I got tired of this.
So I wrote flake8-ado — a tiny Flake8 plugin that forces honesty. If you reference an Azure DevOps work item in your code, it had better exist. Otherwise, your pipeline fails, and the lie stops right there.
Why bother?
Most teams try to enforce consistency socially:
- “Make sure every TODO points to a real work item.”
- “Use the same comment format everywhere.”
- “Don’t leave TODOs without ticket numbers.”
The shelf-life of such rules is about a week. Then the sprint gets busy, review gets rushed, and suddenly your code looks like this:
# TODO: AB#12345 # literally doesn’t exist
# todo: ab12345 # wrong format
# AB#999999 # maybe real, maybe not — who knows
# fix this later # completely uselessThis is where automation shines. Tools don’t forget. Tools don’t get tired. Tools don’t negotiate.
If a TODO points to a fantasy ticket, flake8-ado stops the build. End of story.
What the plugin actually checks
flake8-ado reads your comments and enforces a few simple rules:
- References like
AB#12345must match an existing ADO work item.
The plugin calls Azure DevOps, verifies the ticket, and fails if it doesn’t exist. - You must use a consistent, uppercase format.
ADO: AB#12345is clean and predictable. - TODO comments must include a ticket.
No more# TODO: refactor thiswith zero context.
This is what intentional code smells like.
A quick example
# foo.py
class Foo:
def foo(self) -> None: # TODO: AB#12345
pass # ADO: AB#999999And then:
flake8 \
--ado-access-token=<TOKEN> \
--ado_organization_url=https://dev.azure.com/<ORG>If something’s wrong, you’ll see it immediately:
./foo.py:2:36: ADO001 Missing ADO item
./foo.py:3:12: ADO002 Malformed or invalid ADO referenceYou don’t have to guess anymore. You don’t have to check manually. You don’t have to trust comments blindly.
A tiny plugin… but surprisingly useful
There’s nothing “fancy” in this tool.
No AI. No magic. No over-engineering.
Get Daniel Kusy’s stories in your inbox
Join Medium for free to get updates from this writer.
It’s a ~simple Flake8 plugin~ that solves a persistent, real annoyance: lying TODOs.
It helps teams who:
- use Azure DevOps,
- want consistent references in code,
- expect TODOs to be traceable,
- and prefer pipelines to enforce rules instead of nagging people during review.
If that’s you — you’ll get value immediately.
CI makes it shine
The real power shows up in CI.
Add something like this to GitHub Actions, Azure Pipelines, or any other system:
flake8 \
--ado-access-token="$ADO_PAT" \
--ado_organization_url="https://dev.azure.com/your-org" \
src/Push a commit with an invalid ticket?
Pipeline goes red. You fix it. The codebase stays clean.
Simple feedback loop. Massive long-term payoff.
Why I built it
I’ve seen too many codebases pretending to be connected to work tracking systems while, in reality, half of the references were wrong.
Developers were adding TODOs with invalid IDs. Tickets were renamed or deleted. ADO references drifted out of sync, silently.
I wanted a tool that:
- tells the truth,
- enforces consistency,
- fixes the problem automatically,
- and doesn’t require convincing anyone of anything.
So I built one.
Try it
Repo:
https://github.com/DanielKusyDev/flake8-ado
PyPI:
https://pypi.org/project/flake8-ado/
If you use Azure DevOps and Flake8, plug this in.
Your future self (and your reviewers) will thank you.









