feat: add prune subcommand, drop archived/stale entries (#1441)
Deploy to GitHub Pages / build (push) Failing after 51s
Deploy to GitHub Pages / deploy (push) Has been skipped
Pull Requests / Weekly QA / test (push) Failing after 1m13s
Broken Links Report / check-links (push) Failing after 45s

* feat: add prune subcommand, drop archived/stale entries, add container-explorer

Add a new `awesome-docker prune` subcommand that removes README entries
whose repository health status matches a configurable set (default:
archived,stale). URLs are read from the local health cache, or from a
markdown report file via --from-report when the cache is outdated.

Apply it against the issue #1439 health report to remove 5 entries
that survived the recent reorg: stitchocker, docker-consul,
blockbridge-docker-volume, docker-explorer, dockdash.

Add google/container-explorer in the Security section as the actively
maintained successor to the now-archived google/docker-explorer.

Co-Authored-By: Claude <noreply@anthropic.com>

* golangci-lint config

* fix: address golangci-lint findings

Fixes errcheck on bufio.Writer.WriteString, gocritic rangeValCopy via
indexed loops with pointer locals, gosec G703 on user-supplied CLI
output path, noctx by switching to exec.CommandContext with a timeout
in the TUI url opener, prealloc in the scorer test, plus fieldalignment
struct reorders and golines line breaks from --fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Julien Bisconti
2026-05-18 23:46:32 +02:00
committed by GitHub
parent 503e5bd7c7
commit 29222bfcb5
23 changed files with 2548 additions and 2803 deletions
+13 -10
View File
@@ -23,15 +23,15 @@ const (
// ScoredEntry is a repo with its computed health status.
type ScoredEntry struct {
LastPush time.Time
URL string
Name string
Status Status
Category string
Description string
Stars int
Forks int
HasLicense bool
LastPush time.Time
Category string
Description string
}
// ReportSummary contains grouped status counts.
@@ -46,10 +46,10 @@ type ReportSummary struct {
// ReportData is the full machine-readable report model.
type ReportData struct {
GeneratedAt time.Time `json:"generated_at"`
Total int `json:"total"`
Summary ReportSummary `json:"summary"`
Entries []ScoredEntry `json:"entries"`
ByStatus map[Status][]ScoredEntry `json:"by_status"`
Entries []ScoredEntry `json:"entries"`
Summary ReportSummary `json:"summary"`
Total int `json:"total"`
}
// Score computes the health status of a GitHub repo.
@@ -94,7 +94,8 @@ func ScoreAll(infos []checker.RepoInfo) []ScoredEntry {
func ToCacheEntries(scored []ScoredEntry) []cache.HealthEntry {
entries := make([]cache.HealthEntry, len(scored))
now := time.Now().UTC()
for i, s := range scored {
for i := range scored {
s := &scored[i]
entries[i] = cache.HealthEntry{
URL: s.URL,
Name: s.Name,
@@ -135,7 +136,8 @@ func GenerateReport(scored []ScoredEntry) string {
return
}
fmt.Fprintf(&b, "## %s\n\n", title)
for _, e := range entries {
for i := range entries {
e := &entries[i]
fmt.Fprintf(&b, "- [%s](%s) - Stars: %d - Last push: %s\n",
e.Name, e.URL, e.Stars, e.LastPush.Format("2006-01-02"))
}
@@ -152,8 +154,9 @@ func GenerateReport(scored []ScoredEntry) string {
// BuildReportData returns full report data for machine-readable and markdown rendering.
func BuildReportData(scored []ScoredEntry) ReportData {
groups := map[Status][]ScoredEntry{}
for _, s := range scored {
groups[s.Status] = append(groups[s.Status], s)
for i := range scored {
s := &scored[i]
groups[s.Status] = append(groups[s.Status], *s)
}
return ReportData{
+11 -4
View File
@@ -70,7 +70,13 @@ func TestGenerateReport(t *testing.T) {
results := []ScoredEntry{
{URL: "https://github.com/a/a", Name: "a/a", Status: StatusHealthy, Stars: 100, LastPush: time.Now()},
{URL: "https://github.com/b/b", Name: "b/b", Status: StatusArchived, Stars: 50, LastPush: time.Now()},
{URL: "https://github.com/c/c", Name: "c/c", Status: StatusStale, Stars: 10, LastPush: time.Now().AddDate(-3, 0, 0)},
{
URL: "https://github.com/c/c",
Name: "c/c",
Status: StatusStale,
Stars: 10,
LastPush: time.Now().AddDate(-3, 0, 0),
},
}
report := GenerateReport(results)
if !strings.Contains(report, "Healthy: 1") {
@@ -85,8 +91,9 @@ func TestGenerateReport(t *testing.T) {
}
func TestGenerateReportShowsAllEntries(t *testing.T) {
var results []ScoredEntry
for i := 0; i < 55; i++ {
const entryCount = 55
results := make([]ScoredEntry, 0, entryCount)
for i := range entryCount {
results = append(results, ScoredEntry{
URL: fmt.Sprintf("https://github.com/stale/%d", i),
Name: fmt.Sprintf("stale/%d", i),
@@ -100,7 +107,7 @@ func TestGenerateReportShowsAllEntries(t *testing.T) {
if strings.Contains(report, "... and") {
t.Fatal("report should not be truncated")
}
if !strings.Contains(report, "stale/54") {
if !strings.Contains(report, fmt.Sprintf("stale/%d", entryCount-1)) {
t.Fatal("report should contain all entries")
}
}