Major improvements to code quality, documentation, and CI: Code Quality: - Add golangci-lint configuration with 13 linters - Fix unchecked error returns in export/import/init - Refactor duplicate scanIssues code - Add package comments for all packages - Add const block comments for exported constants - Configure errcheck to allow idiomatic defer patterns Documentation: - Add comprehensive CONTRIBUTING.md with setup, testing, and workflow - Fix QUICKSTART.md binary name references (beads → bd) - Correct default database path documentation CI/CD: - Add GitHub Actions workflow for tests and linting - Enable race detection and coverage reporting - Automated quality checks on all PRs All tests passing. Lint issues reduced from 117 to 103 (remaining are idiomatic patterns and test code). Ready for open-source release. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
84 lines
2.0 KiB
Go
84 lines
2.0 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"sort"
|
|
|
|
"github.com/spf13/cobra"
|
|
"github.com/steveyegge/beads/internal/types"
|
|
)
|
|
|
|
var exportCmd = &cobra.Command{
|
|
Use: "export",
|
|
Short: "Export issues to JSONL format",
|
|
Long: `Export all issues to JSON Lines format (one JSON object per line).
|
|
Issues are sorted by ID for consistent diffs.
|
|
|
|
Output to stdout by default, or use -o flag for file output.`,
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
format, _ := cmd.Flags().GetString("format")
|
|
output, _ := cmd.Flags().GetString("output")
|
|
statusFilter, _ := cmd.Flags().GetString("status")
|
|
|
|
if format != "jsonl" {
|
|
fmt.Fprintf(os.Stderr, "Error: only 'jsonl' format is currently supported\n")
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Build filter
|
|
filter := types.IssueFilter{}
|
|
if statusFilter != "" {
|
|
status := types.Status(statusFilter)
|
|
filter.Status = &status
|
|
}
|
|
|
|
// Get all issues
|
|
ctx := context.Background()
|
|
issues, err := store.SearchIssues(ctx, "", filter)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Sort by ID for consistent output
|
|
sort.Slice(issues, func(i, j int) bool {
|
|
return issues[i].ID < issues[j].ID
|
|
})
|
|
|
|
// Open output
|
|
out := os.Stdout
|
|
if output != "" {
|
|
f, err := os.Create(output)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error creating output file: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
defer func() {
|
|
if err := f.Close(); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Warning: failed to close output file: %v\n", err)
|
|
}
|
|
}()
|
|
out = f
|
|
}
|
|
|
|
// Write JSONL
|
|
encoder := json.NewEncoder(out)
|
|
for _, issue := range issues {
|
|
if err := encoder.Encode(issue); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error encoding issue %s: %v\n", issue.ID, err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
},
|
|
}
|
|
|
|
func init() {
|
|
exportCmd.Flags().StringP("format", "f", "jsonl", "Export format (jsonl)")
|
|
exportCmd.Flags().StringP("output", "o", "", "Output file (default: stdout)")
|
|
exportCmd.Flags().StringP("status", "s", "", "Filter by status")
|
|
rootCmd.AddCommand(exportCmd)
|
|
}
|