Skip to content

Commit

Permalink
Add github actions and linter
Browse files Browse the repository at this point in the history
  • Loading branch information
plutov committed Oct 18, 2024
1 parent fd04b0d commit 13ebc20
Show file tree
Hide file tree
Showing 13 changed files with 119 additions and 57 deletions.
52 changes: 49 additions & 3 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -1,18 +1,64 @@
name: Tests
on: [push]
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
lint:
name: Lint Go
runs-on: ubuntu-latest
steps:
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: 1.23

- name: Check out code
uses: actions/checkout@v4

- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: v1.60
working-directory: ./api

test:
name: Tests
name: Test Go
runs-on: ubuntu-latest
steps:
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: 1.23

- name: Check out code into the Go module directory
- name: Check out code
uses: actions/checkout@v4

- name: Run Tests
working-directory: ./api
run: go test -v -bench=. -race ./...

lint-ui:
name: Lint UI
runs-on: ubuntu-latest
strategy:
matrix:
node_version: [20]

steps:
- name: Check out code
uses: actions/checkout@v4

- name: Use Node.js ${{ matrix.node_version }}
uses: actions/setup-node@v4
with:
node_version: ${{ matrix.node_version }}

- name: run CI
working-directory: ./ui
run: |
npm install
npm run lint
2 changes: 1 addition & 1 deletion api/pkg/parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ func TestReadSurveys(t *testing.T) {
if err == nil {
t.Fatalf("expected error, got nil")
}
}
}
4 changes: 2 additions & 2 deletions api/pkg/services/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import (
)

type Services struct {
Storage storage.Interface
FileStorage storage.FileInterface
Storage storage.Interface
FileStorage storage.FileInterface
}

func InitServices() (Services, error) {
Expand Down
2 changes: 1 addition & 1 deletion api/pkg/storage/file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,4 @@ func TestSaveFile(t *testing.T) {
}
})
}
}
}
9 changes: 7 additions & 2 deletions api/pkg/storage/sqlite.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
migratepg "github.com/golang-migrate/migrate/v4/database/sqlite3"
_ "github.com/golang-migrate/migrate/v4/source/file"
"github.com/google/uuid"
"github.com/plutov/formulosity/api/pkg/log"
"github.com/plutov/formulosity/api/pkg/types"
)

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

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

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

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

return survey, nil
}
Expand Down
4 changes: 3 additions & 1 deletion api/pkg/surveys/sessions.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ func convertAnswerBytesToAnswerType(survey *types.Survey, answers []types.Questi
if err != nil {
log.WithError(err).Error("unable to get answer type")
} else {
json.Unmarshal(a.AnswerBytes, &answerType)
if err := json.Unmarshal(a.AnswerBytes, &answerType); err != nil {
log.WithError(err).Error("unable to decode answer")
}
answers[i].Answer = answerType
}

Expand Down
12 changes: 7 additions & 5 deletions api/pkg/surveys/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,17 @@ func SyncSurveysOnChange(svc services.Services) {

dir := os.Getenv("SURVEYS_DIR")

watcher.Add(dir)
if err := watcher.Add(dir); err != nil {
log.WithError(err).Error("unable to add watcher")
}

done := make(chan bool)
go func() {
for {
select {
case event := <-watcher.Events:
log.With("event", event).Info("file change event received")
SyncSurveys(svc)
event := <-watcher.Events
log.With("event", event).Info("file change event received")
if err := SyncSurveys(svc); err != nil {
log.WithError(err).Error("unable to sync surveys on file change")
}
}
}()
Expand Down
44 changes: 22 additions & 22 deletions api/pkg/types/answers.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,12 +187,12 @@ func (a *FileAnswer) Validate(q Question) error {

if q.Validation.MaxSizeBytes != nil {
bytes, err := GetStringMultiplication(*q.Validation.MaxSizeBytes)
if err != nil {
return fmt.Errorf("invalid MaxSizeBytes format: %v", err)
}
if a.FileSize > bytes {
return fmt.Errorf("file size exceeds the maximum size of %s", formatBytes(bytes))
}
if err != nil {
return fmt.Errorf("invalid MaxSizeBytes format: %v", err)
}
if a.FileSize > bytes {
return fmt.Errorf("file size exceeds the maximum size of %s", formatBytes(bytes))
}
} else {
return fmt.Errorf("questions[].validation.maxSizeBytes is required when questions[].type is file")
}
Expand All @@ -213,23 +213,23 @@ func (a *FileAnswer) Validate(q Question) error {
}

func formatBytes(bytes int64) string {
const (
KB = 1024
MB = KB * 1024
GB = MB * 1024
const (
KB = 1024
MB = KB * 1024
GB = MB * 1024
TB = GB * 1024
)
)

switch {
switch {
case bytes >= TB:
return fmt.Sprintf("%.2f TB", float64(bytes)/float64(TB))
case bytes >= GB:
return fmt.Sprintf("%.2f GB", float64(bytes)/float64(GB))
case bytes >= MB:
return fmt.Sprintf("%.2f MB", float64(bytes)/float64(MB))
case bytes >= KB:
return fmt.Sprintf("%.2f KB", float64(bytes)/float64(KB))
default:
return fmt.Sprintf("%d bytes", bytes)
}
}
case bytes >= GB:
return fmt.Sprintf("%.2f GB", float64(bytes)/float64(GB))
case bytes >= MB:
return fmt.Sprintf("%.2f MB", float64(bytes)/float64(MB))
case bytes >= KB:
return fmt.Sprintf("%.2f KB", float64(bytes)/float64(KB))
default:
return fmt.Sprintf("%d bytes", bytes)
}
}
1 change: 1 addition & 0 deletions api/pkg/types/answers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"strings"
"testing"
)

func ptrString(s string) *string {
return &s
}
Expand Down
10 changes: 5 additions & 5 deletions api/pkg/types/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package types
import "io"

type File struct {
Name string
Data io.Reader
Size int64
Format string
}
Name string
Data io.Reader
Size int64
Format string
}
17 changes: 10 additions & 7 deletions api/pkg/types/questions.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"fmt"
"strconv"
"strings"

"github.com/plutov/formulosity/api/pkg/log"
)

