From dec5b8c7b2f1fef145f1aa827f67f29aaab2ccad Mon Sep 17 00:00:00 2001 From: Tiago Angelo Date: Thu, 28 Aug 2025 17:07:54 -0300 Subject: [PATCH 01/15] Correct pointer value handling for slices --- _test/testdata/bar/types.go | 9 +++++---- internal/scan/fld/finder.go | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/_test/testdata/bar/types.go b/_test/testdata/bar/types.go index 39d8912..503a3f9 100644 --- a/_test/testdata/bar/types.go +++ b/_test/testdata/bar/types.go @@ -7,10 +7,11 @@ import ( ) type Quux struct { - Id string `json:"Id"` - Name string `json:"Name"` - Quuz Quuz `json:"Quuz"` - Status string `json:"Status"` + Id string `json:"Id"` + Name string `json:"Name"` + Quuz Quuz `json:"Quuz"` + Status string `json:"Status"` + Numbers *[]int `json:"Numbers"` } type Quuz struct { diff --git a/internal/scan/fld/finder.go b/internal/scan/fld/finder.go index f51137e..24b19c7 100644 --- a/internal/scan/fld/finder.go +++ b/internal/scan/fld/finder.go @@ -78,7 +78,7 @@ func (f *Finder) buildField(expr ast.Expr, st *projscan.Struct, proj *projscan.P Type: field.Type, Doc: field.Doc, StructRef: field.StructRef, - Pointer: false, + Pointer: field.Pointer, Array: true, ArrayPointer: field.Pointer, }) From 003f833ef3e8cda14c2dd7e74ddee87026136914 Mon Sep 17 00:00:00 2001 From: Tiago Angelo Date: Thu, 28 Aug 2025 17:10:41 -0300 Subject: [PATCH 02/15] Replace "golang.org/x/exp/slog" with "log/slog" --- internal/scan/st/finder.go | 3 ++- main.go | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/scan/st/finder.go b/internal/scan/st/finder.go index 54aa4a8..cadfbe6 100644 --- a/internal/scan/st/finder.go +++ b/internal/scan/st/finder.go @@ -3,11 +3,12 @@ package st import ( "go/ast" + "log/slog" + "github.com/cloud104/pflagstruct/internal/dir" "github.com/cloud104/pflagstruct/internal/syntree" "github.com/cloud104/pflagstruct/projscan" "github.com/pkg/errors" - "golang.org/x/exp/slog" ) // Finder is a struct that represents a Go struct type finder. diff --git a/main.go b/main.go index 7ec3ff3..af24f9c 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "fmt" "go/token" + "log/slog" "os" "time" @@ -12,7 +13,6 @@ import ( "github.com/lmittmann/tint" "github.com/pkg/errors" "github.com/spf13/cobra" - "golang.org/x/exp/slog" "github.com/cloud104/pflagstruct/internal/code" scanfld "github.com/cloud104/pflagstruct/internal/scan/fld" From bc7b0439fb3a2da0bf881dee0b144dcd889852e8 Mon Sep 17 00:00:00 2001 From: Tiago Angelo Date: Thu, 28 Aug 2025 17:10:58 -0300 Subject: [PATCH 03/15] Update Go version and dependencies in go.mod files --- _test/testdata/go.mod | 2 +- go.mod | 25 +++++++++++----------- go.sum | 50 +++++++++++++++++++++++-------------------- 3 files changed, 41 insertions(+), 36 deletions(-) diff --git a/_test/testdata/go.mod b/_test/testdata/go.mod index f1b39dc..49c823c 100644 --- a/_test/testdata/go.mod +++ b/_test/testdata/go.mod @@ -1,6 +1,6 @@ module github.com/cloud104/pflagstruct/_test/testdata -go 1.20 +go 1.25.0 require github.com/apirator/apirator v1.0.1 diff --git a/go.mod b/go.mod index a2b961b..cf3f22f 100644 --- a/go.mod +++ b/go.mod @@ -1,21 +1,20 @@ module github.com/cloud104/pflagstruct -go 1.20 +go 1.25.0 require ( - github.com/dave/jennifer v1.6.1 + github.com/dave/jennifer v1.7.1 github.com/enescakir/emoji v1.0.0 github.com/go-ozzo/ozzo-validation/v4 v4.3.0 - github.com/gookit/color v1.5.3 + github.com/gookit/color v1.6.0 github.com/ku/go-change-case v0.0.1 - github.com/lmittmann/tint v0.3.4 + github.com/lmittmann/tint v1.1.2 github.com/pkg/errors v0.9.1 - github.com/samber/lo v1.38.1 - github.com/spf13/cobra v1.7.0 - github.com/stretchr/testify v1.8.4 - github.com/wk8/go-ordered-map/v2 v2.1.7 - golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 - golang.org/x/mod v0.11.0 + github.com/samber/lo v1.51.0 + github.com/spf13/cobra v1.9.1 + github.com/stretchr/testify v1.11.1 + github.com/wk8/go-ordered-map/v2 v2.1.8 + golang.org/x/mod v0.27.0 ) require ( @@ -25,8 +24,10 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/pflag v1.0.6 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - golang.org/x/sys v0.9.0 // indirect + golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index e357c1a..8848c12 100644 --- a/go.sum +++ b/go.sum @@ -4,9 +4,9 @@ github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPn github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/dave/jennifer v1.6.1 h1:T4T/67t6RAA5AIV6+NP8Uk/BIsXgDoqEowgycdQQLuk= -github.com/dave/jennifer v1.6.1/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/dave/jennifer v1.7.1 h1:B4jJJDHelWcDhlRQxWeo0Npa/pYKBLrirAQoTN45txo= +github.com/dave/jennifer v1.7.1/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -14,15 +14,17 @@ github.com/enescakir/emoji v1.0.0 h1:W+HsNql8swfCQFtioDGDHCHri8nudlK1n5p2rHCJoog github.com/enescakir/emoji v1.0.0/go.mod h1:Bt1EKuLnKDTYpLALApstIkAjdDrS/8IAgTkKp+WKFD0= github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es= github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew= -github.com/gookit/color v1.5.3 h1:twfIhZs4QLCtimkP7MOxlF3A0U/5cDPseRT9M/+2SCE= -github.com/gookit/color v1.5.3/go.mod h1:NUzwzeehUfl7GIb36pqId+UGmRfQcU/WiiyTTeNjHtE= +github.com/gookit/assert v0.1.1 h1:lh3GcawXe/p+cU7ESTZ5Ui3Sm/x8JWpIis4/1aF0mY0= +github.com/gookit/assert v0.1.1/go.mod h1:jS5bmIVQZTIwk42uXl4lyj4iaaxx32tqH16CFj0VX2E= +github.com/gookit/color v1.6.0 h1:JjJXBTk1ETNyqyilJhkTXJYYigHG24TM9Xa2M1xAhRA= +github.com/gookit/color v1.6.0/go.mod h1:9ACFc7/1IpHGBW8RwuDm/0YEnhg3dwwXpoMsmtyHfjs= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/ku/go-change-case v0.0.1 h1:Dym6yulm/ma+XRgH1SG2CIOLk2biWpSFf6mMPtg3ic8= github.com/ku/go-change-case v0.0.1/go.mod h1:7rNOPNKPrCdjm8+iDIKgs87tZuyPJkhnStQZIOT3Pss= -github.com/lmittmann/tint v0.3.4 h1:QOr2U9GKQfNsNhKPhL7PexQm0mqkRmvuy1UrZb6AidM= -github.com/lmittmann/tint v0.3.4/go.mod h1:vYasuAV5qbz2TYeUK+sj8iURGIl9T/WOlh4qzYGP16I= +github.com/lmittmann/tint v1.1.2 h1:2CQzrL6rslrsyjqLDwD11bZ5OpLBPU+g3G/r5LSfS8w= +github.com/lmittmann/tint v1.1.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -30,26 +32,28 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= -github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/samber/lo v1.51.0 h1:kysRYLbHy/MB7kQZf5DSN50JHmMsNEdeY24VzJFu7wI= +github.com/samber/lo v1.51.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= +github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= +github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/wk8/go-ordered-map/v2 v2.1.7 h1:aUZ1xBMdbvY8wnNt77qqo4nyT3y0pX4Usat48Vm+hik= -github.com/wk8/go-ordered-map/v2 v2.1.7/go.mod h1:9Xvgm2mV2kSq2SAm0Y608tBmu8akTzI7c2bz7/G7ZN4= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= +github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= -golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= -golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0= +golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From 0bf1f780a017d9ce2ee074eb0d832e9114ce21c2 Mon Sep 17 00:00:00 2001 From: Tiago Angelo Date: Thu, 28 Aug 2025 17:13:45 -0300 Subject: [PATCH 04/15] Add Makefile with build, test, install commands --- Makefile | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9d47e15 --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +SHELL = /usr/bin/env bash -o pipefail +.SHELLFLAGS = -ec + +.PHONY: help +help: ## Display this help. + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + +##@ Build + +.PHONY: build +build: ## Compiles the source code. + go build ./... + +.PHONY: test +test: ## Run all unit tests. + go test ./... + +.PHONY: install +install: ## Build and install the binary + go install ./... From c5002f80b5e13f31dffeddd53a050c42c00c16f9 Mon Sep 17 00:00:00 2001 From: Tiago Angelo Date: Thu, 28 Aug 2025 17:29:53 -0300 Subject: [PATCH 05/15] Add project structure description to README.md --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index d2e8ec9..1986781 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,16 @@ The CLI provides the following flags: Feel free to explore the available flags and experiment with different options to generate code based on your struct definitions. +## How the Project Is Built + +The project is structured into modular internal packages, each with a specific responsibility: + +* `internal/scan/` → scans Go code for struct definitions, fields, packages, and projects. +* `internal/code/` → generates Go code ([`jen` library](https://github.com/dave/jennifer) is used to programmatically build Go ASTs). +* `internal/dir/` → handles filesystem paths. +* `projscan/` → defines core types (`Struct`, `Field`, `Package`, etc.) used in scanning and generation. +* `main.go` → CLI entrypoint, built with `cobra`. + ## Contributing Contributions to the pflagstruct are welcome! If you find any issues or have suggestions for improvement, From b0db8182eec071e5051412ca457a754170c5318b Mon Sep 17 00:00:00 2001 From: Tiago Angelo Date: Thu, 28 Aug 2025 17:41:08 -0300 Subject: [PATCH 06/15] Update Makefile to include build and install flags --- Makefile | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 9d47e15..11018f0 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,11 @@ SHELL = /usr/bin/env bash -o pipefail .SHELLFLAGS = -ec +BIN := pflagstruct +OUTDIR := bin +GO := go +LDFLAGS := -s -w + .PHONY: help help: ## Display this help. @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) @@ -9,12 +14,12 @@ help: ## Display this help. .PHONY: build build: ## Compiles the source code. - go build ./... + $(GO) build -trimpath -ldflags '$(LDFLAGS)' -o $(OUTDIR)/$(BIN) . .PHONY: test test: ## Run all unit tests. - go test ./... + $(GO) test ./... .PHONY: install install: ## Build and install the binary - go install ./... + $(GO) install -trimpath -ldflags '$(LDFLAGS)' . From 29dba69c2fa50944c1a2ea60269d1f040662b9bc Mon Sep 17 00:00:00 2001 From: Tiago Angelo Date: Thu, 28 Aug 2025 18:06:28 -0300 Subject: [PATCH 07/15] Add Go Test workflow for pull requests on main branch --- .github/workflows/go-test.yml | 47 +++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .github/workflows/go-test.yml diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml new file mode 100644 index 0000000..51f7a19 --- /dev/null +++ b/.github/workflows/go-test.yml @@ -0,0 +1,47 @@ +name: Go Test + +on: + pull_request: + branches: [ "main" ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + pull-requests: read + +jobs: + test: + runs-on: tks-gha-runner + + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + cache: true + + - name: Verify modules + run: | + go mod tidy + git diff --exit-code -- go.mod go.sum || (echo "Run 'go mod tidy' locally" && exit 1) + + - name: Format + run: | + go fmt ./... + git diff --exit-code || (echo "Run 'go fmt ./...' locally" && exit 1) + + - name: Vet + run: go vet ./... + + - name: Test + run: go test -race ./... + + - name: Build + run: | + go build -trimpath -ldflags '-s -w' . From 1037570a16694f5679ed62b9e5166ce36705fb54 Mon Sep 17 00:00:00 2001 From: Tiago Angelo Date: Thu, 28 Aug 2025 18:18:43 -0300 Subject: [PATCH 08/15] Update GitHub Actions to run on ubuntu-latest --- .github/workflows/go-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml index 51f7a19..d061771 100644 --- a/.github/workflows/go-test.yml +++ b/.github/workflows/go-test.yml @@ -14,7 +14,7 @@ permissions: jobs: test: - runs-on: tks-gha-runner + runs-on: ubuntu-latest steps: - name: Checkout From f42357abd3de3999da3b30f70a6b10b7e6d49e82 Mon Sep 17 00:00:00 2001 From: Tiago Angelo Date: Thu, 28 Aug 2025 18:34:13 -0300 Subject: [PATCH 09/15] Set GOPATH for go tests in GitHub actions --- .github/workflows/go-test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml index d061771..e1fd136 100644 --- a/.github/workflows/go-test.yml +++ b/.github/workflows/go-test.yml @@ -39,6 +39,9 @@ jobs: - name: Vet run: go vet ./... + - name: Set GOPATH for Test + run: echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV + - name: Test run: go test -race ./... From 149c73eba34ec83c9866f1c37316d1af415ca30b Mon Sep 17 00:00:00 2001 From: Tiago Angelo Date: Fri, 29 Aug 2025 10:56:24 -0300 Subject: [PATCH 10/15] Add goenv package to handle Go environment variables --- internal/goenv/getter.go | 23 +++++++++++++++++++++++ internal/scan/pkg/wrappers.go | 9 ++++----- internal/scan/proj/mod.go | 13 +++++++------ 3 files changed, 34 insertions(+), 11 deletions(-) create mode 100644 internal/goenv/getter.go diff --git a/internal/goenv/getter.go b/internal/goenv/getter.go new file mode 100644 index 0000000..653cd5b --- /dev/null +++ b/internal/goenv/getter.go @@ -0,0 +1,23 @@ +package goenv + +import ( + "os/exec" + "strings" + + "github.com/pkg/errors" +) + +// Get retrieves the value of a Go environment variable +func Get(key string) (string, error) { + out, err := exec.Command("go", "env", key).Output() + if err != nil { + return "", errors.Wrapf(err, "failed to get Go env variable %q", key) + } + + value := strings.TrimSpace(string(out)) + if value == "" { + return "", errors.Errorf("Go env variable %q is empty", key) + } + + return value, nil +} diff --git a/internal/scan/pkg/wrappers.go b/internal/scan/pkg/wrappers.go index 75ebd6e..0c7a284 100644 --- a/internal/scan/pkg/wrappers.go +++ b/internal/scan/pkg/wrappers.go @@ -1,12 +1,11 @@ package pkg import ( - "os" "path" "strings" + "github.com/cloud104/pflagstruct/internal/goenv" "github.com/cloud104/pflagstruct/projscan" - "github.com/pkg/errors" ) // pkgListWrapper is a wrapper struct for a list of packages. @@ -68,9 +67,9 @@ func (w *projAndPkgWrapper) getPackageDirectory() (string, error) { return replacePrefix(w.pkgpath, dep.Path, dep.Directory), nil } - goroot, ok := os.LookupEnv("GOROOT") - if !ok { - return "", errors.New(`the environment variable GOROOT has not been configured`) + goroot, err := goenv.Get("GOROOT") + if err != nil { + return "", err } return path.Join(goroot, "src", w.pkgpath), nil diff --git a/internal/scan/proj/mod.go b/internal/scan/proj/mod.go index 603569a..0f8478d 100644 --- a/internal/scan/proj/mod.go +++ b/internal/scan/proj/mod.go @@ -1,13 +1,14 @@ package proj import ( - "os" "path" - "github.com/cloud104/pflagstruct/internal/dir" - "github.com/cloud104/pflagstruct/projscan" "github.com/pkg/errors" "golang.org/x/mod/modfile" + + "github.com/cloud104/pflagstruct/internal/dir" + "github.com/cloud104/pflagstruct/internal/goenv" + "github.com/cloud104/pflagstruct/projscan" ) type Module struct { @@ -55,9 +56,9 @@ func (m *Module) Directory() string { // Dependencies returns a list of dependencies for the module, or an error if they cannot be determined. func (m *Module) Dependencies() ([]*projscan.Dependency, error) { - gopath, ok := os.LookupEnv("GOPATH") - if !ok { - return nil, errors.New(`the environment variable GOPATH has not been configured`) + gopath, err := goenv.Get("GOPATH") + if err != nil { + return nil, err } dependencies := make([]*projscan.Dependency, 0) From ecb360392162d1a89e92e675eeb65b272babdefb Mon Sep 17 00:00:00 2001 From: Tiago Angelo Date: Fri, 29 Aug 2025 10:56:40 -0300 Subject: [PATCH 11/15] Remove GOPATH setting in GitHub workflows --- .github/workflows/go-test.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml index e1fd136..d061771 100644 --- a/.github/workflows/go-test.yml +++ b/.github/workflows/go-test.yml @@ -39,9 +39,6 @@ jobs: - name: Vet run: go vet ./... - - name: Set GOPATH for Test - run: echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV - - name: Test run: go test -race ./... From 5563256a36533795f7fe6de5b4acaabd999bb922 Mon Sep 17 00:00:00 2001 From: Tiago Angelo Date: Fri, 29 Aug 2025 11:03:48 -0300 Subject: [PATCH 12/15] Add func to get source path from package --- internal/goenv/list.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 internal/goenv/list.go diff --git a/internal/goenv/list.go b/internal/goenv/list.go new file mode 100644 index 0000000..f0d4a61 --- /dev/null +++ b/internal/goenv/list.go @@ -0,0 +1,25 @@ +package goenv + +import ( + "bytes" + "os/exec" + "strings" + + "github.com/pkg/errors" +) + +// GoListDir runs "go list -f '{{.Dir}}' " and returns the source path. +func GoListDir(pkg string) (string, error) { + cmd := exec.Command("go", "list", "-f", "{{.Dir}}", pkg) + + var out bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &out + + err := cmd.Run() + if err != nil { + return "", errors.Errorf("failed to run go list: %v, output: %s", err, out.String()) + } + + return strings.TrimSpace(out.String()), nil +} From aced905cadf9b208cd7ade900d0c0550dcae2237 Mon Sep 17 00:00:00 2001 From: Tiago Angelo Date: Fri, 29 Aug 2025 11:18:53 -0300 Subject: [PATCH 13/15] Add tests for goenv Get and GoListDir functions --- internal/goenv/getter_test.go | 42 +++++++++++++++++++++++++++++ internal/goenv/list_test.go | 50 +++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 internal/goenv/getter_test.go create mode 100644 internal/goenv/list_test.go diff --git a/internal/goenv/getter_test.go b/internal/goenv/getter_test.go new file mode 100644 index 0000000..25ba3a0 --- /dev/null +++ b/internal/goenv/getter_test.go @@ -0,0 +1,42 @@ +package goenv + +import "testing" + +func TestGet(t *testing.T) { + type args struct { + key string + } + + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "valid GOVERSION", + args: args{key: "GOVERSION"}, + want: "go1.25.0", + wantErr: false, + }, + { + name: "invalid key returns error", + args: args{key: "__THIS_GO_ENV_KEY_DOES_NOT_EXIST__"}, + want: "", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := Get(tt.args.key) + if (err != nil) != tt.wantErr { + t.Errorf("Get() error = %v, wantErr %v", err, tt.wantErr) + return + } + + if !tt.wantErr && got != tt.want { + t.Errorf("Get() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/goenv/list_test.go b/internal/goenv/list_test.go new file mode 100644 index 0000000..297e102 --- /dev/null +++ b/internal/goenv/list_test.go @@ -0,0 +1,50 @@ +package goenv + +import ( + path "path" + "testing" +) + +func TestGoListDir(t *testing.T) { + goroot, err := Get("GOROOT") + if err != nil { + t.Fatalf("failed to retrieve GOROOT using go env: %v", err) + } + + type args struct { + pkg string + } + + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "stdlib package fmt", + args: args{pkg: "fmt"}, + want: path.Join(goroot, "src/fmt"), + wantErr: false, + }, + { + name: "nonexistent package returns error", + args: args{pkg: "not/a/real/package/definitelynot"}, + want: "", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GoListDir(tt.args.pkg) + if (err != nil) != tt.wantErr { + t.Errorf("GoListDir() error = %v, wantErr %v", err, tt.wantErr) + return + } + + if !tt.wantErr && got != tt.want { + t.Errorf("GoListDir() got = %v, want %v", got, tt.want) + } + }) + } +} From 9826a9ccb369696c1e303eac162eaaa11ccb65e5 Mon Sep 17 00:00:00 2001 From: Tiago Angelo Date: Fri, 29 Aug 2025 11:19:17 -0300 Subject: [PATCH 14/15] Rename GoListDir function to ListDir --- internal/goenv/list.go | 4 ++-- internal/goenv/list_test.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/goenv/list.go b/internal/goenv/list.go index f0d4a61..27bea54 100644 --- a/internal/goenv/list.go +++ b/internal/goenv/list.go @@ -8,8 +8,8 @@ import ( "github.com/pkg/errors" ) -// GoListDir runs "go list -f '{{.Dir}}' " and returns the source path. -func GoListDir(pkg string) (string, error) { +// ListDir runs "go list -f '{{.Dir}}' " and returns the source path. +func ListDir(pkg string) (string, error) { cmd := exec.Command("go", "list", "-f", "{{.Dir}}", pkg) var out bytes.Buffer diff --git a/internal/goenv/list_test.go b/internal/goenv/list_test.go index 297e102..085adbb 100644 --- a/internal/goenv/list_test.go +++ b/internal/goenv/list_test.go @@ -36,14 +36,14 @@ func TestGoListDir(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := GoListDir(tt.args.pkg) + got, err := ListDir(tt.args.pkg) if (err != nil) != tt.wantErr { - t.Errorf("GoListDir() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("ListDir() error = %v, wantErr %v", err, tt.wantErr) return } if !tt.wantErr && got != tt.want { - t.Errorf("GoListDir() got = %v, want %v", got, tt.want) + t.Errorf("ListDir() got = %v, want %v", got, tt.want) } }) } From 498a9047d0ab13fdb269dcfb8876365d1812dee7 Mon Sep 17 00:00:00 2001 From: Tiago Angelo Date: Fri, 29 Aug 2025 11:32:47 -0300 Subject: [PATCH 15/15] Update go-test workflow to download all dependencies --- .github/workflows/go-test.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml index d061771..f160651 100644 --- a/.github/workflows/go-test.yml +++ b/.github/workflows/go-test.yml @@ -25,6 +25,13 @@ jobs: with: go-version-file: 'go.mod' cache: true + cache-dependency-path: | + go.sum + _test/testdata/go.sum + + - name: Download dependencies + run: | + find . -name go.mod -not -path '*/vendor/*' -execdir go mod download \; - name: Verify modules run: |