• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

samsarahq / taskrunner / 25516302028

07 May 2026 07:05PM UTC coverage: 40.25% (+2.0%) from 38.25%
25516302028

push

github

samloop
executor: tag OnStart/OnStop hook errors with hook index

When a hook returns an error, the run aborts with a bare error message
that doesn't say which hook failed. The cache snapshot hook hitting
exit 128 was particularly hard to trace because the surfaced error was
just "exit status 128" with no indication it came from the OnStart
phase. Wrapping with oops.Wrapf("OnStart/OnStop hook %d failed", i)
gives future failures a stack frame and a phase tag.

2 of 4 new or added lines in 1 file covered. (50.0%)

28 existing lines in 2 files now uncovered.

836 of 2077 relevant lines covered (40.25%)

3.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/cache/git.go
1
package cache
2

3
import (
4
        "bytes"
5
        "context"
6
        "fmt"
7
        "strings"
8

9
        "github.com/samsarahq/go/oops"
10
        "github.com/samsarahq/taskrunner/shell"
11
)
12

13
type gitClient struct {
14
        shellRun shell.ShellRun
15
}
16

17
func stripStdout(buf bytes.Buffer) string {
×
18
        return strings.Trim(buf.String(), "\n")
×
UNCOV
19
}
×
20

21
func splitStdout(buf bytes.Buffer) []string {
×
22
        return strings.Split(stripStdout(buf), "\n")
×
UNCOV
23
}
×
24

25
func (g gitClient) currentCommit(ctx context.Context) (commitHash string, err error) {
×
26
        var buffer, stderr bytes.Buffer
×
27
        if err := g.shellRun(ctx, "git rev-parse HEAD", shell.Stdout(&buffer), shell.Stderr(&stderr)); err != nil {
×
28
                return "", oops.Wrapf(err, "git rev-parse HEAD; stderr: %s", stderr.String())
×
UNCOV
29
        }
×
30

UNCOV
31
        return stripStdout(buffer), nil
×
32
}
33

34
func (g gitClient) diff(ctx context.Context, commitHash string) (modifiedFiles []string, error error) {
×
35
        var buffer, stderr bytes.Buffer
×
36
        if err := g.shellRun(ctx, fmt.Sprintf("git diff --name-only %s", commitHash), shell.Stdout(&buffer), shell.Stderr(&stderr)); err != nil {
×
37
                return nil, oops.Wrapf(err, "git diff --name-only %s; stderr: %s", commitHash, stderr.String())
×
UNCOV
38
        }
×
39

UNCOV
40
        return splitStdout(buffer), nil
×
41
}
42

43
func (g gitClient) uncomittedFiles(ctx context.Context) (newFiles []string, modifiedFiles []string, err error) {
×
44
        var buffer, stderr bytes.Buffer
×
45
        if err := g.shellRun(ctx, "git status --porcelain", shell.Stdout(&buffer), shell.Stderr(&stderr)); err != nil {
×
46
                return nil, nil, oops.Wrapf(err, "git status --porcelain; stderr: %s", stderr.String())
×
UNCOV
47
        }
×
48

49
        for _, statusLine := range splitStdout(buffer) {
×
50
                if len(strings.TrimSpace(statusLine)) < 4 {
×
UNCOV
51
                        continue
×
52
                }
53
                if strings.HasPrefix(statusLine, "??") {
×
54
                        newFiles = append(newFiles, statusLine[3:])
×
55
                } else {
×
56
                        modifiedFiles = append(modifiedFiles, statusLine[3:])
×
UNCOV
57
                }
×
58
        }
59

UNCOV
60
        return newFiles, modifiedFiles, nil
×
61
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc