Skip to content

Commit 0ff2c9e

Browse files
committed
ci: github actions for vet, lint, and test matrix
Signed-off-by: Sanjay Santhanam <[email protected]>
1 parent a73438c commit 0ff2c9e

13 files changed

Lines changed: 189 additions & 87 deletions

File tree

.github/workflows/ci.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: ci
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
8+
jobs:
9+
test:
10+
strategy:
11+
fail-fast: false
12+
matrix:
13+
os: [ubuntu-latest, macos-latest, windows-latest]
14+
go: ["1.22.x"]
15+
runs-on: ${{ matrix.os }}
16+
steps:
17+
- uses: actions/checkout@v4
18+
- uses: actions/setup-go@v5
19+
with:
20+
go-version: ${{ matrix.go }}
21+
cache: true
22+
- run: go vet ./...
23+
- run: go test -race -cover ./...
24+
25+
lint:
26+
runs-on: ubuntu-latest
27+
steps:
28+
- uses: actions/checkout@v4
29+
- uses: actions/setup-go@v5
30+
with:
31+
go-version: "1.22.x"
32+
cache: true
33+
- uses: golangci/golangci-lint-action@v6
34+
with:
35+
version: latest

.golangci.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
version: "2"
2+
3+
run:
4+
timeout: 5m
5+
6+
linters:
7+
default: none
8+
enable:
9+
- errcheck
10+
- govet
11+
- ineffassign
12+
- staticcheck
13+
- unused
14+
- misspell
15+
- revive
16+
- gocyclo
17+
settings:
18+
gocyclo:
19+
min-complexity: 15
20+
revive:
21+
rules:
22+
- name: exported
23+
disabled: false
24+
- name: package-comments
25+
disabled: true
26+
27+
formatters:
28+
enable:
29+
- gofmt
30+
31+
issues:
32+
max-issues-per-linter: 0
33+
max-same-issues: 0

internal/commands/add.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func newAddCmd() *cobra.Command {
5151
if err := s.Save(); err != nil {
5252
return err
5353
}
54-
fmt.Fprintf(cmd.OutOrStdout(), "added #%d: %s\n", id, title)
54+
pf(cmd.OutOrStdout(), "added #%d: %s\n", id, title)
5555
return nil
5656
},
5757
}

internal/commands/helpers.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,23 @@ package commands
22

33
import (
44
"fmt"
5+
"io"
56
"os"
67

78
"github.com/Sanjays2402/tsk/internal/store"
89
"github.com/spf13/cobra"
910
)
1011

12+
// pf is a tolerant Fprintf: errors writing to user-facing output are ignored.
13+
func pf(w io.Writer, format string, args ...any) {
14+
_, _ = fmt.Fprintf(w, format, args...)
15+
}
16+
17+
// pln is a tolerant Fprintln.
18+
func pln(w io.Writer, args ...any) {
19+
_, _ = fmt.Fprintln(w, args...)
20+
}
21+
1122
// resolveStore opens (and returns) the store at --file, nearest .tsk.md, or a cwd fallback.
1223
// If requireExisting is true, an error is returned when no file is found.
1324
func resolveStore(cmd *cobra.Command, requireExisting bool) (*store.Store, error) {

internal/commands/init.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func newInitCmd() *cobra.Command {
2828
if err := store.AtomicWriteFile(path, []byte("# tsk\n\n"), 0o644); err != nil {
2929
return err
3030
}
31-
fmt.Fprintf(cmd.OutOrStdout(), "created %s\n", path)
31+
pf(cmd.OutOrStdout(), "created %s\n", path)
3232
return nil
3333
},
3434
}

internal/commands/ls.go

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -48,38 +48,17 @@ func newLsCmd() *cobra.Command {
4848
}
4949

