Skip to content

Commit 63f55cc

Browse files
committed
Fix stale command reporting 0 days for all dependencies
Go's time.Time.String() produces timestamps like '2026-02-05 14:16:48 +0000 +0000' which SQLite's julianday() cannot parse, returning NULL. The CAST to INTEGER then gives 0. Fix the storage to format committed_at as UTC and wrap julianday() calls in substr(..., 1, 19) so existing databases with the old format still work. Fixes #83
1 parent 376652a commit 63f55cc

File tree

4 files changed

+69
-4
lines changed

4 files changed

+69
-4
lines changed

cmd/analysis_test.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ package cmd_test
33
import (
44
"bytes"
55
"encoding/json"
6+
"os"
7+
"os/exec"
8+
"path/filepath"
69
"strings"
710
"testing"
811

@@ -863,4 +866,66 @@ func TestStaleCommand(t *testing.T) {
863866
t.Error("expected 'name' field in stale JSON")
864867
}
865868
})
869+
870+
t.Run("computes days since correctly for old commits", func(t *testing.T) {
871+
repoDir := createTestRepo(t)
872+
873+
// Create lockfile with a backdated commit (90 days ago)
874+
fullPath := filepath.Join(repoDir, "package-lock.json")
875+
if err := os.WriteFile(fullPath, []byte(packageLockJSON), 0644); err != nil {
876+
t.Fatal(err)
877+
}
878+
gitCmd := exec.Command("git", "add", "package-lock.json")
879+
gitCmd.Dir = repoDir
880+
if err := gitCmd.Run(); err != nil {
881+
t.Fatal(err)
882+
}
883+
gitCmd = exec.Command("git", "commit", "-m", "Add lockfile")
884+
gitCmd.Dir = repoDir
885+
gitCmd.Env = append(os.Environ(),
886+
"GIT_COMMITTER_DATE=2020-01-01T00:00:00Z",
887+
"GIT_AUTHOR_DATE=2020-01-01T00:00:00Z",
888+
)
889+
if err := gitCmd.Run(); err != nil {
890+
t.Fatal(err)
891+
}
892+
893+
cleanup := chdir(t, repoDir)
894+
defer cleanup()
895+
896+
rootCmd := cmd.NewRootCmd()
897+
rootCmd.SetArgs([]string{"init"})
898+
if err := rootCmd.Execute(); err != nil {
899+
t.Fatalf("init failed: %v", err)
900+
}
901+
902+
var stdout bytes.Buffer
903+
rootCmd = cmd.NewRootCmd()
904+
rootCmd.SetArgs([]string{"stale", "--days", "0", "--format", "json"})
905+
rootCmd.SetOut(&stdout)
906+
907+
if err := rootCmd.Execute(); err != nil {
908+
t.Fatalf("stale failed: %v", err)
909+
}
910+
911+
var result []map[string]interface{}
912+
if err := json.Unmarshal(stdout.Bytes(), &result); err != nil {
913+
t.Fatalf("failed to parse JSON: %v", err)
914+
}
915+
916+
if len(result) == 0 {
917+
t.Fatal("expected stale packages")
918+
}
919+
920+
// The commit is from 2020, so days_since should be well over 1000
921+
for _, entry := range result {
922+
days, ok := entry["days_since"].(float64)
923+
if !ok {
924+
t.Fatalf("days_since not a number: %v", entry["days_since"])
925+
}
926+
if days < 1000 {
927+
t.Errorf("expected days_since > 1000 for a 2020 commit, got %v for %v", days, entry["name"])
928+
}
929+
}
930+
})
866931
}

internal/database/batch_writer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ func (w *BatchWriter) insertCommits(tx *sql.Tx, now time.Time) error {
228228
if pc.hasChanges {
229229
hasChanges = 1
230230
}
231-
args = append(args, pc.info.SHA, pc.info.Message, pc.info.AuthorName, pc.info.AuthorEmail, pc.info.CommittedAt, hasChanges, now, now)
231+
args = append(args, pc.info.SHA, pc.info.Message, pc.info.AuthorName, pc.info.AuthorEmail, pc.info.CommittedAt.UTC().Format("2006-01-02 15:04:05"), hasChanges, now, now)
232232
}
233233

234234
if _, err := tx.Exec(sb.String(), args...); err != nil {

internal/database/queries.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,7 @@ func (db *DB) GetStaleDependencies(branchID int64, ecosystem string, days int) (
696696
)
697697
SELECT cd.name, cd.ecosystem, cd.requirement, cd.path,
698698
COALESCE(lc.last_changed, '') as last_changed,
699-
CAST(julianday('now') - julianday(COALESCE(lc.last_changed, '2000-01-01')) AS INTEGER) as days_since
699+
CAST(julianday('now') - julianday(substr(COALESCE(lc.last_changed, '2000-01-01'), 1, 19)) AS INTEGER) as days_since
700700
FROM current_deps cd
701701
LEFT JOIN last_changed lc ON lc.name = cd.name AND lc.path = cd.path
702702
`
@@ -713,7 +713,7 @@ func (db *DB) GetStaleDependencies(branchID int64, ecosystem string, days int) (
713713
} else {
714714
query += " WHERE"
715715
}
716-
query += " CAST(julianday('now') - julianday(COALESCE(lc.last_changed, '2000-01-01')) AS INTEGER) >= ?"
716+
query += " CAST(julianday('now') - julianday(substr(COALESCE(lc.last_changed, '2000-01-01'), 1, 19)) AS INTEGER) >= ?"
717717
args = append(args, days)
718718
}
719719

internal/database/writer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ func (w *Writer) InsertCommit(info CommitInfo, hasChanges bool) (int64, bool, er
196196
info.Message,
197197
info.AuthorName,
198198
info.AuthorEmail,
199-
info.CommittedAt,
199+
info.CommittedAt.UTC().Format("2006-01-02 15:04:05"),
200200
hasChangesInt,
201201
now,
202202
now,

0 commit comments

Comments
 (0)