SG CommandandClaude Sonnet 5 4d299fda98 feat(job): declarative YAML job files for named relspec workflows
Add `relspec job list` and `relspec job run <name>` driven by YAML job
manifests (relspec.yml / relspec.<name>.yml), so multi-file merge and
conversion workflows can be expressed declaratively instead of as long
shell command lines.

v1 contract (see docs/JOB_FILES.md):
- `command` is a closed allow-list (convert, merge, scripts-list); no
  field accepts a shell string or executable path.
- Deterministic discovery: default file first, then named files sorted
  lexically; all files merged into one namespace; duplicate job names
  across files are a hard error.
- Every path resolves relative to the job file's directory; absolute,
  home-relative and directory-escaping paths are rejected at validation.
- Database credentials referenced by env-var name via `conn_env:`;
  connection strings are never stored and are redacted from logs/plan.
- Full validation (version, unknown fields, command/format, per-command
  input/output shape, path traversal, depends_on targets, dependency
  cycles) runs before anything is read, written or executed; per-job
  pre-flight then checks input existence, script dirs, env vars and the
  output overwrite policy for the whole plan.
- `depends_on` closure runs in deterministic topological order;
  `--no-deps` runs only the named job.
- `--dry-run` (alias `--plan`) prints the resolved plan and exits 0
  without touching inputs, outputs or databases.
- A failing job propagates the underlying non-zero exit status, logs
  FAILED (never OK), and writes no success marker.

pkg/jobs is side-effect free (discovery/parse/validate/plan only);
execution adapters live in cmd/relspec/job.go. Includes unit tests for
discovery, validation, planning and path safety, plus CLI tests for
end-to-end convert/merge, scripts-list across multiple directories,
dry-run, dependency chains, exit-code propagation and log redaction.

Deferred: live `scripts execute` from jobs, split/inspect/diff/templ
commands, job-to-job output wiring, log rotation/retention.

Refs #20

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 00:44:38 +02:00
2026-04-08 21:34:00 +02:00
2026-08-31 02:05:32 +02:00
2025-12-16 13:12:43 +02:00
2025-12-16 13:12:43 +02:00
2025-12-16 13:12:43 +02:00
2025-12-16 08:38:49 +00:00

RelSpec

Release CI Integration Tests Go Version License

Bidirectional database schema conversion, validation, and templating tool.

RelSpec

Install

go install -v git.warky.dev/wdevs/relspecgo/cmd/relspec@latest

Supported Formats

Direction Formats
Readers bun dbml dctx drawdb drizzle gorm graphql json mssql pgsql prisma sqldir sqlite typeorm yaml
Writers bun dbml dctx drawdb drizzle gorm graphql json mssql pgsql prisma sqlexec sqlite template typeorm yaml

Commands

convert — Schema conversion

# PostgreSQL → GORM models
relspec convert --from pgsql --from-conn "postgres://user:pass@localhost/mydb" \
                --to gorm --to-path models/ --package models

# DBML → PostgreSQL DDL
relspec convert --from dbml --from-path schema.dbml --to pgsql --to-path schema.sql

# PostgreSQL → SQLite (auto flattens schemas)
relspec convert --from pgsql --from-conn "postgres://..." --to sqlite --to-path schema.sql

# Multiple input files merged
relspec convert --from json --from-list "a.json,b.json" --to yaml --to-path merged.yaml

PostgreSQL connections opened by relspec set application_name by default to relspecgo/<version> (with component suffixes internally, e.g. readers/writers). If you need a custom value, provide application_name explicitly in the connection string query parameters.

merge — Additive schema merge (never modifies existing items)

# Merge two JSON schemas
relspec merge --target json --target-path base.json \
              --source json --source-path additions.json \
              --output json --output-path merged.json

# Merge PostgreSQL into JSON, skipping tables
relspec merge --target json --target-path current.json \
              --source pgsql --source-conn "postgres://user:pass@localhost/db" \
              --output json --output-path updated.json \
              --skip-tables "audit_log,temp_tables"

Skip flags: --skip-relations --skip-views --skip-domains --skip-enums --skip-sequences

inspect — Schema validation / linting

# Validate PostgreSQL database
relspec inspect --from pgsql --from-conn "postgres://user:pass@localhost/mydb"

# Validate DBML with custom rules
relspec inspect --from dbml --from-path schema.dbml --rules .relspec-rules.yaml

# JSON report output
relspec inspect --from json --from-path db.json --output-format json --output report.json

# Filter to specific schema
relspec inspect --from pgsql --from-conn "..." --schema public

