Skip to content

Commit 13ebc20

Browse files
committed
Add github actions and linter
1 parent fd04b0d commit 13ebc20

File tree

13 files changed

+119
-57
lines changed

13 files changed

+119
-57
lines changed

Diff for: .github/workflows/test.yaml

+49-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,64 @@
11
name: Tests
2-
on: [push]
2+
on:
3+
push:
4+
branches:
5+
- main
6+
pull_request:
7+
branches:
8+
- main
39
jobs:
10+
lint:
11+
name: Lint Go
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Install Go
15+
uses: actions/setup-go@v5
16+
with:
17+
go-version: 1.23
18+
19+
- name: Check out code
20+
uses: actions/checkout@v4
21+
22+
- name: golangci-lint
23+
uses: golangci/golangci-lint-action@v6
24+
with:
25+
version: v1.60
26+
working-directory: ./api
27+
428
test:
5-
name: Tests
29+
name: Test Go
630
runs-on: ubuntu-latest
731
steps:
832
- name: Install Go
933
uses: actions/setup-go@v5
1034
with:
1135
go-version: 1.23
1236

13-
- name: Check out code into the Go module directory
37+
- name: Check out code
1438
uses: actions/checkout@v4
1539

1640
- name: Run Tests
1741
working-directory: ./api
1842
run: go test -v -bench=. -race ./...
43+
44+
lint-ui:
45+
name: Lint UI
46+
runs-on: ubuntu-latest
47+
strategy:
48+
matrix:
49+
node_version: [20]
50+
51+
steps:
52+
- name: Check out code
53+
uses: actions/checkout@v4
54+
55+
- name: Use Node.js ${{ matrix.node_version }}
56+
uses: actions/setup-node@v4
57+
with:
58+
node_version: ${{ matrix.node_version }}
59+
60+
- name: run CI
61+
working-directory: ./ui
62+
run: |
63+
npm install
64+
npm run lint

Diff for: api/pkg/parser/parser_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,4 @@ func TestReadSurveys(t *testing.T) {
3939
if err == nil {
4040
t.Fatalf("expected error, got nil")
4141
}
42-
}
42+
}

Diff for: api/pkg/services/services.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import (
88
)
99

1010
type Services struct {
11-
Storage storage.Interface
12-
FileStorage storage.FileInterface
11+
Storage storage.Interface
12+
FileStorage storage.FileInterface
1313
}
1414

1515
func InitServices() (Services, error) {

Diff for: api/pkg/storage/file_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,4 @@ func TestSaveFile(t *testing.T) {
8888
}
8989
})
9090
}
91-
}
91+
}

Diff for: api/pkg/storage/sqlite.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
migratepg "github.com/golang-migrate/migrate/v4/database/sqlite3"
1616
_ "github.com/golang-migrate/migrate/v4/source/file"
1717
"github.com/google/uuid"
18+
"github.com/plutov/formulosity/api/pkg/log"
1819
"github.com/plutov/formulosity/api/pkg/types"
1920
)
2021

@@ -134,7 +135,9 @@ func (p *Sqlite) GetSurveys() ([]*types.Survey, error) {
134135
}
135136

136137
survey.CreatedAt, _ = time.Parse(types.DateTimeFormat, createdAtStr.String)
137-
json.Unmarshal([]byte(configStr.String), &survey.Config)
138+
if err := json.Unmarshal([]byte(configStr.String), &survey.Config); err != nil {
139+
log.WithError(err).Error("unable to decode config")
140+
}
138141

139142
totalResponses := survey.Stats.SessionsCountInProgess + survey.Stats.SessionsCountCompleted
140143
if totalResponses > 0 {
@@ -174,7 +177,9 @@ func (p *Sqlite) GetSurveyByField(field string, value interface{}) (*types.Surve
174177
}
175178

176179
survey.CreatedAt, _ = time.Parse(types.DateTimeFormat, createdAtStr.String)
177-
json.Unmarshal([]byte(configStr.String), &survey.Config)
180+
if err := json.Unmarshal([]byte(configStr.String), &survey.Config); err != nil {
181+
log.WithError(err).Error("unable to decode survey config")
182+
}
178183

179184
return survey, nil
180185
}

