Skip to content

Commit

Permalink
ci: add golangci linter rules (#118)
Browse files Browse the repository at this point in the history
* ci: pre-job on Go workflow
* ci: always run Go coverage
  • Loading branch information
andreoliwa authored Dec 28, 2024
1 parent f737ea4 commit 7dfc21e
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 72 deletions.
4 changes: 2 additions & 2 deletions .github/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ coverage:
project:
default:
# Target coverage for the whole project https://docs.codecov.com/docs/commit-status#target
target: 50%
target: 75%

# Maximum decrease in coverage https://docs.codecov.com/docs/commit-status#threshold
threshold: 10%
threshold: 5%

patch:
default:
Expand Down
69 changes: 58 additions & 11 deletions .github/workflows/go.yaml
Original file line number Diff line number Diff line change
@@ -1,24 +1,71 @@
name: go
on: [push, pull_request]
on: push

jobs:
build:
# Adapted from https://github.com/marketplace/actions/skip-duplicate-actions
pre_job:
continue-on-error: true
runs-on: ubuntu-latest
# Map a step output to a job output
outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip }}
steps:
- id: skip_check
uses: fkirc/skip-duplicate-actions@v5
with:
# https://github.com/marketplace/actions/skip-duplicate-actions#skip-concurrent-workflow-runs
concurrent_skipping: "same_content_newer"
# https://github.com/marketplace/actions/skip-duplicate-actions#cancel_others
# Don't cancel other jobs, they might be pushes to master
cancel_others: false
# https://github.com/marketplace/actions/skip-duplicate-actions#do_not_skip
do_not_skip: '["workflow_dispatch", "schedule", "merge_group", "release"]'
# https://github.com/marketplace/actions/skip-duplicate-actions#paths
paths: '["go.*", "*.go", "cmd/**", "Cargo.*", "pyproject.toml", "python/**", "rust/**"]'

