Skip to content

Commit 96a3718

Browse files
committed
Fix errors
1 parent ed0856b commit 96a3718

File tree

7 files changed

+101
-74
lines changed

7 files changed

+101
-74
lines changed

.github/workflows/test.yml

Lines changed: 7 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ on:
66

77
jobs:
88
test:
9-
name: Run Tests
9+
name: CI Tests
1010
runs-on: ubuntu-latest
1111

1212
steps:
@@ -19,54 +19,11 @@ jobs:
1919
go-version: '1.25'
2020
cache: true
2121

22-
- name: Download dependencies
23-
run: go mod download
22+
- name: Install just
23+
uses: extractions/setup-just@v2
2424

25-
- name: Verify dependencies
26-
run: go mod verify
25+
- name: Install staticcheck
26+
run: go install honnef.co/go/tools/cmd/staticcheck@latest
2727

28-
- name: Run tests
29-
run: go test -v -race -timeout 5m -coverprofile=coverage.out -covermode=atomic
30-
31-
- name: Display coverage
32-
run: go tool cover -func=coverage.out
33-
34-
- name: Upload coverage to Codecov
35-
uses: codecov/codecov-action@v4
36-
with:
37-
files: ./coverage.out
38-
flags: unittests
39-
fail_ci_if_error: false
40-
env:
41-
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
42-
43-
lint:
44-
name: Run Linters
45-
runs-on: ubuntu-latest
46-
47-
steps:
48-
- name: Checkout code
49-
uses: actions/checkout@v4
50-
51-
- name: Set up Go
52-
uses: actions/setup-go@v5
53-
with:
54-
go-version: '1.25'
55-
cache: true
56-
57-
- name: Run go vet
58-
run: go vet ./...
59-
60-
- name: Run gofmt
61-
run: |
62-
if [ -n "$(gofmt -l .)" ]; then
63-
echo "Go code is not formatted:"
64-
gofmt -d .
65-
exit 1
66-
fi
67-
68-
- name: Run staticcheck
69-
uses: dominikh/staticcheck-action@v1
70-
with:
71-
version: "latest"
72-
install-go: false
28+
- name: Run CI checks
29+
run: just ci

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
rtask
22
*.toml
33
*.nu
4+
coverage.out

go.mod

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,28 @@ module rtask
33
go 1.25
44

55
require (
6-
github.com/go-chi/chi/v5 v5.2.2
7-
github.com/lmittmann/tint v1.1.1
8-
github.com/urfave/cli/v3 v3.3.8
9-
golang.org/x/crypto v0.40.0
6+
github.com/go-chi/chi/v5 v5.2.3
7+
github.com/lmittmann/tint v1.1.2
8+
github.com/urfave/cli/v3 v3.4.1
9+
golang.org/x/crypto v0.43.0
1010
)
1111

12-
require github.com/x448/float16 v0.8.4 // indirect
12+
require (
13+
github.com/x448/float16 v0.8.4 // indirect
14+
go.yaml.in/yaml/v2 v2.4.3 // indirect
15+
)
1316

1417
require (
1518
github.com/BurntSushi/toml v1.5.0
1619
github.com/beorn7/perks v1.0.1 // indirect
1720
github.com/cespare/xxhash/v2 v2.3.0 // indirect
1821
github.com/fxamacker/cbor/v2 v2.9.0
1922
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
20-
github.com/prometheus/client_golang v1.22.0
21-
github.com/prometheus/client_model v0.6.1 // indirect
22-
github.com/prometheus/common v0.62.0 // indirect
23-
github.com/prometheus/procfs v0.15.1 // indirect
24-
golang.org/x/sys v0.34.0 // indirect
25-
golang.org/x/time v0.11.0
26-
google.golang.org/protobuf v1.36.5 // indirect
23+
github.com/prometheus/client_golang v1.23.2
24+
github.com/prometheus/client_model v0.6.2 // indirect
25+
github.com/prometheus/common v0.67.1 // indirect
26+
github.com/prometheus/procfs v0.17.0 // indirect
27+
golang.org/x/sys v0.37.0 // indirect
28+
golang.org/x/time v0.14.0
29+
google.golang.org/protobuf v1.36.10 // indirect
2730
)

