Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cdd066dafe | ||
|
|
5c25f333b7 | ||
|
|
77e6e72f5a | ||
|
|
4d4bc09b86 |
@@ -23,10 +23,16 @@ jobs:
|
|||||||
- name: go vet
|
- name: go vet
|
||||||
run: go vet ./...
|
run: go vet ./...
|
||||||
|
|
||||||
- name: gofumpt (golangci-lint fmt)
|
- name: Install lint tools
|
||||||
run: |
|
run: |
|
||||||
go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest
|
go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest
|
||||||
diff=$(golangci-lint fmt --diff 2>&1)
|
go install honnef.co/go/tools/cmd/staticcheck@latest
|
||||||
|
go install golang.org/x/vuln/cmd/govulncheck@latest
|
||||||
|
echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH"
|
||||||
|
|
||||||
|
- name: gofumpt (golangci-lint fmt)
|
||||||
|
run: |
|
||||||
|
diff=$(golangci-lint fmt --diff)
|
||||||
if [ -n "$diff" ]; then
|
if [ -n "$diff" ]; then
|
||||||
echo "$diff"
|
echo "$diff"
|
||||||
echo "Formatting issues found. Run: make fmt"
|
echo "Formatting issues found. Run: make fmt"
|
||||||
@@ -34,14 +40,10 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: staticcheck
|
- name: staticcheck
|
||||||
run: |
|
run: staticcheck ./...
|
||||||
go install honnef.co/go/tools/cmd/staticcheck@latest
|
|
||||||
staticcheck ./...
|
|
||||||
|
|
||||||
- name: govulncheck
|
- name: govulncheck
|
||||||
run: |
|
run: govulncheck ./...
|
||||||
go install golang.org/x/vuln/cmd/govulncheck@latest
|
|
||||||
govulncheck ./...
|
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: go test ./...
|
run: go test ./...
|
||||||
|
|||||||
@@ -14,9 +14,10 @@ GOGET=$(GOCMD) get
|
|||||||
GOMOD=$(GOCMD) mod
|
GOMOD=$(GOCMD) mod
|
||||||
GOCLEAN=$(GOCMD) clean
|
GOCLEAN=$(GOCMD) clean
|
||||||
|
|
||||||
# Resolve Go tool binaries (GOPATH/bin may not be on PATH in CI)
|
# Tool versions (compiled on demand via `go run` so they match the local toolchain)
|
||||||
GOBIN_DIR := $(shell $(GOCMD) env GOPATH)/bin
|
GOLANGCI_LINT = go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest
|
||||||
TOOL = $(if $(shell command -v $(1) 2>/dev/null),$(1),$(GOBIN_DIR)/$(1))
|
STATICCHECK = go run honnef.co/go/tools/cmd/staticcheck@latest
|
||||||
|
GOVULNCHECK = go run golang.org/x/vuln/cmd/govulncheck@latest
|
||||||
|
|
||||||
# Version information
|
# Version information
|
||||||
VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
|
VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
|
||||||
@@ -53,24 +54,20 @@ vet: ## Run go vet
|
|||||||
|
|
||||||
fmt: ## Format code (gofumpt + goimports via golangci-lint)
|
fmt: ## Format code (gofumpt + goimports via golangci-lint)
|
||||||
@echo "Formatting..."
|
@echo "Formatting..."
|
||||||
@command -v golangci-lint > /dev/null || test -x $(GOBIN_DIR)/golangci-lint || $(GOCMD) install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest
|
$(GOLANGCI_LINT) fmt --config=.golangci.json
|
||||||
$(call TOOL,golangci-lint) fmt --config=.golangci.json
|
|
||||||
|
|
||||||
fmt-check: ## Check formatting (gofumpt + goimports via golangci-lint)
|
fmt-check: ## Check formatting (gofumpt + goimports via golangci-lint)
|
||||||
@echo "Checking formatting..."
|
@echo "Checking formatting..."
|
||||||
@command -v golangci-lint > /dev/null || test -x $(GOBIN_DIR)/golangci-lint || $(GOCMD) install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest
|
@diff=$$($(GOLANGCI_LINT) fmt --diff --config=.golangci.json); \
|
||||||
@diff=$$($(call TOOL,golangci-lint) fmt --diff --config=.golangci.json 2>&1); \
|
|
||||||
if [ -n "$$diff" ]; then echo "$$diff"; echo "Run: make fmt"; exit 1; fi
|
if [ -n "$$diff" ]; then echo "$$diff"; echo "Run: make fmt"; exit 1; fi
|
||||||
|
|
||||||
staticcheck: ## Run staticcheck
|
staticcheck: ## Run staticcheck
|
||||||
@echo "Running staticcheck..."
|
@echo "Running staticcheck..."
|
||||||
@command -v staticcheck > /dev/null || test -x $(GOBIN_DIR)/staticcheck || $(GOCMD) install honnef.co/go/tools/cmd/staticcheck@latest
|
$(STATICCHECK) ./...
|
||||||
$(call TOOL,staticcheck) ./...
|
|
||||||
|
|
||||||
govulncheck: ## Run govulncheck
|
govulncheck: ## Run govulncheck
|
||||||
@echo "Running govulncheck..."
|
@echo "Running govulncheck..."
|
||||||
@command -v govulncheck > /dev/null || test -x $(GOBIN_DIR)/govulncheck || $(GOCMD) install golang.org/x/vuln/cmd/govulncheck@latest
|
$(GOVULNCHECK) ./...
|
||||||
$(call TOOL,govulncheck) ./...
|
|
||||||
|
|
||||||
build: deps ## Build the binary
|
build: deps ## Build the binary
|
||||||
@echo "Building $(BINARY_NAME) $(VERSION)..."
|
@echo "Building $(BINARY_NAME) $(VERSION)..."
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module git.warky.dev/wdevs/relspecgo
|
module git.warky.dev/wdevs/relspecgo
|
||||||
|
|
||||||
go 1.25.7
|
go 1.25.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gdamore/tcell/v2 v2.13.9
|
github.com/gdamore/tcell/v2 v2.13.9
|
||||||
|
|||||||
@@ -445,21 +445,21 @@ type (
|
|||||||
SqlUUID = SqlNull[uuid.UUID]
|
SqlUUID = SqlNull[uuid.UUID]
|
||||||
)
|
)
|
||||||
|
|
||||||
// SqlTimeStamp - Timestamp with custom formatting (YYYY-MM-DDTHH:MM:SS).
|
// SqlTimeStamp - Timestamp serialized as RFC3339.
|
||||||
type SqlTimeStamp struct{ SqlNull[time.Time] }
|
type SqlTimeStamp struct{ SqlNull[time.Time] }
|
||||||
|
|
||||||
func (t SqlTimeStamp) MarshalJSON() ([]byte, error) {
|
func (t SqlTimeStamp) MarshalJSON() ([]byte, error) {
|
||||||
if !t.Valid || t.Val.IsZero() || t.Val.Before(time.Date(0o002, 1, 1, 0, 0, 0, 0, time.UTC)) {
|
if !t.Valid || t.Val.IsZero() || t.Val.Before(time.Date(0o002, 1, 1, 0, 0, 0, 0, time.UTC)) {
|
||||||
return []byte("null"), nil
|
return []byte("null"), nil
|
||||||
}
|
}
|
||||||
return fmt.Appendf(nil, `"%s"`, t.Val.Format("2006-01-02T15:04:05")), nil
|
return fmt.Appendf(nil, `"%s"`, t.Val.Format(time.RFC3339)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *SqlTimeStamp) UnmarshalJSON(b []byte) error {
|
func (t *SqlTimeStamp) UnmarshalJSON(b []byte) error {
|
||||||
if err := t.SqlNull.UnmarshalJSON(b); err != nil {
|
if err := t.SqlNull.UnmarshalJSON(b); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if t.Valid && (t.Val.IsZero() || t.Val.Format("2006-01-02T15:04:05") == "0001-01-01T00:00:00") {
|
if t.Valid && (t.Val.IsZero() || t.Val.Format(time.RFC3339) == "0001-01-01T00:00:00Z") {
|
||||||
t.Valid = false
|
t.Valid = false
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -469,21 +469,21 @@ func (t SqlTimeStamp) Value() (driver.Value, error) {
|
|||||||
if !t.Valid || t.Val.IsZero() || t.Val.Before(time.Date(0o002, 1, 1, 0, 0, 0, 0, time.UTC)) {
|
if !t.Valid || t.Val.IsZero() || t.Val.Before(time.Date(0o002, 1, 1, 0, 0, 0, 0, time.UTC)) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
return t.Val.Format("2006-01-02T15:04:05"), nil
|
return t.Val.Format(time.RFC3339), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t SqlTimeStamp) MarshalYAML() (any, error) {
|
func (t SqlTimeStamp) MarshalYAML() (any, error) {
|
||||||
if !t.Valid || t.Val.IsZero() || t.Val.Before(time.Date(0o002, 1, 1, 0, 0, 0, 0, time.UTC)) {
|
if !t.Valid || t.Val.IsZero() || t.Val.Before(time.Date(0o002, 1, 1, 0, 0, 0, 0, time.UTC)) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
return t.Val.Format("2006-01-02T15:04:05"), nil
|
return t.Val.Format(time.RFC3339), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *SqlTimeStamp) UnmarshalYAML(value *yaml.Node) error {
|
func (t *SqlTimeStamp) UnmarshalYAML(value *yaml.Node) error {
|
||||||
if err := t.SqlNull.UnmarshalYAML(value); err != nil {
|
if err := t.SqlNull.UnmarshalYAML(value); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if t.Valid && (t.Val.IsZero() || t.Val.Format("2006-01-02T15:04:05") == "0001-01-01T00:00:00") {
|
if t.Valid && (t.Val.IsZero() || t.Val.Format(time.RFC3339) == "0001-01-01T00:00:00Z") {
|
||||||
t.Valid = false
|
t.Valid = false
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -493,7 +493,7 @@ func (t SqlTimeStamp) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
|
|||||||
if !t.Valid || t.Val.IsZero() || t.Val.Before(time.Date(0o002, 1, 1, 0, 0, 0, 0, time.UTC)) {
|
if !t.Valid || t.Val.IsZero() || t.Val.Before(time.Date(0o002, 1, 1, 0, 0, 0, 0, time.UTC)) {
|
||||||
return e.EncodeElement("", start)
|
return e.EncodeElement("", start)
|
||||||
}
|
}
|
||||||
return e.EncodeElement(t.Val.Format("2006-01-02T15:04:05"), start)
|
return e.EncodeElement(t.Val.Format(time.RFC3339), start)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *SqlTimeStamp) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
func (t *SqlTimeStamp) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
@@ -511,7 +511,7 @@ func (t *SqlTimeStamp) UnmarshalXML(d *xml.Decoder, start xml.StartElement) erro
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
t.Val = tm
|
t.Val = tm
|
||||||
t.Valid = !tm.IsZero() && tm.Format("2006-01-02T15:04:05") != "0001-01-01T00:00:00"
|
t.Valid = !tm.IsZero() && tm.Format(time.RFC3339) != "0001-01-01T00:00:00Z"
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ func TestSqlTimeStamp_JSON(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Marshal failed: %v", err)
|
t.Fatalf("Marshal failed: %v", err)
|
||||||
}
|
}
|
||||||
expected := `"2024-01-15T10:30:45"`
|
expected := `"2024-01-15T10:30:45Z"`
|
||||||
if string(data) != expected {
|
if string(data) != expected {
|
||||||
t.Errorf("expected %s, got %s", expected, string(data))
|
t.Errorf("expected %s, got %s", expected, string(data))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ func TestSqlTimeStamp_YAML(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Marshal failed: %v", err)
|
t.Fatalf("Marshal failed: %v", err)
|
||||||
}
|
}
|
||||||
if string(data) != "2024-06-15T09:30:00\n" {
|
if string(data) != "\"2024-06-15T09:30:00Z\"\n" {
|
||||||
t.Errorf("unexpected YAML: %q", string(data))
|
t.Errorf("unexpected YAML: %q", string(data))
|
||||||
}
|
}
|
||||||
var ts2 SqlTimeStamp
|
var ts2 SqlTimeStamp
|
||||||
|
|||||||
Reference in New Issue
Block a user