5050
func applyFilters(in []model.Task, f lsFilters) ([]model.Task, error) {
51-
var prio model.Priority
52-
prioFilter := false
53-
if f.priorityStr != "" {
54-
p, err := model.ParsePriority(f.priorityStr)
55-
if err != nil {
56-
return nil, err
57-
}
58-
prio = p
59-
prioFilter = true
51+
prio, prioFilter, err := resolvePriorityFilter(f.priorityStr)
52+
if err != nil {
53+
return nil, err
6054
}
6155
now := time.Now()
6256
out := make([]model.Task, 0, len(in))
6357
for _, t := range in {
64-
switch {
65-
case f.all:
66-
// everything
67-
case f.done:
68-
if !t.Done {
69-
continue
70-
}
71-
default:
72-
if t.Done {
73-
continue
74-
}
75-
}
76-
if f.today && !t.IsDueToday(now) {
58+
if !passStateFilter(t, f) {
7759
continue
7860
}
79-
if f.overdue && !t.IsOverdue(now) {
80-
continue
81-
}
82-
if f.upcoming && !t.IsUpcoming(now) {
61+
if !passDueFilter(t, f, now) {
8362
continue
8463
}
8564
if f.tag != "" && !t.HasTag(f.tag) {
@@ -93,14 +72,49 @@ func applyFilters(in []model.Task, f lsFilters) ([]model.Task, error) {
9372
return out, nil
9473
}
9574

75+
func resolvePriorityFilter(s string) (model.Priority, bool, error) {
76+
if s == "" {
77+
return model.PriorityMedium, false, nil
78+
}
79+
p, err := model.ParsePriority(s)
80+
if err != nil {
81+
return 0, false, err
82+
}
83+
return p, true, nil
84+
}
85+
86+
func passStateFilter(t model.Task, f lsFilters) bool {
87+
switch {
88+
case f.all:
89+
return true
90+
case f.done:
91+
return t.Done
92+
default:
93+
return !t.Done
94+
}
95+
}
96+
97+
func passDueFilter(t model.Task, f lsFilters, now time.Time) bool {
98+
if f.today && !t.IsDueToday(now) {
99+
return false
100+
}
101+
if f.overdue && !t.IsOverdue(now) {
102+
return false
103+
}
104+
if f.upcoming && !t.IsUpcoming(now) {
105+
return false
106+
}
107+
return true
108+
}
109+
96110
func printTasks(w io.Writer, tasks []model.Task, asJSON bool) error {
97111
if asJSON {
98112
enc := json.NewEncoder(w)
99113
enc.SetIndent("", " ")
100114
return enc.Encode(tasks)
101115
}
102116
if len(tasks) == 0 {
103-
fmt.Fprintln(w, "no tasks")
117+
pln(w, "no tasks")
104118
return nil
105119
}
106120
for _, t := range tasks {
@@ -115,7 +129,7 @@ func printTasks(w io.Writer, tasks []model.Task, asJSON bool) error {
115129
if len(t.Tags) > 0 {
116130
line += " #" + strings.Join(t.Tags, " #")
117131
}
118-
fmt.Fprintln(w, line)
132+
pln(w, line)
119133
}
120134
return nil
121135
}

internal/commands/next.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@ func newNextCmd() *cobra.Command {
3535
}
3636
}
3737
if best == nil {
38-
fmt.Fprintln(cmd.OutOrStdout(), "all caught up")
38+
pln(cmd.OutOrStdout(), "all caught up")
3939
return nil
4040
}
4141
line := fmt.Sprintf("#%d [%s] %s", best.ID, best.Priority, best.Title)
4242
if best.Due != nil {
4343
line += " due:" + best.Due.Format(model.DateLayout)
4444
}
45-
fmt.Fprintln(cmd.OutOrStdout(), line)
45+
pln(cmd.OutOrStdout(), line)
4646
return nil
4747
},
4848
}

internal/commands/root.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func newVersionCmd() *cobra.Command {
6464
Use: "version",
6565
Short: "Print build version",
6666
RunE: func(cmd *cobra.Command, _ []string) error {
67-
fmt.Fprintf(cmd.OutOrStdout(), "tsk %s (commit %s, built %s)\n", buildVersion, buildCommit, buildDate)
67+
pf(cmd.OutOrStdout(), "tsk %s (commit %s, built %s)\n", buildVersion, buildCommit, buildDate)
6868
return nil
6969
},
7070
}

internal/commands/stats.go

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package commands
22

33
import (
4-
"fmt"
54
"sort"
65
"time"
76

@@ -20,17 +19,17 @@ func newStatsCmd() *cobra.Command {
2019
}
2120
summary := computeStats(s.Tasks, time.Now())
2221
out := cmd.OutOrStdout()
23-
fmt.Fprintf(out, "total: %d\n", summary.Total)
24-
fmt.Fprintf(out, "done: %d\n", summary.Done)
25-
fmt.Fprintf(out, "undone: %d\n", summary.Undone)
26-
fmt.Fprintf(out, "overdue: %d\n", summary.Overdue)
27-
fmt.Fprintf(out, "today: %d\n", summary.Today)
28-
fmt.Fprintf(out, "completion: %.0f%%\n", summary.Completion)
29-
fmt.Fprintf(out, "streak: %d day(s)\n", summary.Streak)
22+
pf(out, "total: %d\n", summary.Total)
23+
pf(out, "done: %d\n", summary.Done)
24+
pf(out, "undone: %d\n", summary.Undone)
25+
pf(out, "overdue: %d\n", summary.Overdue)
26+
pf(out, "today: %d\n", summary.Today)
27+
pf(out, "completion: %.0f%%\n", summary.Completion)
28+
pf(out, "streak: %d day(s)\n", summary.Streak)
3029
if len(summary.TopTags) > 0 {
31-
fmt.Fprintln(out, "top tags:")
30+
pln(out, "top tags:")
3231
for _, tc := range summary.TopTags {
33-
fmt.Fprintf(out, " %-16s %d\n", tc.Tag, tc.Count)
32+
pf(out, " %-16s %d\n", tc.Tag, tc.Count)
3433
}
3534
}
3635
return nil

internal/commands/toggle.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func runToggle(done bool) func(*cobra.Command, []string) error {
4747
if !done {
4848
verb = "undone"
4949
}
50-
fmt.Fprintf(cmd.OutOrStdout(), "marked %d task(s) %s\n", len(args), verb)
50+
pf(cmd.OutOrStdout(), "marked %d task(s) %s\n", len(args), verb)
5151
return nil
5252
}
5353
}
@@ -75,7 +75,7 @@ func newRmCmd() *cobra.Command {
7575
if err := s.Save(); err != nil {
7676
return err
7777
}
78-
fmt.Fprintf(cmd.OutOrStdout(), "removed %d task(s)\n", len(args))
78+
pf(cmd.OutOrStdout(), "removed %d task(s)\n", len(args))
7979
return nil
8080
},
8181
}

0 commit comments

Comments
 (0)