diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..f240a7b --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,41 @@ +name: Test & Lint Code + +on: + push: + branches: ["main"] + paths-ignore: + - ".github/**" + - ".githooks/**" + pull_request: + paths-ignore: + - ".github/**" + - ".githooks/**" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + test: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v3 + - name: Set up Go + uses: actions/setup-go@v4 + - name: Install Tools + run: make install + - name: Run Test + run: make test + + lint: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v3 + - name: Set up Go + uses: actions/setup-go@v4 + - name: Install Tools + run: make install + - name: Lint Go + run: make lint diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..3f111a0 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,129 @@ +linters-settings: + forbidigo: + forbid: + - ^print.*$ + dupl: + threshold: 100 + funlen: + lines: 30 + statements: 15 + goconst: + min-len: 2 + min-occurrences: 3 + gocritic: + enabled-tags: + - diagnostic + - experimental + - opinionated + - performance + - style + gocyclo: + min-complexity: 15 + gofmt: + rewrite-rules: + - pattern: "interface{}" + replacement: "any" + goimports: + local-prefixes: github.com/golangci/golangci-lint + gomnd: + # don't include the "operation" and "assign" + checks: + - argument + - case + - condition + - return + ignored-numbers: + - "0" + - "1" + - "2" + - "3" + ignored-functions: + - strings.SplitN + + govet: + check-shadowing: false + settings: + printf: + funcs: + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf + lll: + line-length: 89 + misspell: + locale: US + nolintlint: + allow-unused: true # report any unused nolint directives + require-explanation: false # don't require an explanation for nolint directives + require-specific: false # don't require nolint directives to be specific about which linter is being skipped + staticcheck: + checks: + - all + - "-SA1029" + +linters: + disable-all: true + enable: + - bodyclose + # - depguard + - dogsled + - dupl + - errcheck + - exportloopref + - funlen + - gochecknoinits + - goconst + - gocritic + - gocyclo + - gofmt + - goimports + - gomnd + - goprintffuncname + - gosec + - gosimple + - govet + - ineffassign + - lll + - misspell + - nakedret + - noctx + - nolintlint + - revive + - staticcheck + - stylecheck + - typecheck + - unconvert + - unparam + - unused + - whitespace + +issues: + # Excluding configuration per-path, per-linter, per-text and per-source + exclude-rules: + - path: _test\.go + linters: + - gomnd + - path: pkg/golinters/errcheck.go + text: "SA1019: errCfg.Exclude is deprecated: use ExcludeFunctions instead" + - path: pkg/commands/run.go + text: "SA1019: lsc.Errcheck.Exclude is deprecated: use ExcludeFunctions instead" + - path: pkg/commands/run.go + text: "SA1019: e.cfg.Run.Deadline is deprecated: Deadline exists for historical compatibility and should not be used." + - path: pkg/golinters/gofumpt.go + text: "SA1019: settings.LangVersion is deprecated: use the global `run.go` instead." + - path: pkg/golinters/staticcheck_common.go + text: "SA1019: settings.GoVersion is deprecated: use the global `run.go` instead." + - path: pkg/lint/lintersdb/manager.go + text: "SA1019: (.+).(GoVersion|LangVersion) is deprecated: use the global `run.go` instead." + - path: pkg/golinters/unused.go + text: "rangeValCopy: each iteration copies 160 bytes \\(consider pointers or indexing\\)" + - path: test/(fix|linters)_test.go + text: "string `gocritic.go` has 3 occurrences, make it a constant" + + fix: false + +run: + timeout: 5m + skip-dirs: + - gen diff --git a/common/files.go b/common/files.go index 73750c8..775a97c 100644 --- a/common/files.go +++ b/common/files.go @@ -6,7 +6,7 @@ import ( "os" ) -func WriteCsv(csvData [][]string, csvPath string) { +func WriteCSV(csvData [][]string, csvPath string) { f, err := os.Create(csvPath) if err != nil { panic(err) @@ -19,7 +19,7 @@ func WriteCsv(csvData [][]string, csvPath string) { } } -func ReadXml(xmlPath string) []byte { +func ReadXML(xmlPath string) []byte { xmlFile, err := os.Open(xmlPath) if err != nil { panic(err) diff --git a/main.go b/main.go index a39449d..d0c9dca 100644 --- a/main.go +++ b/main.go @@ -9,8 +9,18 @@ func main() { defaultInputPath := "./data/moly/readings.xml" defaultOutputPath := "./data/goodreads/readings.csv" - inputPath := flag.String("sourcefile", defaultInputPath, "Source moly.hu xml file location") - outputPath := flag.String("targetfile", defaultOutputPath, "Target goodreads csv file location") + inputPath := flag.String( + "sourcefile", + defaultInputPath, + "Source moly.hu xml file location", + ) + + outputPath := flag.String( + "targetfile", + defaultOutputPath, + "Target goodreads csv file location", + ) + flag.Parse() transformer.MolyToGoodReads( diff --git a/transformer/transformer.go b/transformer/transformer.go index b0d335d..f6d5548 100644 --- a/transformer/transformer.go +++ b/transformer/transformer.go @@ -6,46 +6,50 @@ import ( "moly-to-goodreads/common" ) -func MolyToGoodReads(molyXmlPath, goodReadsTargetCsvPath string) { - xmlData := common.ReadXml(molyXmlPath) +func MolyToGoodReads(molyXMLPath, goodReadsTargetCSVPath string) { + xmlData := common.ReadXML(molyXMLPath) molyData := parseMolyData(xmlData) goodReadsData := transform(molyData) - common.WriteCsv(goodReadsData, goodReadsTargetCsvPath) + common.WriteCSV(goodReadsData, goodReadsTargetCSVPath) } func transform(data MolyReads) [][]string { csvData := [][]string{} csvData = append(csvData, goodReadsHeaders) for i := 0; i < len(data.Readings); i++ { - reading := data.Readings[i] + csvData = append( + csvData, + transformReading(&data.Readings[i]), + ) + } - author := "" - title := reading.AuthorAndTitle - if strings.Contains(reading.AuthorAndTitle, ":") { - author = strings.Split(reading.AuthorAndTitle, ": ")[0] - title = strings.Split(reading.AuthorAndTitle, ": ")[1] - } + return csvData +} - createdAt := common.FormatDate(reading.CreatedAt) - finishedAt := common.FormatDate(reading.EndTime) +func transformReading(reading *Reading) []string { + author := "" + title := reading.AuthorAndTitle + if strings.Contains(reading.AuthorAndTitle, ":") { + author = strings.Split(reading.AuthorAndTitle, ": ")[0] + title = strings.Split(reading.AuthorAndTitle, ": ")[1] + } - shelves := createShelves(finishedAt) + createdAt := common.FormatDate(reading.CreatedAt) + finishedAt := common.FormatDate(reading.EndTime) - row := createCsvRow( - title, - author, - reading.Publisher, - reading.YearOfPublication, - finishedAt, - createdAt, - shelves, - ) - csvData = append(csvData, row) - } + shelves := createShelves(finishedAt) - return csvData + return createCsvRow( + title, + author, + reading.Publisher, + reading.YearOfPublication, + finishedAt, + createdAt, + shelves, + ) } func createShelves(finishedAt string) string { @@ -55,7 +59,14 @@ func createShelves(finishedAt string) string { return "read" } -func createCsvRow(title, author, publisher, yearOfPublication, finishedAt, createdAt, shelves string) []string { +func createCsvRow(title, + author, + publisher, + yearOfPublication, + finishedAt, + createdAt, + shelves string, +) []string { return []string{ title, author,