Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80a3453233 | ||
|
|
ade71b75fa | ||
|
|
799b7feb53 |
@@ -312,7 +312,13 @@ jobs:
|
|||||||
rockylinux:9 \
|
rockylinux:9 \
|
||||||
bash -lc "
|
bash -lc "
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
dnf install -y rpm-build git &&
|
# Avoid transient/out-of-sync mirrors while bootstrapping the RPM builder.
|
||||||
|
sed -i \
|
||||||
|
-e 's|^mirrorlist=|#mirrorlist=|' \
|
||||||
|
-e 's|^#baseurl=http://dl.rockylinux.org|baseurl=https://dl.rockylinux.org|' \
|
||||||
|
/etc/yum.repos.d/rocky*.repo
|
||||||
|
dnf clean all
|
||||||
|
dnf -y --setopt=timeout=60 --setopt=retries=5 install rpm-build git
|
||||||
curl -fsSL https://go.dev/dl/go\${GO_VER}.linux-amd64.tar.gz | tar -C /usr/local -xz &&
|
curl -fsSL https://go.dev/dl/go\${GO_VER}.linux-amd64.tar.gz | tar -C /usr/local -xz &&
|
||||||
export PATH=\$PATH:/usr/local/go/bin &&
|
export PATH=\$PATH:/usr/local/go/bin &&
|
||||||
mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} &&
|
mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} &&
|
||||||
|
|||||||
+2
-2
@@ -841,7 +841,7 @@ func writeJobOutput(rj *resolvedJob, db *models.Database, lg *jobLogger) error {
|
|||||||
return fmt.Errorf("database output is only supported for pgsql (got %q)", rj.job.Output.Format)
|
return fmt.Errorf("database output is only supported for pgsql (got %q)", rj.job.Output.Format)
|
||||||
}
|
}
|
||||||
lg.logf("writing output to database env:%s", rj.outputConnEnv)
|
lg.logf("writing output to database env:%s", rj.outputConnEnv)
|
||||||
writerOpts := newWriterOptions("", o.Package, o.FlattenSchema, "", "", o.ContinueOnError)
|
writerOpts := newWriterOptions("", o.Package, o.FlattenSchema, o.Types, o.ArrayNullable, o.ContinueOnError)
|
||||||
writerOpts.Metadata = map[string]interface{}{"connection_string": rj.outputConn}
|
writerOpts.Metadata = map[string]interface{}{"connection_string": rj.outputConn}
|
||||||
return wpgsql.NewWriter(writerOpts).WriteDatabase(db)
|
return wpgsql.NewWriter(writerOpts).WriteDatabase(db)
|
||||||
}
|
}
|
||||||
@@ -852,7 +852,7 @@ func writeJobOutput(rj *resolvedJob, db *models.Database, lg *jobLogger) error {
|
|||||||
lg.logf("writing output: %s (%s)", rj.outputPath, format)
|
lg.logf("writing output: %s (%s)", rj.outputPath, format)
|
||||||
|
|
||||||
write := func(target string) error {
|
write := func(target string) error {
|
||||||
return writeDatabase(db, format, target, o.Package, o.Schema, o.FlattenSchema, "", "", o.ContinueOnError, "")
|
return writeDatabase(db, format, target, o.Package, o.Schema, o.FlattenSchema, o.Types, o.ArrayNullable, o.ContinueOnError, "")
|
||||||
}
|
}
|
||||||
// Single-file formats are written to a temp file and renamed into place so
|
// Single-file formats are written to a temp file and renamed into place so
|
||||||
// a failure never leaves a partial or truncated output. Directory-emitting
|
// a failure never leaves a partial or truncated output. Directory-emitting
|
||||||
|
|||||||
@@ -666,6 +666,7 @@ jobs:
|
|||||||
format: dbml
|
format: dbml
|
||||||
template: templates/schema.tmpl
|
template: templates/schema.tmpl
|
||||||
output:
|
output:
|
||||||
|
format: text
|
||||||
path: build/schema.txt
|
path: build/schema.txt
|
||||||
overwrite: true
|
overwrite: true
|
||||||
`)
|
`)
|
||||||
@@ -682,3 +683,61 @@ jobs:
|
|||||||
t.Fatalf("templ output missing users table: %s", out)
|
t.Fatalf("templ output missing users table: %s", out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestJobRun_BunSqlTypesOption(t *testing.T) {
|
||||||
|
dir := jobFixture(t, `version: 1
|
||||||
|
jobs:
|
||||||
|
models:
|
||||||
|
command: convert
|
||||||
|
inputs:
|
||||||
|
- path: schema/core.dbml
|
||||||
|
format: dbml
|
||||||
|
output:
|
||||||
|
format: bun
|
||||||
|
path: build/models
|
||||||
|
options:
|
||||||
|
package: models
|
||||||
|
types: sqltypes
|
||||||
|
`)
|
||||||
|
set := mustLoadSet(t, filepath.Join(dir, "relspec.yml"))
|
||||||
|
if err := executeJobPlan(set, "models", false, false, &bytes.Buffer{}); err != nil {
|
||||||
|
t.Fatalf("execute Bun job: %v", err)
|
||||||
|
}
|
||||||
|
generated, err := os.ReadFile(filepath.Join(dir, "build", "models"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("read Bun output: %v", err)
|
||||||
|
}
|
||||||
|
if !strings.Contains(string(generated), "git.warky.dev/wdevs/relspecgo/pkg/sqltypes") {
|
||||||
|
t.Fatalf("Bun output did not preserve options.types: %s", generated)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJobValidation_TemplTextFormat(t *testing.T) {
|
||||||
|
validDir := jobFixture(t, `version: 1
|
||||||
|
jobs:
|
||||||
|
docs:
|
||||||
|
command: templ
|
||||||
|
inputs: [{path: schema/core.dbml, format: dbml}]
|
||||||
|
template: schema.tmpl
|
||||||
|
output: {format: text, path: build/docs.txt}
|
||||||
|
`)
|
||||||
|
valid := mustLoadSet(t, filepath.Join(validDir, "relspec.yml"))
|
||||||
|
if err := valid.Validate(); err != nil {
|
||||||
|
t.Fatalf("text output should be valid for templ: %v", err)
|
||||||
|
}
|
||||||
|
invalidDir := jobFixture(t, `version: 1
|
||||||
|
jobs:
|
||||||
|
docs:
|
||||||
|
command: templ
|
||||||
|
inputs: [{path: schema/core.dbml, format: dbml}]
|
||||||
|
template: schema.tmpl
|
||||||
|
output: {format: json, path: build/docs.txt}
|
||||||
|
`)
|
||||||
|
invalid, err := jobs.Load([]string{filepath.Join(invalidDir, "relspec.yml")})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("load invalid manifest: %v", err)
|
||||||
|
}
|
||||||
|
if err := invalid.Validate(); err == nil || !strings.Contains(err.Error(), "output.format: text") {
|
||||||
|
t.Fatalf("expected templ format rejection, got %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+6
-2
@@ -192,6 +192,8 @@ jobs:
|
|||||||
flatten_schema: false
|
flatten_schema: false
|
||||||
schema: public
|
schema: public
|
||||||
package: models # for gorm/bun output
|
package: models # for gorm/bun output
|
||||||
|
types: sqltypes # Bun/GORM nullable types: baselib|stdlib|sqltypes
|
||||||
|
array_nullable: pointer_slice # Bun: slice|pointer_slice
|
||||||
continue_on_error: false # pgsql / scripts-exec output
|
continue_on_error: false # pgsql / scripts-exec output
|
||||||
skip_relations: false # merge only
|
skip_relations: false # merge only
|
||||||
skip_enums: false
|
skip_enums: false
|
||||||
@@ -205,8 +207,10 @@ jobs:
|
|||||||
|
|
||||||
For `templ`, `inputs` use the same file or `pgsql`/`conn_env` source forms as
|
For `templ`, `inputs` use the same file or `pgsql`/`conn_env` source forms as
|
||||||
schema conversion. `output` is optional (empty means stdout); when present it
|
schema conversion. `output` is optional (empty means stdout); when present it
|
||||||
contains only `path` and `overwrite`, because templates do not select a schema
|
contains `path` and `overwrite`, plus the explicit `format: text` marker. The
|
||||||
writer format.
|
marker is templ-only: it describes arbitrary text produced by a Go template,
|
||||||
|
not a database schema format. It is optional for compatibility with older
|
||||||
|
manifests and has no effect on template execution.
|
||||||
|
|
||||||
A `from_job` input takes no `path`, `format` or `conn_env`: it resolves to the
|
A `from_job` input takes no `path`, `format` or `conn_env`: it resolves to the
|
||||||
named job's `output.path` and inherits its format, and implies a dependency on
|
named job's `output.path` and inherits its format, and implies a dependency on
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ jobs:
|
|||||||
mode: table
|
mode: table
|
||||||
filename_pattern: "{{.Name}}.ts"
|
filename_pattern: "{{.Name}}.ts"
|
||||||
output:
|
output:
|
||||||
|
format: text
|
||||||
path: "${VST}"
|
path: "${VST}"
|
||||||
overwrite: true
|
overwrite: true
|
||||||
|
|
||||||
|
|||||||
+10
-4
@@ -277,9 +277,13 @@ func parseHumanSize(s string) (int64, error) {
|
|||||||
|
|
||||||
// Options carries the subset of command flags a job file may set.
|
// Options carries the subset of command flags a job file may set.
|
||||||
type Options struct {
|
type Options struct {
|
||||||
FlattenSchema bool `yaml:"flatten_schema"`
|
FlattenSchema bool `yaml:"flatten_schema"`
|
||||||
Schema string `yaml:"schema"`
|
Schema string `yaml:"schema"`
|
||||||
Package string `yaml:"package"`
|
Package string `yaml:"package"`
|
||||||
|
// Types and ArrayNullable mirror the existing convert/split writer flags.
|
||||||
|
// They are passed through only to writers that already support them.
|
||||||
|
Types string `yaml:"types"`
|
||||||
|
ArrayNullable string `yaml:"array_nullable"`
|
||||||
ContinueOnError bool `yaml:"continue_on_error"`
|
ContinueOnError bool `yaml:"continue_on_error"`
|
||||||
SkipRelations bool `yaml:"skip_relations"`
|
SkipRelations bool `yaml:"skip_relations"`
|
||||||
SkipEnums bool `yaml:"skip_enums"`
|
SkipEnums bool `yaml:"skip_enums"`
|
||||||
@@ -569,7 +573,9 @@ func (j *Job) validate() []string {
|
|||||||
e = append(e, "command \"templ\" does not support database output")
|
e = append(e, "command \"templ\" does not support database output")
|
||||||
}
|
}
|
||||||
if j.Output != nil && j.Output.Format != "" {
|
if j.Output != nil && j.Output.Format != "" {
|
||||||
e = append(e, "output.format is not valid for command \"templ\"")
|
if strings.ToLower(j.Output.Format) != "text" {
|
||||||
|
e = append(e, "command \"templ\" accepts only output.format: text")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case CommandSplit:
|
case CommandSplit:
|
||||||
if len(j.Inputs) < 1 {
|
if len(j.Inputs) < 1 {
|
||||||
|
|||||||
Reference in New Issue
Block a user