Wróć do bloga
Case Study

RepoGuard – projekt naszego kursanta

W kodzie zostają rozwiązania, które miały być tylko tymczasowe – i nadal działają, mimo że termin dawno minął. RepoGuard szuka takich miejsc w projektach .NET: TODO z datami, wygasające certyfikaty, przestarzałe API, zaniedbane pakiety NuGet – i rozpoznaje je przez analizę składni Roslyna, nie przez grep.

7 min czytania
case study, .NET, C#, Roslyn, GitHub Actions, dług techniczny

W kodzie często zostają rozwiązania, które miały obowiązywać tylko do jakiegoś terminu:

csharp
// 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:

csharp
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

InspektorCo znajdujeWymaga sieci
Datowane komentarzeTODO, 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 kodzienp. new DateTime(2026, 11, 1) – daty mogące wpłynąć na późniejsze działanie aplikacji
Feature flagiflagi z polem expires/removeAfter i ich aktualnym stanem
Wsparcie .NETTargetFramework i global.json zestawione z datami końca wsparcia platformy
Tokeny i certyfikatyclaim exp w JWT-ach z konfiguracji oraz NotAfter w plikach .pfx, .cer, .pem
Certyfikaty TLSdaty ważności certyfikatów wskazanych domen
Zależności NuGetpakiety 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

1

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.

2

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.

3

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!”.

Struktura repozytorium RepoGuard na GitHubie – foldery workflows, docs, sample, src, testy oraz pliki konfiguracyjne

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.

Chcesz wdrożyć to u siebie?

Praktyczne kursy i wdrożenia AI oraz automatyzacji. Albo zapisz się na newsletter, żeby nie przegapić nowych treści.