type QuestionType string
Expand Down Expand Up @@ -55,10 +57,10 @@ type Question struct {
}

type QuestionValidation struct {
Min *int `json:"min,omitempty" yaml:"min,omitempty"`
Max *int `json:"max,omitempty" yaml:"max,omitempty"`
Formats *[]string `json:"formats,omitempty" yaml:"formats,omitempty"`
MaxSizeBytes *string `json:"max_size_bytes,omitempty" yaml:"max_size_bytes,omitempty"`
Min *int `json:"min,omitempty" yaml:"min,omitempty"`
Max *int `json:"max,omitempty" yaml:"max,omitempty"`
Formats *[]string `json:"formats,omitempty" yaml:"formats,omitempty"`
MaxSizeBytes *string `json:"max_size_bytes,omitempty" yaml:"max_size_bytes,omitempty"`
}

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

func (q Question) GenerateHash() string {
var b bytes.Buffer
gob.NewEncoder(&b).Encode(q)
if err := gob.NewEncoder(&b).Encode(q); err != nil {
log.WithError(err).Error("unable to generate question has")
}

h := sha256.New()
h.Write(b.Bytes())
Expand Down Expand Up @@ -227,7 +231,6 @@ func (q Question) ValidateAnswer(answer interface{}) error {
return nil
}


func GetStringMultiplication(expression string) (int64, error) {
parts := strings.Split(expression, "*")

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

return int64(result), nil
}
}
5 changes: 4 additions & 1 deletion api/pkg/types/survey.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"time"

"github.com/microcosm-cc/bluemonday"
"github.com/plutov/formulosity/api/pkg/log"
)

const (
Expand Down Expand Up @@ -192,7 +193,9 @@ func (s *SurveyConfig) Normalize() {

func (s *SurveyConfig) GenerateHash() {
var b bytes.Buffer
gob.NewEncoder(&b).Encode(*s)
if err := gob.NewEncoder(&b).Encode(*s); err != nil {
log.WithError(err).Error("unable to generate question has")
}

h := sha256.New()
h.Write(b.Bytes())
Expand Down
14 changes: 7 additions & 7 deletions api/surveys/custom_theme/questions.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
questions:
- type: file
label: Upload a Berlin Image
validation:
formats:
- .jpg
- .png
max_size_bytes: 5*1024*1024 # 5 MB
- type: single-choice
id: question1 # optional ID, must be unique across all questions
label: What is the capital of Germany?
Expand Down Expand Up @@ -41,3 +34,10 @@ questions:
optionsFromVariable: german-city-options
- type: yes-no
label: Is Berlin the capital of Germany?
- type: file
label: Upload a Berlin Image
validation:
formats:
- .jpg
- .png
max_size_bytes: 5*1024*1024 # 5 MB

0 comments on commit 13ebc20

Please sign in to comment.