lint:
needs: pre_job
if: ${{ needs.pre_job.outputs.should_skip != 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: "stable"
- uses: golangci/golangci-lint-action@v6
with:
version: "v1.60"

test:
needs: pre_job
strategy:
matrix:
include:
- name: "ubuntu + coverage"
os: "ubuntu-latest"
go: "stable"
codecov: true
- name: "macos"
os: "macos-latest"
go: "stable"
- name: "windows"
os: "windows-latest"
go: "stable"
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
if: ${{ needs.pre_job.outputs.should_skip != 'true' || matrix.codecov }}
- uses: actions/setup-go@v5
if: ${{ needs.pre_job.outputs.should_skip != 'true' || matrix.codecov }}
with:
go-version: "1.21"
- name: Install richgo
run: |
go install github.com/kyoh86/richgo@latest
- name: Run tests and generate coverage data
run: |
make test-go-coverage
go-version: ${{ matrix.go }}
- name: Run tests with coverage
if: ${{ needs.pre_job.outputs.should_skip != 'true' || matrix.codecov }}
run: make test-go-coverage
env:
GO111MODULE: "auto"
- name: Upload coverage to CodeCov
if: ${{ matrix.codecov }}
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
2 changes: 1 addition & 1 deletion .github/workflows/maturin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
# https://github.com/marketplace/actions/skip-duplicate-actions#do_not_skip
do_not_skip: '["workflow_dispatch", "schedule", "merge_group", "release"]'
# https://github.com/marketplace/actions/skip-duplicate-actions#paths
paths: '["go.*", "*.go", "go/**", "Cargo.*", "pyproject.toml", "python/**", "rust/**"]'
paths: '["go.*", "*.go", "cmd/**", "Cargo.*", "pyproject.toml", "python/**", "rust/**"]'

linux:
needs: pre_job
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/tox.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: tox
on: [push]
on: push

jobs:
# Adapted from https://github.com/marketplace/actions/skip-duplicate-actions
Expand All @@ -21,7 +21,7 @@ jobs:
# https://github.com/marketplace/actions/skip-duplicate-actions#do_not_skip
do_not_skip: '["workflow_dispatch", "schedule", "merge_group", "release"]'
# https://github.com/marketplace/actions/skip-duplicate-actions#paths
paths: '["go.*", "*.go", "go/**", "Cargo.*", "pyproject.toml", "python/**", "rust/**"]'
paths: '["go.*", "*.go", "cmd/**", "Cargo.*", "pyproject.toml", "python/**", "rust/**"]'

test:
needs: pre_job
Expand Down
17 changes: 17 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# https://golangci-lint.run/usage/configuration/
linters:
enable-all: true
disable:
# keep-sorted start
- copyloopvar
- depguard
- exportloopref
- forbidigo
- gci
- gochecknoinits
- godox
- intrange
- ireturn
- paralleltest
- testpackage
# keep-sorted end
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@

Logseq Doctor: heal your flat old Markdown files before importing them.

**NOTE:** This project is still alpha, so it\'s very rough on the edges
(documentation and feature-wise).

At the moment, it has a Python package shipped with a Rust module, plus
an external Go executable with recent additions.

The long-term plan is to convert it to Go and slowly remove Rust and
Python. New features will be added to the Go executable only.
> [!NOTE]
> This project is still alpha, so it\'s very rough on the edges
> (documentation and feature-wise).
>
> At the moment, it has a Python package shipped with a Rust extension, plus
> an external Go executable with recent additions.
>
> The long-term plan is to convert it to Go and slowly remove Rust and
> Python. New features will be added to the Go executable only.
## Installation

Expand Down
6 changes: 3 additions & 3 deletions cmd/lsdg.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"github.com/spf13/cobra"
)

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
// rootCmd represents the base command when called without any subcommands.
var rootCmd = &cobra.Command{ //nolint:exhaustruct,gochecknoglobals
Use: "lsdg",
Short: "Logseq Doctor (Go) heals your Markdown files for Logseq",
Long: `Logseq Doctor (Go) heals your Markdown files for Logseq.
Expand Down Expand Up @@ -40,5 +40,5 @@ func init() {

// Cobra also supports local flags, which will only run
// when this action is called directly.
//rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
// rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
83 changes: 45 additions & 38 deletions cmd/tidy_up.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@ package cmd
import (
"context"
"fmt"
"github.com/andreoliwa/logseq-go"
"github.com/andreoliwa/logseq-go/content"
"github.com/spf13/cobra"
"log"
"os"
"sort"
"strings"

"github.com/andreoliwa/logseq-go"
"github.com/andreoliwa/logseq-go/content"
"github.com/spf13/cobra"
)

// tidyUpCmd represents the tidyUp command
var tidyUpCmd = &cobra.Command{
// tidyUpCmd represents the tidyUp command.
var tidyUpCmd = &cobra.Command{ //nolint:exhaustruct,gochecknoglobals
Use: "tidy-up",
Short: "Tidy up your Markdown files.",
Long: `Tidy up your Markdown files, checking for invalid content and fixing some of them automatically.
Expand All @@ -22,7 +23,7 @@ var tidyUpCmd = &cobra.Command{
- Check for running tasks (DOING)
- Check for double spaces`,
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
Run: func(_ *cobra.Command, args []string) {
dir := os.Getenv("LOGSEQ_GRAPH_PATH")
if dir == "" {
log.Fatalln("LOGSEQ_GRAPH_PATH environment variable is not set.")
Expand All @@ -32,7 +33,6 @@ var tidyUpCmd = &cobra.Command{
graph, err := logseq.Open(ctx, dir)
if err != nil {
log.Fatalln("error opening graph: %w", err)
return
}

exitCode := 0
Expand All @@ -43,11 +43,9 @@ var tidyUpCmd = &cobra.Command{
page, err := graph.OpenViaPath(path)
if err != nil {
log.Fatalf("%s: error opening file via path: %s\n", path, err)
return
}
if page == nil {
log.Fatalf("%s: error opening file via path: page is nil\n", path)
return
}

changes := make([]string, 0)
Expand All @@ -73,16 +71,6 @@ var tidyUpCmd = &cobra.Command{

func init() {
rootCmd.AddCommand(tidyUpCmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// tidyUpCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// tidyUpCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

// isValidMarkdownFile checks if a file is a Markdown file, by looking at its extension, not its content.
Expand All @@ -106,34 +94,40 @@ func isValidMarkdownFile(filePath string) bool {
// checkForbiddenReferences checks if a page has forbidden references to other pages or tags.
func checkForbiddenReferences(page logseq.Page) string {
all := make([]string, 0)

for _, block := range page.Blocks() {
block.Children().FilterDeep(func(n content.Node) bool {
var to string
var reference string
if pageLink, ok := n.(*content.PageLink); ok {
to = pageLink.To
reference = pageLink.To
} else if tag, ok := n.(*content.Hashtag); ok {
to = tag.To
reference = tag.To
}

// TODO: these values should be read from a config file or env var
forbidden := false
switch strings.ToLower(to) {

switch strings.ToLower(reference) {
case "quick capture":
forbidden = true
case "inbox":
forbidden = true
}

if forbidden {
all = append(all, to)
all = append(all, reference)
}

return false
})
}
count := len(all)
if count > 0 {

if count := len(all); count > 0 {
unique := sortAndRemoveDuplicates(all)

return fmt.Sprintf("remove %d forbidden references to pages/tags: %s", count, strings.Join(unique, ", "))
}

return ""
}

Expand All @@ -144,9 +138,11 @@ func sortAndRemoveDuplicates(elements []string) []string {
for _, element := range elements {
if !seen[element] {
seen[element] = true

uniqueElements = append(uniqueElements, element)
}
}

sort.Strings(uniqueElements)

return uniqueElements
Expand All @@ -155,51 +151,62 @@ func sortAndRemoveDuplicates(elements []string) []string {
// checkRunningTasks checks if a page has running tasks (DOING, etc.).
func checkRunningTasks(page logseq.Page) string {
all := make([]string, 0)

for _, block := range page.Blocks() {
block.Children().FilterDeep(func(n content.Node) bool {
if task, ok := n.(*content.TaskMarker); ok {
s := task.Status
// TODO: the conversion from a task status to the "DOING"/"IN-PROGRESS" strings should be done in logseq-go
if s == content.TaskStatusDoing {
status := task.Status
// TODO: convert to strings "DOING"/"IN-PROGRESS" in logseq-go
if status == content.TaskStatusDoing {
all = append(all, "DOING")
}
if s == content.TaskStatusInProgress {

if status == content.TaskStatusInProgress {
all = append(all, "IN-PROGRESS")
}
}

return false
})
}
count := len(all)
if count > 0 {

if count := len(all); count > 0 {
unique := sortAndRemoveDuplicates(all)

return fmt.Sprintf("stop %d running task(s): %s", count, strings.Join(unique, ", "))
}

return ""
}

func checkDoubleSpaces(page logseq.Page) string {
all := make([]string, 0)

for _, block := range page.Blocks() {
block.Children().FilterDeep(func(n content.Node) bool {
block.Children().FilterDeep(func(node content.Node) bool {
var value string
if text, ok := n.(*content.Text); ok {

if text, ok := node.(*content.Text); ok {
value = text.Value
} else if pageLink, ok := n.(*content.PageLink); ok {
} else if pageLink, ok := node.(*content.PageLink); ok {
value = pageLink.To
} else if tag, ok := n.(*content.Hashtag); ok {
} else if tag, ok := node.(*content.Hashtag); ok {
value = tag.To
}

if strings.Contains(value, " ") {
all = append(all, fmt.Sprintf("'%s'", value))
}

return false
})
}
count := len(all)
if count > 0 {

if count := len(all); count > 0 {
unique := sortAndRemoveDuplicates(all)

return fmt.Sprintf("%d double spaces: %s", count, strings.Join(unique, ", "))
}

return ""
}
Loading

0 comments on commit 7dfc21e

Please sign in to comment.