feat(job): complete deferred job-file features
Implements the remaining items from issue #20: - version is now forward-permissive: any value >= 1 is accepted; a newer-than-known version loads best-effort (unknown fields ignored, warning printed) instead of hard-failing on "must be 1" - from_job input reference: `inputs: [{ from_job: <job> }]` resolves to that job's single-file output + format and implies a dependency edge; combined depends_on + from_job graph gets topological ordering and cycle detection - logfile size-rotation, on by default (5MB, keep 3), overridable per job (log_max_size / log_keep) or file-wide via a top-level defaults block - new commands: split (schema/table subsetting via select:), inspect (rule validation -> markdown/json report, fails job on enforced-rule errors), diff (compare exactly two schemas, never fails), scripts-exec (run SQL script dirs against a live PostgreSQL database) - atomic single-file output/report writes (temp file + rename) - symlink-escape hardening in SafeJoin via EvalSymlinks preflight Updates docs/JOB_FILES.md and examples/jobs/relspec.yml accordingly.
This commit is contained in:
+50
-6
@@ -205,8 +205,52 @@ func runSplit(cmd *cobra.Command, args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// filterDatabase filters the database based on provided criteria
|
||||
// splitSelection is the schema/table selection for a split, independent of the
|
||||
// CLI flag globals so the job runner can build one directly.
|
||||
type splitSelection struct {
|
||||
Schemas []string
|
||||
Tables []string
|
||||
ExcludeSchemas []string
|
||||
ExcludeTables []string
|
||||
DatabaseName string
|
||||
}
|
||||
|
||||
// summary renders a one-line human description of the selection.
|
||||
func (s splitSelection) summary() string {
|
||||
var parts []string
|
||||
if len(s.Schemas) > 0 {
|
||||
parts = append(parts, "schemas="+strings.Join(s.Schemas, ","))
|
||||
}
|
||||
if len(s.Tables) > 0 {
|
||||
parts = append(parts, "tables="+strings.Join(s.Tables, ","))
|
||||
}
|
||||
if len(s.ExcludeSchemas) > 0 {
|
||||
parts = append(parts, "exclude_schemas="+strings.Join(s.ExcludeSchemas, ","))
|
||||
}
|
||||
if len(s.ExcludeTables) > 0 {
|
||||
parts = append(parts, "exclude_tables="+strings.Join(s.ExcludeTables, ","))
|
||||
}
|
||||
if s.DatabaseName != "" {
|
||||
parts = append(parts, "database_name="+s.DatabaseName)
|
||||
}
|
||||
if len(parts) == 0 {
|
||||
return "(all schemas/tables)"
|
||||
}
|
||||
return strings.Join(parts, " ")
|
||||
}
|
||||
|
||||
// filterDatabase filters the database based on the CLI split flags.
|
||||
func filterDatabase(db *models.Database) (*models.Database, error) {
|
||||
return filterDatabaseSelection(db, splitSelection{
|
||||
Schemas: parseCommaSeparated(splitSchemas),
|
||||
Tables: parseCommaSeparated(splitTables),
|
||||
ExcludeSchemas: parseCommaSeparated(splitExcludeSchema),
|
||||
ExcludeTables: parseCommaSeparated(splitExcludeTables),
|
||||
})
|
||||
}
|
||||
|
||||
// filterDatabaseSelection filters db down to the schemas/tables named by sel.
|
||||
func filterDatabaseSelection(db *models.Database, sel splitSelection) (*models.Database, error) {
|
||||
filteredDB := &models.Database{
|
||||
Name: db.Name,
|
||||
Description: db.Description,
|
||||
@@ -220,11 +264,11 @@ func filterDatabase(db *models.Database) (*models.Database, error) {
|
||||
Domains: db.Domains, // Keep domains for now
|
||||
}
|
||||
|
||||
// Parse filter flags
|
||||
includeSchemas := parseCommaSeparated(splitSchemas)
|
||||
includeTables := parseCommaSeparated(splitTables)
|
||||
excludeSchemas := parseCommaSeparated(splitExcludeSchema)
|
||||
excludeTables := parseCommaSeparated(splitExcludeTables)
|
||||
// Selection criteria
|
||||
includeSchemas := sel.Schemas
|
||||
includeTables := sel.Tables
|
||||
excludeSchemas := sel.ExcludeSchemas
|
||||
excludeTables := sel.ExcludeTables
|
||||
|
||||
// Convert table names to lowercase for case-insensitive matching
|
||||
includeTablesLower := make(map[string]bool)
|
||||
|
||||
Reference in New Issue
Block a user