chore(ci): add govulncheck, staticcheck, go vet, gofumpt gates
Release / test (push) Failing after 2m20s
Release / release (push) Skipped
Release / pkg-aur (push) Skipped
Release / pkg-deb (push) Skipped
Release / pkg-rpm (push) Skipped

* Add lint/format checks to the Gitea release workflow and Makefile
  (targets: vet, fmt, fmt-check, staticcheck, govulncheck, check)
* Switch .golangci.json formatter from gofmt to gofumpt (extra.group-params)
* Bump golang.org/x/text 0.37.0 -> 0.39.0 for GO-2026-5970; re-vendor
* Fix staticcheck S1011 in pkg/diff; drop unused pgsql writer helpers
* Fix gocritic unnamedResult (pkg/diff) and rangeValCopy (pkg/pgsql)
* Apply gofumpt + goimports formatting across the tree
This commit is contained in:
2026-09-03 21:17:03 +02:00
parent d6d0200938
commit 96281c9f03
138 changed files with 2245 additions and 1004 deletions
+3 -3
View File
@@ -195,7 +195,7 @@ func (w *Writer) writeMultiFile(db *models.Database) error {
}
// Create output directory if it doesn't exist
if err := os.MkdirAll(w.options.OutputPath, 0755); err != nil {
if err := os.MkdirAll(w.options.OutputPath, 0o755); err != nil {
return fmt.Errorf("failed to create output directory: %w", err)
}
@@ -267,7 +267,7 @@ func (w *Writer) writeMultiFile(db *models.Database) error {
filepath := filepath.Join(w.options.OutputPath, filename)
// Write file
if err := os.WriteFile(filepath, []byte(formatted), 0644); err != nil {
if err := os.WriteFile(filepath, []byte(formatted), 0o644); err != nil {
return fmt.Errorf("failed to write file %s: %w", filename, err)
}
@@ -471,7 +471,7 @@ func (w *Writer) formatCode(code string) (string, error) {
// writeOutput writes the content to file or stdout
func (w *Writer) writeOutput(content string) error {
if w.options.OutputPath != "" {
return os.WriteFile(w.options.OutputPath, []byte(content), 0644)
return os.WriteFile(w.options.OutputPath, []byte(content), 0o644)
}
// Print to stdout
+3 -3
View File
@@ -27,7 +27,7 @@ func (w *Writer) WriteDatabase(db *models.Database) error {
content := w.databaseToDBML(db)
if w.options.OutputPath != "" {
return os.WriteFile(w.options.OutputPath, []byte(content), 0644)
return os.WriteFile(w.options.OutputPath, []byte(content), 0o644)
}
fmt.Print(content)
@@ -39,7 +39,7 @@ func (w *Writer) WriteSchema(schema *models.Schema) error {
content := w.schemaToDBML(schema)
if w.options.OutputPath != "" {
return os.WriteFile(w.options.OutputPath, []byte(content), 0644)
return os.WriteFile(w.options.OutputPath, []byte(content), 0o644)
}
fmt.Print(content)
@@ -51,7 +51,7 @@ func (w *Writer) WriteTable(table *models.Table) error {
content := w.tableToDBML(table)
if w.options.OutputPath != "" {
return os.WriteFile(w.options.OutputPath, []byte(content), 0644)
return os.WriteFile(w.options.OutputPath, []byte(content), 0o644)
}
fmt.Print(content)
+3 -2
View File
@@ -5,9 +5,10 @@ import (
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"git.warky.dev/wdevs/relspecgo/pkg/models"
"git.warky.dev/wdevs/relspecgo/pkg/writers"
"github.com/stretchr/testify/assert"
)
func TestWriter_WriteTable(t *testing.T) {
@@ -152,4 +153,4 @@ func TestWriter_WriteDatabase_OneToOneRelationship(t *testing.T) {
output := string(content)
assert.Contains(t, output, "Ref: public.profiles.user_id - public.users.id")
}
}
+2 -1
View File
@@ -5,11 +5,12 @@ import (
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"git.warky.dev/wdevs/relspecgo/pkg/models"
"git.warky.dev/wdevs/relspecgo/pkg/readers"
dctxreader "git.warky.dev/wdevs/relspecgo/pkg/readers/dctx"
"git.warky.dev/wdevs/relspecgo/pkg/writers"
"github.com/stretchr/testify/assert"
)
func TestRoundTrip_WriteAndRead(t *testing.T) {
+3 -2
View File
@@ -5,9 +5,10 @@ import (
"os"
"testing"
"github.com/stretchr/testify/assert"
"git.warky.dev/wdevs/relspecgo/pkg/models"
"git.warky.dev/wdevs/relspecgo/pkg/writers"
"github.com/stretchr/testify/assert"
)
func TestWriter_WriteSchema(t *testing.T) {
@@ -149,4 +150,4 @@ func TestWriter_WriteSchema(t *testing.T) {
// PrimaryMapping should reference foreign table (posts) fields
assert.Len(t, relationResult.PrimaryMappings, 1)
assert.NotEmpty(t, relationResult.PrimaryMappings[0].Field)
}
}
+1 -1
View File
@@ -48,7 +48,7 @@ func (w *Writer) writeJSON(data interface{}) error {
}
if w.options.OutputPath != "" {
return os.WriteFile(w.options.OutputPath, jsonData, 0644)
return os.WriteFile(w.options.OutputPath, jsonData, 0o644)
}
// If no output path, print to stdout
+4 -4
View File
@@ -115,7 +115,7 @@ func (w *Writer) writeMultiFile(db *models.Database) error {
}
// Create output directory if it doesn't exist
if err := os.MkdirAll(w.options.OutputPath, 0755); err != nil {
if err := os.MkdirAll(w.options.OutputPath, 0o755); err != nil {
return fmt.Errorf("failed to create output directory: %w", err)
}
@@ -163,7 +163,7 @@ func (w *Writer) writeEnumsFile(schema *models.Schema) error {
// Write to enums.ts file
filename := filepath.Join(w.options.OutputPath, "enums.ts")
return os.WriteFile(filename, []byte(code), 0644)
return os.WriteFile(filename, []byte(code), 0o644)
}
// writeTableFile writes a single table to its own file
@@ -200,7 +200,7 @@ func (w *Writer) writeTableFile(table *models.Table, schema *models.Schema, db *
// Sanitize table name to remove quotes, comments, and invalid characters
safeTableName := writers.SanitizeFilename(table.Name)
filename := filepath.Join(w.options.OutputPath, safeTableName+".ts")
return os.WriteFile(filename, []byte(code), 0644)
return os.WriteFile(filename, []byte(code), 0o644)
}
// buildTableData builds TableData from a models.Table
@@ -533,7 +533,7 @@ func (w *Writer) getForeignKeyForColumn(columnName string, table *models.Table)
// writeOutput writes the content to file or stdout
func (w *Writer) writeOutput(content string) error {
if w.options.OutputPath != "" {
return os.WriteFile(w.options.OutputPath, []byte(content), 0644)
return os.WriteFile(w.options.OutputPath, []byte(content), 0o644)
}
// Print to stdout
+3 -3
View File
@@ -152,7 +152,7 @@ func (w *Writer) writeMultiFile(db *models.Database) error {
}
// Create output directory if it doesn't exist
if err := os.MkdirAll(w.options.OutputPath, 0755); err != nil {
if err := os.MkdirAll(w.options.OutputPath, 0o755); err != nil {
return fmt.Errorf("failed to create output directory: %w", err)
}
@@ -218,7 +218,7 @@ func (w *Writer) writeMultiFile(db *models.Database) error {
filepath := filepath.Join(w.options.OutputPath, filename)
// Write file
if err := os.WriteFile(filepath, []byte(formatted), 0644); err != nil {
if err := os.WriteFile(filepath, []byte(formatted), 0o644); err != nil {
return fmt.Errorf("failed to write file %s: %w", filename, err)
}
@@ -422,7 +422,7 @@ func (w *Writer) formatCode(code string) (string, error) {
// writeOutput writes the content to file or stdout
func (w *Writer) writeOutput(content string) error {
if w.options.OutputPath != "" {
return os.WriteFile(w.options.OutputPath, []byte(content), 0644)
return os.WriteFile(w.options.OutputPath, []byte(content), 0o644)
}
// Print to stdout
+1 -1
View File
@@ -76,7 +76,7 @@ func (w *Writer) generateRelationFields(table *models.Table, db *models.Database
return fields
}
func (w *Writer) getManyToManyField(table *models.Table, joinTable *models.Table, db *models.Database) string {
func (w *Writer) getManyToManyField(table, joinTable *models.Table, db *models.Database) string {
// Find the two FK constraints in the join table
var fk1, fk2 *models.Constraint
for _, constraint := range joinTable.Constraints {
+1 -1
View File
@@ -24,7 +24,7 @@ func (w *Writer) WriteDatabase(db *models.Database) error {
content := w.databaseToGraphQL(db)
if w.options.OutputPath != "" {
return os.WriteFile(w.options.OutputPath, []byte(content), 0644)
return os.WriteFile(w.options.OutputPath, []byte(content), 0o644)
}
fmt.Print(content)
+1 -1
View File
@@ -55,7 +55,7 @@ func (w *Writer) WriteTable(table *models.Table) error {
// writeOutput writes the content to file or stdout
func (w *Writer) writeOutput(data []byte) error {
if w.options.OutputPath != "" {
return os.WriteFile(w.options.OutputPath, data, 0644)
return os.WriteFile(w.options.OutputPath, data, 0o644)
}
// Print to stdout
+2 -1
View File
@@ -4,9 +4,10 @@ import (
"bytes"
"testing"
"github.com/stretchr/testify/assert"
"git.warky.dev/wdevs/relspecgo/pkg/models"
"git.warky.dev/wdevs/relspecgo/pkg/writers"
"github.com/stretchr/testify/assert"
)
// TestGenerateColumnDefinition tests column definition generation
+8 -8
View File
@@ -47,7 +47,7 @@ func NewMigrationWriter(options *writers.WriterOptions) (*MigrationWriter, error
}
// WriteMigration generates migration scripts using templates
func (w *MigrationWriter) WriteMigration(model *models.Database, current *models.Database) error {
func (w *MigrationWriter) WriteMigration(model, current *models.Database) error {
if model == nil {
return fmt.Errorf("model database is required")
}
@@ -161,7 +161,7 @@ func (w *MigrationWriter) WriteMigration(model *models.Database, current *models
}
// generateSchemaScripts generates migration scripts for a schema using templates
func (w *MigrationWriter) generateSchemaScripts(model *models.Schema, current *models.Schema) ([]MigrationScript, error) {
func (w *MigrationWriter) generateSchemaScripts(model, current *models.Schema) ([]MigrationScript, error) {
scripts := make([]MigrationScript, 0)
for _, extension := range requiredExtensions(model) {
@@ -220,7 +220,7 @@ func (w *MigrationWriter) generateSchemaScripts(model *models.Schema, current *m
// generateDropScripts generates DROP scripts using templates.
// Returns the scripts and a set of FK constraint keys (schema.table.name) that were
// explicitly dropped because their referenced PK was being dropped, so they can be force-recreated.
func (w *MigrationWriter) generateDropScripts(model *models.Schema, current *models.Schema) ([]MigrationScript, map[string]bool, error) {
func (w *MigrationWriter) generateDropScripts(model, current *models.Schema) ([]MigrationScript, map[string]bool, error) {
scripts := make([]MigrationScript, 0)
droppedFKs := make(map[string]bool)
@@ -349,7 +349,7 @@ func (w *MigrationWriter) generateDropScripts(model *models.Schema, current *mod
}
// generateTableScripts generates CREATE/ALTER TABLE scripts using templates
func (w *MigrationWriter) generateTableScripts(model *models.Schema, current *models.Schema) ([]MigrationScript, error) {
func (w *MigrationWriter) generateTableScripts(model, current *models.Schema) ([]MigrationScript, error) {
scripts := make([]MigrationScript, 0)
// Build map of current tables
@@ -394,7 +394,7 @@ func (w *MigrationWriter) generateTableScripts(model *models.Schema, current *mo
}
// generateAlterTableScripts generates ALTER TABLE scripts using templates
func (w *MigrationWriter) generateAlterTableScripts(schema *models.Schema, modelTable *models.Table, currentTable *models.Table) ([]MigrationScript, error) {
func (w *MigrationWriter) generateAlterTableScripts(schema *models.Schema, modelTable, currentTable *models.Table) ([]MigrationScript, error) {
scripts := make([]MigrationScript, 0)
// Build map of current columns
@@ -514,7 +514,7 @@ func (w *MigrationWriter) generateAlterTableScripts(schema *models.Schema, model
}
// generateIndexScripts generates CREATE INDEX scripts using templates
func (w *MigrationWriter) generateIndexScripts(model *models.Schema, current *models.Schema) ([]MigrationScript, error) {
func (w *MigrationWriter) generateIndexScripts(model, current *models.Schema) ([]MigrationScript, error) {
scripts := make([]MigrationScript, 0)
// Build map of current tables
@@ -709,7 +709,7 @@ func buildIndexColumnExpressionsFiltered(table *models.Table, index *models.Inde
// generateForeignKeyScripts generates ADD CONSTRAINT FOREIGN KEY scripts using templates.
// forceRecreate is a set of FK constraint keys (schema.table.name) that must be recreated
// even if unchanged, because their referenced PK was dropped and recreated.
func (w *MigrationWriter) generateForeignKeyScripts(model *models.Schema, current *models.Schema, forceRecreate map[string]bool) ([]MigrationScript, error) {
func (w *MigrationWriter) generateForeignKeyScripts(model, current *models.Schema, forceRecreate map[string]bool) ([]MigrationScript, error) {
scripts := make([]MigrationScript, 0)
// Build map of current tables
@@ -787,7 +787,7 @@ func (w *MigrationWriter) generateForeignKeyScripts(model *models.Schema, curren
}
// generateCommentScripts generates COMMENT ON scripts using templates
func (w *MigrationWriter) generateCommentScripts(model *models.Schema, current *models.Schema) ([]MigrationScript, error) {
func (w *MigrationWriter) generateCommentScripts(model, current *models.Schema) ([]MigrationScript, error) {
scripts := make([]MigrationScript, 0)
_ = current // TODO: Compare with current schema to only add new/changed comments
-18
View File
@@ -1579,11 +1579,6 @@ func indexOperatorClassForColumn(col *models.Column, indexType, comment string)
}
}
// ginOperatorClassForColumn is the GIN-specific form of indexOperatorClassForColumn.
func ginOperatorClassForColumn(col *models.Column, comment string) string {
return indexOperatorClassForColumn(col, "gin", comment)
}
func operatorClassCompatible(method, baseType string, isArray bool, opClass string) bool {
if vectorType, ok := vectorOperatorClasses[opClass]; ok {
return !isArray && baseType == vectorType && isVectorIndexMethod(method)
@@ -1604,10 +1599,6 @@ func operatorClassCompatible(method, baseType string, isArray bool, opClass stri
}
}
func ginOperatorClassCompatible(baseType string, isArray bool, opClass string) bool {
return operatorClassCompatible("gin", baseType, isArray, opClass)
}
func isTextGinBaseType(baseType string) bool {
switch baseType {
case "text", "varchar", "character varying", "char", "character", "string", "citext", "bpchar":
@@ -1793,15 +1784,6 @@ func nativeGistBaseType(baseType string) bool {
return strings.HasSuffix(baseType, "range") || strings.HasSuffix(baseType, "multirange")
}
func schemaRequiresPGTrgm(schema *models.Schema) bool {
for _, ext := range requiredExtensions(schema) {
if ext == "pg_trgm" {
return true
}
}
return false
}
func resolveIndexColumn(table *models.Table, colName string) (*models.Column, bool) {
if table == nil {
return nil, false
+1 -1
View File
@@ -27,7 +27,7 @@ func (w *Writer) WriteDatabase(db *models.Database) error {
content := w.databaseToPrisma(db)
if w.options.OutputPath != "" {
return os.WriteFile(w.options.OutputPath, []byte(content), 0644)
return os.WriteFile(w.options.OutputPath, []byte(content), 0o644)
}
fmt.Print(content)
+2 -2
View File
@@ -11,8 +11,8 @@ import (
func TestNewWriter(t *testing.T) {
opts := &writers.WriterOptions{
OutputPath: "/tmp/test.sql",
FlattenSchema: false, // Should be forced to true
OutputPath: "/tmp/test.sql",
FlattenSchema: false, // Should be forced to true
}
writer := NewWriter(opts)
+2 -2
View File
@@ -57,7 +57,7 @@ func Indent(s string, spaces int) string {
// IndentWith indents each line of a string with a custom prefix
// Usage: {{ .Column.Description | indentWith " " }}
func IndentWith(s string, prefix string) string {
func IndentWith(s, prefix string) string {
if s == "" {
return ""
}
@@ -93,7 +93,7 @@ func EscapeQuotes(s string) string {
// Comment adds comment prefix to a string
// Supports: "//" (Go, C++, etc.), "#" (Python, shell), "--" (SQL), "/* */" (block)
// Usage: {{ .Table.Description | comment "//" }}
func Comment(s string, style string) string {
func Comment(s, style string) string {
if s == "" {
return ""
}
+5 -5
View File
@@ -8,13 +8,13 @@ import (
// Get safely gets a value from a map by key
// Usage: {{ get .Metadata "key" }}
func Get(m interface{}, key interface{}) interface{} {
func Get(m, key interface{}) interface{} {
return reflectutil.MapGet(m, key)
}
// GetOr safely gets a value from a map with a default fallback
// Usage: {{ getOr .Metadata "key" "default" }}
func GetOr(m interface{}, key interface{}, defaultValue interface{}) interface{} {
func GetOr(m, key, defaultValue interface{}) interface{} {
result := Get(m, key)
if result == nil {
return defaultValue
@@ -56,7 +56,7 @@ func SafeIndexOr(slice interface{}, index int, defaultValue interface{}) interfa
// Has checks if a key exists in a map
// Usage: {{ if has .Metadata "key" }}...{{ end }}
func Has(m interface{}, key interface{}) bool {
func Has(m, key interface{}) bool {
v := reflect.ValueOf(m)
// Dereference pointers
@@ -189,7 +189,7 @@ func Omit(m interface{}, keys ...interface{}) map[interface{}]interface{} {
// SliceContains checks if a slice contains a value
// Usage: {{ if sliceContains .Names "admin" }}...{{ end }}
func SliceContains(slice interface{}, value interface{}) bool {
func SliceContains(slice, value interface{}) bool {
v := reflect.ValueOf(slice)
v, ok := reflectutil.Deref(v)
if !ok {
@@ -211,7 +211,7 @@ func SliceContains(slice interface{}, value interface{}) bool {
// IndexOf returns the index of a value in a slice, or -1 if not found
// Usage: {{ $idx := indexOf .Names "admin" }}
func IndexOf(slice interface{}, value interface{}) int {
func IndexOf(slice, value interface{}) int {
v := reflect.ValueOf(slice)
v, ok := reflectutil.Deref(v)
if !ok {
+3 -3
View File
@@ -285,7 +285,7 @@ func (w *Writer) generateFilename(data *TemplateData) (string, error) {
}
// writeOutput writes the output to a file or stdout
func (w *Writer) writeOutput(content string, outputPath string) error {
func (w *Writer) writeOutput(content, outputPath string) error {
// If output path is empty, write to stdout
if outputPath == "" {
fmt.Print(content)
@@ -295,13 +295,13 @@ func (w *Writer) writeOutput(content string, outputPath string) error {
// Ensure directory exists
dir := filepath.Dir(outputPath)
if dir != "." && dir != "" {
if err := os.MkdirAll(dir, 0755); err != nil {
if err := os.MkdirAll(dir, 0o755); err != nil {
return fmt.Errorf("failed to create directory %s: %w", dir, err)
}
}
// Write to file
if err := os.WriteFile(outputPath, []byte(content), 0644); err != nil {
if err := os.WriteFile(outputPath, []byte(content), 0o644); err != nil {
return fmt.Errorf("failed to write file %s: %w", outputPath, err)
}
+2 -2
View File
@@ -17,10 +17,10 @@ func TestWriterTableIndexValuesDeterministic(t *testing.T) {
outputPath := filepath.Join(outputDir, "accounts.txt")
templateBody := "{{range values .Table.Indexes}}{{.Name}}:{{join .Columns \",\"}}\n{{end}}"
if err := os.MkdirAll(outputDir, 0755); err != nil {
if err := os.MkdirAll(outputDir, 0o755); err != nil {
t.Fatalf("create output dir: %v", err)
}
if err := os.WriteFile(templatePath, []byte(templateBody), 0644); err != nil {
if err := os.WriteFile(templatePath, []byte(templateBody), 0o644); err != nil {
t.Fatalf("write template: %v", err)
}
+1 -1
View File
@@ -27,7 +27,7 @@ func (w *Writer) WriteDatabase(db *models.Database) error {
content := w.databaseToTypeORM(db)
if w.options.OutputPath != "" {
return os.WriteFile(w.options.OutputPath, []byte(content), 0644)
return os.WriteFile(w.options.OutputPath, []byte(content), 0o644)
}
fmt.Print(content)
+1 -1
View File
@@ -55,7 +55,7 @@ func (w *Writer) WriteTable(table *models.Table) error {
// writeOutput writes the content to file or stdout
func (w *Writer) writeOutput(data []byte) error {
if w.options.OutputPath != "" {
return os.WriteFile(w.options.OutputPath, data, 0644)
return os.WriteFile(w.options.OutputPath, data, 0o644)
}
// Print to stdout