go.sum

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sa
1010
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
1111
github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618=
1212
github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
13+
github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE=
14+
github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
1315
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
1416
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
1517
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
@@ -18,31 +20,55 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0
1820
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
1921
github.com/lmittmann/tint v1.1.1 h1:xmmGuinUsCSxWdwH1OqMUQ4tzQsq3BdjJLAAmVKJ9Dw=
2022
github.com/lmittmann/tint v1.1.1/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
23+
github.com/lmittmann/tint v1.1.2 h1:2CQzrL6rslrsyjqLDwD11bZ5OpLBPU+g3G/r5LSfS8w=
24+
github.com/lmittmann/tint v1.1.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
2125
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
2226
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
2327
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
2428
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
2529
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
2630
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
31+
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
32+
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
2733
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
2834
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
35+
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
36+
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
2937
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
3038
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
39+
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
40+
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
3141
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
3242
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
43+
github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
44+
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
3345
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
3446
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
47+
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
3548
github.com/urfave/cli/v3 v3.3.8 h1:BzolUExliMdet9NlJ/u4m5vHSotJ3PzEqSAZ1oPMa/E=
3649
github.com/urfave/cli/v3 v3.3.8/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo=
50+
github.com/urfave/cli/v3 v3.4.1 h1:1M9UOCy5bLmGnuu1yn3t3CB4rG79Rtoxuv1sPhnm6qM=
51+
github.com/urfave/cli/v3 v3.4.1/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo=
3752
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
3853
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
54+
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
55+
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
3956
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
4057
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
58+
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
59+
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
4160
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
4261
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
62+
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
63+
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
4364
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
4465
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
66+
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
67+
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
4568
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
4669
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
70+
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
71+
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
72+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
4773
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
4874
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

handler.go

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,22 @@ func NewTaskContext(tm *TaskManager, w http.ResponseWriter, r *http.Request) *ta
5353
}
5454

5555
type taskExecutionResult struct {
56-
Status string `json:"status,omitempty"`
57-
ExitCode int `json:"exit_code"`
58-
StdOut string `json:"stdout,omitempty"`
59-
StdErr string `json:"stderr,omitempty"`
56+
mu sync.RWMutex `json:"-"`
57+
Status string `json:"status,omitempty"`
58+
ExitCode int `json:"exit_code"`
59+
StdOut string `json:"stdout,omitempty"`
60+
StdErr string `json:"stderr,omitempty"`
61+
}
62+
63+
func (r *taskExecutionResult) copy() taskExecutionResult {
64+
r.mu.RLock()
65+
defer r.mu.RUnlock()
66+
return taskExecutionResult{
67+
Status: r.Status,
68+
ExitCode: r.ExitCode,
69+
StdOut: r.StdOut,
70+
StdErr: r.StdErr,
71+
}
6072
}
6173

6274
type TaskManager struct {
@@ -158,7 +170,9 @@ func (tm *TaskManager) getTaskResult(w http.ResponseWriter, r *http.Request) {
158170

159171
w.Header().Set("Content-Type", "application/json")
160172
if exists {
161-
json.NewEncoder(w).Encode(result)
173+
// Copy the result using thread-safe copy method
174+
resultCopy := result.copy()
175+
json.NewEncoder(w).Encode(&resultCopy)
162176
} else {
163177
w.WriteHeader(http.StatusNotFound)
164178
json.NewEncoder(w).Encode(map[string]string{"error": "task not found"})
@@ -283,6 +297,10 @@ func (tm *TaskManager) runTask(taskCtx *taskContext) {
283297
err := cmd.Run()
284298
duration := time.Since(startTime)
285299

300+
// Lock the result for all updates
301+
taskCtx.result.mu.Lock()
302+
defer taskCtx.result.mu.Unlock()
303+
286304
taskCtx.result.StdOut = limitedStdout.Buffer.String()
287305
taskCtx.result.StdErr = limitedStderr.Buffer.String()
288306

justfile

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,32 @@ build:
33

44
run *args: build
55
GO_LOG=debug ./rtask {{args}}
6+
7+
# Download and verify dependencies
8+
deps:
9+
go mod download
10+
go mod verify
11+
12+
# Run tests with race detection and coverage
13+
test:
14+
go test -v -race -timeout 5m -coverprofile=coverage.out -covermode=atomic
15+
go tool cover -func=coverage.out
16+
17+
# Run linters
18+
lint:
19+
go vet ./...
20+
gofmt -l .
21+
staticcheck
22+
23+
# Check code formatting (fail if not formatted)
24+
fmt-check:
25+
#!/usr/bin/env bash
26+
set -euo pipefail
27+
if [ -n "$(gofmt -l .)" ]; then
28+
echo "Go code is not formatted:"
29+
gofmt -d .
30+
exit 1
31+
fi
32+
33+
# Full CI check (what runs in GitHub Actions)
34+
ci: deps lint fmt-check test

util.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,6 @@ import (
77
"strings"
88
)
99

10-
func truncateString(s string, maxLen int) string {
11-
if len(s) <= maxLen {
12-
return s
13-
}
14-
return s[:maxLen]
15-
}
16-
1710
// OutputCollector wraps an io.Writer and limits the number of bytes written to it.
1811
// Once the limit is reached, subsequent writes are discarded (no-op).
1912
type OutputCollector struct {

0 commit comments

Comments
 (0)