Diff for: api/pkg/surveys/sessions.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,9 @@ func convertAnswerBytesToAnswerType(survey *types.Survey, answers []types.Questi
7979
if err != nil {
8080
log.WithError(err).Error("unable to get answer type")
8181
} else {
82-
json.Unmarshal(a.AnswerBytes, &answerType)
82+
if err := json.Unmarshal(a.AnswerBytes, &answerType); err != nil {
83+
log.WithError(err).Error("unable to decode answer")
84+
}
8385
answers[i].Answer = answerType
8486
}
8587

Diff for: api/pkg/surveys/sync.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,17 @@ func SyncSurveysOnChange(svc services.Services) {
1616

1717
dir := os.Getenv("SURVEYS_DIR")
1818

19-
watcher.Add(dir)
19+
if err := watcher.Add(dir); err != nil {
20+
log.WithError(err).Error("unable to add watcher")
21+
}
2022

2123
done := make(chan bool)
2224
go func() {
2325
for {
24-
select {
25-
case event := <-watcher.Events:
26-
log.With("event", event).Info("file change event received")
27-
SyncSurveys(svc)
26+
event := <-watcher.Events
27+
log.With("event", event).Info("file change event received")
28+
if err := SyncSurveys(svc); err != nil {
29+
log.WithError(err).Error("unable to sync surveys on file change")
2830
}
2931
}
3032
}()

Diff for: api/pkg/types/answers.go

+22-22
Original file line numberDiff line numberDiff line change
@@ -187,12 +187,12 @@ func (a *FileAnswer) Validate(q Question) error {
187187

188188
if q.Validation.MaxSizeBytes != nil {
189189
bytes, err := GetStringMultiplication(*q.Validation.MaxSizeBytes)
190-
if err != nil {
191-
return fmt.Errorf("invalid MaxSizeBytes format: %v", err)
192-
}
193-
if a.FileSize > bytes {
194-
return fmt.Errorf("file size exceeds the maximum size of %s", formatBytes(bytes))
195-
}
190+
if err != nil {
191+
return fmt.Errorf("invalid MaxSizeBytes format: %v", err)
192+
}
193+
if a.FileSize > bytes {
194+
return fmt.Errorf("file size exceeds the maximum size of %s", formatBytes(bytes))
195+
}
196196
} else {
197197
return fmt.Errorf("questions[].validation.maxSizeBytes is required when questions[].type is file")
198198
}
@@ -213,23 +213,23 @@ func (a *FileAnswer) Validate(q Question) error {
213213
}
214214

215215
func formatBytes(bytes int64) string {
216-
const (
217-
KB = 1024
218-
MB = KB * 1024
219-
GB = MB * 1024
216+
const (
217+
KB = 1024
218+
MB = KB * 1024
219+
GB = MB * 1024
220220
TB = GB * 1024
221-
)
221+
)
222222

223-
switch {
223+
switch {
224224
case bytes >= TB:
225225
return fmt.Sprintf("%.2f TB", float64(bytes)/float64(TB))
226-
case bytes >= GB:
227-
return fmt.Sprintf("%.2f GB", float64(bytes)/float64(GB))
228-
case bytes >= MB:
229-
return fmt.Sprintf("%.2f MB", float64(bytes)/float64(MB))
230-
case bytes >= KB:
231-
return fmt.Sprintf("%.2f KB", float64(bytes)/float64(KB))
232-
default:
233-
return fmt.Sprintf("%d bytes", bytes)
234-
}
235-
}
226+
case bytes >= GB:
227+
return fmt.Sprintf("%.2f GB", float64(bytes)/float64(GB))
228+
case bytes >= MB:
229+
return fmt.Sprintf("%.2f MB", float64(bytes)/float64(MB))
230+
case bytes >= KB:
231+
return fmt.Sprintf("%.2f KB", float64(bytes)/float64(KB))
232+
default:
233+
return fmt.Sprintf("%d bytes", bytes)
234+
}
235+
}

Diff for: api/pkg/types/answers_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"strings"
55
"testing"
66
)
7+
78
func ptrString(s string) *string {
89
return &s
910
}

Diff for: api/pkg/types/files.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ package types
33
import "io"
44

55
type File struct {
6-
Name string
7-
Data io.Reader
8-
Size int64
9-
Format string
10-
}
6+
Name string
7+
Data io.Reader
8+
Size int64
9+
Format string
10+
}

Diff for: api/pkg/types/questions.go

+10-7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"fmt"
88
"strconv"
99
"strings"
10+
11+
"github.com/plutov/formulosity/api/pkg/log"
1012
)
1113