Rules: naming conventions, PK/FK standards, missing indexes, reserved keywords, circular dependencies.

diff — Schema comparison

relspec diff --from pgsql --from-conn "postgres://localhost/db1" \
             --to pgsql --to-conn "postgres://localhost/db2"

templ — Custom template rendering

# Render database schema to Markdown docs
relspec templ --from pgsql --from-conn "postgres://user:pass@localhost/db" \
              --template docs.tmpl --output schema-docs.md

# One TypeScript file per table
relspec templ --from dbml --from-path schema.dbml \
              --template ts-model.tmpl --mode table \
              --output ./models/ --filename-pattern "{{.Name | toCamelCase}}.ts"

Modes: database (default) · schema · table · script

Template functions: string utils (toCamelCase, toSnakeCase, pluralize, …), type converters (sqlToGo, sqlToTypeScript, …), filters, loop helpers, safe access.

job — Declarative job files

Run named jobs from a relspec.yml manifest instead of repeating long command lines.

# List jobs discovered in ./relspec.yml and ./relspec.<name>.yml (deterministic)
relspec job list

# Validate and print the plan without running anything
relspec job run build-schema --plan

# Run a job (and its declared dependencies)
relspec job run build-schema
# relspec.yml
version: 1
jobs:
  build-schema:
    command: convert            # closed allow-list: convert | merge | scripts-list
    description: Merge the DBML sources and emit PostgreSQL DDL
    inputs:
      - path: schema/core.dbml
        format: dbml
      - path: schema/tenant.dbml
        format: dbml
    output:
      format: pgsql
      path: build/schema.sql
      overwrite: true
    options:
      flatten_schema: false
    logfile: .relspec/log/build-schema.log

The job system is not a shell: command is a fixed enum, every path is resolved relative to the job file and may not escape it, and remote database credentials are referenced by environment-variable name (conn_env:) and redacted from logs. The whole plan — unknown commands/formats, duplicate job names, missing inputs, path traversal, dependency cycles — is validated before any job runs. See docs/JOB_FILES.md.

edit — Interactive TUI editor

# Edit DBML schema interactively
relspec edit --from dbml --from-path schema.dbml --to dbml --to-path schema.dbml

# Edit live PostgreSQL database
relspec edit --from pgsql --from-conn "postgres://user:pass@localhost/mydb" \
             --to pgsql --to-conn "postgres://user:pass@localhost/mydb"

Development

Prerequisites: Go 1.24.0+

make build     # → build/relspec
make test      # race detection + coverage
make lint      # requires golangci-lint
make coverage  # → coverage.html
make install   # → $GOPATH/bin

Project Structure

cmd/relspec/          CLI commands
pkg/readers/          Input format readers
pkg/writers/          Output format writers
pkg/inspector/        Schema validation
pkg/diff/             Schema comparison
pkg/merge/            Schema merging
pkg/models/           Internal data models
pkg/transform/        Transformation logic
pkg/pgsql/            PostgreSQL utilities
pkg/sqltypes/         Nullable SQL types for generated/hand-written models (see below)

Nullable Types (pkg/sqltypes)

The bun and gorm writers can generate model structs using pkg/sqltypes — nullable types (SqlString, SqlInt32, SqlTimeStamp, SqlStringArray, …) that implement database/sql.Scanner, driver.Valuer, and JSON/YAML/XML marshalling in one type, selected via --types sqltypes. See the pkg/sqltypes README for the full type reference, or the bun / gorm writer docs for the --types flag (sqltypes, stdlib, or baselib). PostgreSQL array columns are the one exception: the bun writer always generates native Go slices ([]string, []int32, …) with an explicit array bun tag, regardless of --types — see bun's --array-nullable flag for nullable-array handling. The SqlXxxArray wrapper types remain available in pkg/sqltypes and are still used by the gorm writer.

Contributing

  1. Register or sign in with GitHub at git.warky.dev
  2. Clone the repository: git clone https://git.warky.dev/wdevs/relspecgo.git
  3. Create a feature branch: git checkout -b feature/your-feature-name
  4. Commit your changes and push the branch
  5. Open a pull request with a description of the new feature or fix

For questions or discussion, join the Discord: discord.gg/74rcTujp25warkyhein

S
Description
Resolve Spec Go
Readme Apache-2.0
48 MiB
v1.0.74
Latest
2026-08-29 18:40:45 +00:00
Languages
Go 96.7%
TypeScript 1.2%
Go Template 1%
Shell 0.5%
Makefile 0.4%
Other 0.2%