Add closed_at timestamp tracking to issues
- Add closed_at field to Issue type with JSON marshaling - Implement closed_at timestamp in SQLite storage layer - Update import/export to handle closed_at field - Add comprehensive tests for closed_at functionality - Maintain backward compatibility with existing databases Amp-Thread-ID: https://ampcode.com/threads/T-f3a7799b-f91e-4432-a690-aae0aed364b3 Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
@@ -37,6 +37,7 @@ func TestExportImport(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create test issues
|
||||
now := time.Now()
|
||||
issues := []*types.Issue{
|
||||
{
|
||||
ID: "test-1",
|
||||
@@ -45,8 +46,8 @@ func TestExportImport(t *testing.T) {
|
||||
Status: types.StatusOpen,
|
||||
Priority: 1,
|
||||
IssueType: types.TypeBug,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
},
|
||||
{
|
||||
ID: "test-2",
|
||||
@@ -56,8 +57,8 @@ func TestExportImport(t *testing.T) {
|
||||
Priority: 2,
|
||||
IssueType: types.TypeFeature,
|
||||
Assignee: "alice",
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
},
|
||||
{
|
||||
ID: "test-3",
|
||||
@@ -66,8 +67,9 @@ func TestExportImport(t *testing.T) {
|
||||
Status: types.StatusClosed,
|
||||
Priority: 3,
|
||||
IssueType: types.TypeTask,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
ClosedAt: &now,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -177,7 +179,7 @@ func TestExportImport(t *testing.T) {
|
||||
// Import as update
|
||||
updates := map[string]interface{}{
|
||||
"title": issue.Title,
|
||||
"status": issue.Status,
|
||||
"status": string(issue.Status),
|
||||
}
|
||||
if err := store.UpdateIssue(ctx, issue.ID, updates, "test"); err != nil {
|
||||
t.Fatalf("UpdateIssue failed: %v", err)
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/steveyegge/beads/internal/storage/sqlite"
|
||||
@@ -237,6 +238,18 @@ Behavior:
|
||||
updated++
|
||||
} else {
|
||||
// Create new issue
|
||||
// Normalize closed_at based on status before creating (enforce invariant)
|
||||
if issue.Status == types.StatusClosed {
|
||||
// Status is closed: ensure closed_at is set
|
||||
if issue.ClosedAt == nil {
|
||||
now := time.Now()
|
||||
issue.ClosedAt = &now
|
||||
}
|
||||
} else {
|
||||
// Status is not closed: ensure closed_at is NULL
|
||||
issue.ClosedAt = nil
|
||||
}
|
||||
|
||||
if err := store.CreateIssue(ctx, issue, "import"); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error creating issue %s: %v\n", issue.ID, err)
|
||||
os.Exit(1)
|
||||
|
||||
Reference in New Issue
Block a user