1214
type QuestionType string
@@ -55,10 +57,10 @@ type Question struct {
5557
}
5658

5759
type QuestionValidation struct {
58-
Min *int `json:"min,omitempty" yaml:"min,omitempty"`
59-
Max *int `json:"max,omitempty" yaml:"max,omitempty"`
60-
Formats *[]string `json:"formats,omitempty" yaml:"formats,omitempty"`
61-
MaxSizeBytes *string `json:"max_size_bytes,omitempty" yaml:"max_size_bytes,omitempty"`
60+
Min *int `json:"min,omitempty" yaml:"min,omitempty"`
61+
Max *int `json:"max,omitempty" yaml:"max,omitempty"`
62+
Formats *[]string `json:"formats,omitempty" yaml:"formats,omitempty"`
63+
MaxSizeBytes *string `json:"max_size_bytes,omitempty" yaml:"max_size_bytes,omitempty"`
6264
}
6365

6466
func (s *Questions) Validate() error {
@@ -135,7 +137,9 @@ func (v QuestionValidation) ValidateFile() error {
135137

136138
func (q Question) GenerateHash() string {
137139
var b bytes.Buffer
138-
gob.NewEncoder(&b).Encode(q)
140+
if err := gob.NewEncoder(&b).Encode(q); err != nil {
141+
log.WithError(err).Error("unable to generate question has")
142+
}
139143

140144
h := sha256.New()
141145
h.Write(b.Bytes())
@@ -227,7 +231,6 @@ func (q Question) ValidateAnswer(answer interface{}) error {
227231
return nil
228232
}
229233

230-
231234
func GetStringMultiplication(expression string) (int64, error) {
232235
parts := strings.Split(expression, "*")
233236

@@ -244,4 +247,4 @@ func GetStringMultiplication(expression string) (int64, error) {
244247
}
245248

246249
return int64(result), nil
247-
}
250+
}

Diff for: api/pkg/types/survey.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"time"
1212

1313
"github.com/microcosm-cc/bluemonday"
14+
"github.com/plutov/formulosity/api/pkg/log"
1415
)
1516

1617
const (
@@ -192,7 +193,9 @@ func (s *SurveyConfig) Normalize() {
192193

193194
func (s *SurveyConfig) GenerateHash() {
194195
var b bytes.Buffer
195-
gob.NewEncoder(&b).Encode(*s)
196+
if err := gob.NewEncoder(&b).Encode(*s); err != nil {
197+
log.WithError(err).Error("unable to generate question has")
198+
}
196199

197200
h := sha256.New()
198201
h.Write(b.Bytes())

Diff for: api/surveys/custom_theme/questions.yaml

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
11
questions:
2-
- type: file
3-
label: Upload a Berlin Image
4-
validation:
5-
formats:
6-
- .jpg
7-
- .png
8-
max_size_bytes: 5*1024*1024 # 5 MB
92
- type: single-choice
103
id: question1 # optional ID, must be unique across all questions
114
label: What is the capital of Germany?
@@ -41,3 +34,10 @@ questions:
4134
optionsFromVariable: german-city-options
4235
- type: yes-no
4336
label: Is Berlin the capital of Germany?
37+
- type: file
38+
label: Upload a Berlin Image
39+
validation:
40+
formats:
41+
- .jpg
42+
- .png
43+
max_size_bytes: 5*1024*1024 # 5 MB

0 commit comments

Comments
 (0)