W kodzie często zostają rozwiązania, które miały obowiązywać tylko do jakiegoś terminu:
// TODO(2025-03-01): usunąć fallback po zakończeniu migracji koszyków
private const bool UzywajStaregoZapisu = true;
Termin mija, a kod dalej działa poprawnie i przechodzi testy – bo ani kompilator, ani standardowe testy nie sprawdzają dat w komentarzach. Ten sam problem dotyczy tymczasowych feature flag, elementów oznaczonych [Obsolete], tokenów i certyfikatów z datą ważności, wersji .NET z kończącym się wsparciem czy pakietów NuGet, które od dawna nikt nie aktualizuje.
Artur zbudował RepoGuard – narzędzie, które takie miejsca znajduje samo, zamiast czekać, aż ktoś natrafi na nie przez przypadek.
„Pomysł jest prosty: w kodzie często pozostają rozwiązania, które miały być tylko tymczasowe albo obowiązywać do określonego momentu. Projekt nadal może działać poprawnie i przechodzić testy, mimo że ustalony termin już dawno minął.”
Co dokładnie sprawdza
- komentarze TODO, FIXME i HACK zawierające daty,
- tymczasowe przełączniki funkcji (feature flagi),
- elementy oznaczone jako przestarzałe (
[Obsolete]), - daty zapisane wprost w kodzie i konfiguracji,
- terminy ważności tokenów i certyfikatów,
- koniec wsparcia używanej wersji .NET,
- pakiety NuGet wymagające uwagi.
Każde znalezisko trafia do jednej z czterech kategorii pilności: 🔴 po terminie, 🟠 wygasa wkrótce, 🟡 termin się zbliża, 🔵 do wiadomości.
Dlaczego Roslyn, a nie grep
Prosty grep po frazie TODO(2020-01-01) złapie ją wszędzie – także tam, gdzie to nie termin, tylko treść zmiennej:
string komunikat = "TODO(2020-01-01): to tylko tekst dla użytkownika";
RepoGuard analizuje drzewo składni Roslyna, więc rozpoznaje, że to literał tekstowy, a nie komentarz z realnym terminem – i pomija go. Ta różnica ma własny test w pakiecie 78 testów jednostkowych, które chodzą offline i deterministycznie.
Analiza jest czysto składniowa – nie wymaga kompilacji ani restore sprawdzanego repozytorium. Dzięki temu RepoGuard przeanalizuje nawet projekt, którego akurat nie da się zbudować.
Osiem inspektorów
| Inspektor | Co znajduje | Wymaga sieci |
|---|---|---|
| Datowane komentarze | TODO, HACK, FIXME z datą – tylko w komentarzach, nie w literałach tekstowych | – |
| Wycofane API | [Obsolete] z terminem lub datą wycofania i liczbą pozostałych użyć w repo | – |
| Daty w kodzie | np. new DateTime(2026, 11, 1) – daty mogące wpłynąć na późniejsze działanie aplikacji | – |
| Feature flagi | flagi z polem expires/removeAfter i ich aktualnym stanem | – |
| Wsparcie .NET | TargetFramework i global.json zestawione z datami końca wsparcia platformy | – |
| Tokeny i certyfikaty | claim exp w JWT-ach z konfiguracji oraz NotAfter w plikach .pfx, .cer, .pem | – |
| Certyfikaty TLS | daty ważności certyfikatów wskazanych domen | ✓ |
| Zależności NuGet | pakiety wycofane, ukryte, z podatnościami albo od dawna niewydawane | ✓ |
Inspektory wymagające dostępu do sieci są domyślnie wyłączone – reszta działa lokalnie, bez łączenia się z niczym na zewnątrz.
Jak to wygląda w praktyce
Na celowo zaniedbanym repozytorium demonstracyjnym RepoGuard znajduje m.in.:
-2116 dni WindowsAzure.Storage – ostatnie wydanie 94 miesiące temu
↳ Polityka repo: pakiet bez wydania przez 24 miesiące traktujemy
jak porzucony.
-561 dni TODO(2025-03-01): usunąć fallback po zakończeniu migracji koszyków
src/Koszyk/KoszykService.cs:10
↳ Zrób to, co obiecuje komentarz, albo świadomie przesuń termin.
Podsumowanie 7 po terminie · 3 wygasa wkrótce · 6 zbliża się · 3 do wiadomości
Do każdego znaleziska RepoGuard dokłada nie tylko lokalizację w kodzie, ale i rekomendację wynikającą z przyjętej polityki repozytorium – np. że pakiet bez wydania od 24 miesięcy uznaje się za porzucony, a [Obsolete] sprząta się 12 miesięcy po wycofaniu, jeśli nikt już z niego nie korzysta.
Automatyzacja, nie tylko raport
Uruchomienie
Co poniedziałek o 6:00 UTC, przy pushu do main, przy pull requeście albo ręcznie – przez workflow_dispatch w GitHub Actions.
Analiza i raport
RepoGuard buduje aplikację, analizuje repozytorium i tworzy raport w Markdown, HTML i JSON, wklejając wersję Markdown wprost do GitHub Step Summary.
Reakcja, jeśli potrzebna
Gdy znajdzie coś po terminie albo wygasające wkrótce – wysyła webhook i zakłada lub aktualizuje GitHub Issue. Jeśli nic nie wymaga uwagi, przebieg kończy się po prostu na zielono.
Raporty trafiają też jako artefakty GitHub Actions przechowywane przez 90 dni. Krok ustalający wynik całego przebiegu wykonuje się jako ostatni, więc raport i powiadomienie powstają nawet wtedy, gdy sama analiza zakończy workflow błędem. RepoGuard nie wymaga jednak GitHub Actions – równie dobrze można go odpalić z cron-a albo Harmonogramu zadań Windows i wysyłać webhook samodzielnie.
Projekt powstał w C#/.NET na konkurs „Strażnik” organizowany z okazji Dnia Programisty 2026 przez StormIT, Helion.pl i inkBOOK Europe LTD, pod hasłem „404? NOT TODAY!”.

Kod źródłowy i demo działania RepoGuard są publicznie dostępne – zobacz repozytorium na GitHubie.
To kolejny z projektów zgłoszonych na konkurs Dzień Programisty 2026. Zobacz pozostałe albo sprawdź, jak zacząć swój.
