Skip to content

Commit c237001

Browse files
authored
Add script to generate CLI structure (#629)
Add script to generate the structure of the CLI for calling it programmatically and validating params. It will also be useful to generate documentation for pgroll.com. --------- Signed-off-by: Alexis Rico <sferadev@gmail.com>
1 parent 05ab88c commit c237001

File tree

9 files changed

+375
-45
lines changed

9 files changed

+375
-45
lines changed

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ generate: format
2121
echo "// SPDX-License-Identifier: Apache-2.0" | cat - pkg/migrations/types.go > pkg/migrations/types.go.tmp
2222
mv pkg/migrations/types.go.tmp pkg/migrations/types.go
2323

24+
# Generate the cli-definition.json file
25+
go run tools/build-cli-definition.go
26+
2427
lint:
2528
golangci-lint --config=.golangci.yml run
2629

cli-definition.json

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
{
2+
"name": "pgroll",
3+
"commands": [
4+
{
5+
"name": "analyze",
6+
"short": "Analyze the SQL schema of the target database",
7+
"use": "analyze",
8+
"example": "",
9+
"flags": [],
10+
"subcommands": [],
11+
"args": []
12+
},
13+
{
14+
"name": "complete",
15+
"short": "Complete an ongoing migration with the operations present in the given file",
16+
"use": "complete <file>",
17+
"example": "",
18+
"flags": [],
19+
"subcommands": [],
20+
"args": []
21+
},
22+
{
23+
"name": "init",
24+
"short": "Initialize pgroll in the target database",
25+
"use": "init <file>",
26+
"example": "",
27+
"flags": [],
28+
"subcommands": [],
29+
"args": []
30+
},
31+
{
32+
"name": "latest",
33+
"short": "Print the name of the latest schema version, either in the target database or a local directory",
34+
"use": "latest",
35+
"example": "latest --local ./migrations",
36+
"flags": [
37+
{
38+
"name": "local",
39+
"shorthand": "l",
40+
"description": "retrieve the latest version from a local migration directory",
41+
"default": ""
42+
},
43+
{
44+
"name": "with-schema",
45+
"shorthand": "s",
46+
"description": "prefix the version with the schema name",
47+
"default": "false"
48+
}
49+
],
50+
"subcommands": [],
51+
"args": []
52+
},
53+
{
54+
"name": "migrate",
55+
"short": "Apply outstanding migrations from a directory to a database",
56+
"use": "migrate <directory>",
57+
"example": "migrate ./migrations",
58+
"flags": [
59+
{
60+
"name": "complete",
61+
"shorthand": "c",
62+
"description": "complete the final migration rather than leaving it active",
63+
"default": "false"
64+
}
65+
],
66+
"subcommands": [],
67+
"args": [
68+
"directory"
69+
]
70+
},
71+
{
72+
"name": "pull",
73+
"short": "Pull migration history from the target database and write it to disk",
74+
"use": "pull <target directory>",
75+
"example": "",
76+
"flags": [
77+
{
78+
"name": "with-prefixes",
79+
"shorthand": "p",
80+
"description": "prefix each migration filename with its position in the schema history",
81+
"default": "false"
82+
}
83+
],
84+
"subcommands": [],
85+
"args": [
86+
"directory"
87+
]
88+
},
89+
{
90+
"name": "rollback",
91+
"short": "Roll back an ongoing migration",
92+
"use": "rollback <file>",
93+
"example": "",
94+
"flags": [],
95+
"subcommands": [],
96+
"args": []
97+
},
98+
{
99+
"name": "sql",
100+
"short": "Convert SQL statements to pgroll operations",
101+
"use": "sql <sql statement>",
102+
"example": "",
103+
"flags": [],
104+
"subcommands": [],
105+
"args": [
106+
"statement"
107+
]
108+
},
109+
{
110+
"name": "start",
111+
"short": "Start a migration for the operations present in the given file",
112+
"use": "start <file>",
113+
"example": "",
114+
"flags": [
115+
{
116+
"name": "complete",
117+
"shorthand": "c",
118+
"description": "Mark the migration as complete",
119+
"default": "false"
120+
},
121+
{
122+
"name": "skip-validation",
123+
"shorthand": "s",
124+
"description": "skip migration validation",
125+
"default": "false"
126+
}
127+
],
128+
"subcommands": [],
129+
"args": [
130+
"file"
131+
]
132+
},
133+
{
134+
"name": "status",
135+
"short": "Show pgroll status",
136+
"use": "status",
137+
"example": "",
138+
"flags": [],
139+
"subcommands": [],
140+
"args": []
141+
}
142+
],
143+
"flags": [
144+
{
145+
"name": "backfill-batch-delay",
146+
"description": "Duration of delay between batch backfills (eg. 1s, 1000ms)",
147+
"default": "0s"
148+
},
149+
{
150+
"name": "backfill-batch-size",
151+
"description": "Number of rows backfilled in each batch",
152+
"default": "1000"
153+
},
154+
{
155+
"name": "lock-timeout",
156+
"description": "Postgres lock timeout in milliseconds for pgroll DDL operations",
157+
"default": "500"
158+
},
159+
{
160+
"name": "pgroll-schema",
161+
"description": "Postgres schema to use for pgroll internal state",
162+
"default": "pgroll"
163+
},
164+
{
165+
"name": "postgres-url",
166+
"description": "Postgres URL",
167+
"default": "postgres://postgres:postgres@localhost?sslmode=disable"
168+
},
169+
{
170+
"name": "role",
171+
"description": "Optional postgres role to set when executing migrations",
172+
"default": ""
173+
},
174+
{
175+
"name": "schema",
176+
"description": "Postgres schema to use for the migration",
177+
"default": "public"
178+
}
179+
]
180+
}

cmd/latest.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ func latestCmd() *cobra.Command {
1414
var migrationsDir string
1515

1616
latestCmd := &cobra.Command{
17-
Use: "latest <directory>",
17+
Use: "latest",
1818
Short: "Print the name of the latest schema version, either in the target database or a local directory",
1919
Example: "latest --local ./migrations",
2020
Args: cobra.NoArgs,

cmd/migrate.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ func migrateCmd() *cobra.Command {
1313
var complete bool
1414

1515
migrateCmd := &cobra.Command{
16-
Use: "migrate <directory>",
17-
Short: "Apply outstanding migrations from a directory to a database",
18-
Example: "migrate ./migrations",
19-
Args: cobra.ExactArgs(1),
16+
Use: "migrate <directory>",
17+
Short: "Apply outstanding migrations from a directory to a database",
18+
Example: "migrate ./migrations",
19+
Args: cobra.ExactArgs(1),
20+
ValidArgs: []string{"directory"},
2021
RunE: func(cmd *cobra.Command, args []string) error {
2122
ctx := cmd.Context()
2223
migrationsDir := args[0]

cmd/pull.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ func pullCmd() *cobra.Command {
1818
var withPrefixes bool
1919

2020
pullCmd := &cobra.Command{
21-
Use: "pull <target directory>",
22-
Short: "Pull migration history from the target database and write it to disk",
23-
Args: cobra.ExactArgs(1),
21+
Use: "pull <target directory>",
22+
Short: "Pull migration history from the target database and write it to disk",
23+
Args: cobra.ExactArgs(1),
24+
ValidArgs: []string{"directory"},
2425
RunE: func(cmd *cobra.Command, args []string) error {
2526
ctx := cmd.Context()
2627
targetDir := args[0]

cmd/root.go

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,33 +16,6 @@ import (
1616
// Version is the pgroll version
1717
var Version = "development"
1818

19-
func init() {
20-
viper.SetEnvPrefix("PGROLL")
21-
viper.AutomaticEnv()
22-
23-
rootCmd.PersistentFlags().String("postgres-url", "postgres://postgres:postgres@localhost?sslmode=disable", "Postgres URL")
24-
rootCmd.PersistentFlags().String("schema", "public", "Postgres schema to use for the migration")
25-
rootCmd.PersistentFlags().String("pgroll-schema", "pgroll", "Postgres schema to use for pgroll internal state")
26-
rootCmd.PersistentFlags().Int("lock-timeout", 500, "Postgres lock timeout in milliseconds for pgroll DDL operations")
27-
rootCmd.PersistentFlags().Int("backfill-batch-size", roll.DefaultBackfillBatchSize, "Number of rows backfilled in each batch")
28-
rootCmd.PersistentFlags().Duration("backfill-batch-delay", roll.DefaultBackfillDelay, "Duration of delay between batch backfills (eg. 1s, 1000ms)")
29-
rootCmd.PersistentFlags().String("role", "", "Optional postgres role to set when executing migrations")
30-
31-
viper.BindPFlag("PG_URL", rootCmd.PersistentFlags().Lookup("postgres-url"))
32-
viper.BindPFlag("SCHEMA", rootCmd.PersistentFlags().Lookup("schema"))
33-
viper.BindPFlag("STATE_SCHEMA", rootCmd.PersistentFlags().Lookup("pgroll-schema"))
34-
viper.BindPFlag("LOCK_TIMEOUT", rootCmd.PersistentFlags().Lookup("lock-timeout"))
35-
viper.BindPFlag("BACKFILL_BATCH_SIZE", rootCmd.PersistentFlags().Lookup("backfill-batch-size"))
36-
viper.BindPFlag("BACKFILL_BATCH_DELAY", rootCmd.PersistentFlags().Lookup("backfill-batch-delay"))
37-
viper.BindPFlag("ROLE", rootCmd.PersistentFlags().Lookup("role"))
38-
}
39-
40-
var rootCmd = &cobra.Command{
41-
Use: "pgroll",
42-
SilenceUsage: true,
43-
Version: Version,
44-
}
45-
4619
func NewRoll(ctx context.Context) (*roll.Roll, error) {
4720
pgURL := flags.PostgresURL()
4821
schema := flags.Schema()
@@ -67,8 +40,32 @@ func NewRoll(ctx context.Context) (*roll.Roll, error) {
6740
)
6841
}
6942

70-
// Execute executes the root command.
71-
func Execute() error {
43+
func Prepare() *cobra.Command {
44+
rootCmd := &cobra.Command{
45+
Use: "pgroll",
46+
SilenceUsage: true,
47+
Version: Version,
48+
}
49+
50+
viper.SetEnvPrefix("PGROLL")
51+
viper.AutomaticEnv()
52+
53+
rootCmd.PersistentFlags().String("postgres-url", "postgres://postgres:postgres@localhost?sslmode=disable", "Postgres URL")
54+
rootCmd.PersistentFlags().String("schema", "public", "Postgres schema to use for the migration")
55+
rootCmd.PersistentFlags().String("pgroll-schema", "pgroll", "Postgres schema to use for pgroll internal state")
56+
rootCmd.PersistentFlags().Int("lock-timeout", 500, "Postgres lock timeout in milliseconds for pgroll DDL operations")
57+
rootCmd.PersistentFlags().Int("backfill-batch-size", roll.DefaultBackfillBatchSize, "Number of rows backfilled in each batch")
58+
rootCmd.PersistentFlags().Duration("backfill-batch-delay", roll.DefaultBackfillDelay, "Duration of delay between batch backfills (eg. 1s, 1000ms)")
59+
rootCmd.PersistentFlags().String("role", "", "Optional postgres role to set when executing migrations")
60+
61+
viper.BindPFlag("PG_URL", rootCmd.PersistentFlags().Lookup("postgres-url"))
62+
viper.BindPFlag("SCHEMA", rootCmd.PersistentFlags().Lookup("schema"))
63+
viper.BindPFlag("STATE_SCHEMA", rootCmd.PersistentFlags().Lookup("pgroll-schema"))
64+
viper.BindPFlag("LOCK_TIMEOUT", rootCmd.PersistentFlags().Lookup("lock-timeout"))
65+
viper.BindPFlag("BACKFILL_BATCH_SIZE", rootCmd.PersistentFlags().Lookup("backfill-batch-size"))
66+
viper.BindPFlag("BACKFILL_BATCH_DELAY", rootCmd.PersistentFlags().Lookup("backfill-batch-delay"))
67+
viper.BindPFlag("ROLE", rootCmd.PersistentFlags().Lookup("role"))
68+
7269
// register subcommands
7370
rootCmd.AddCommand(startCmd())
7471
rootCmd.AddCommand(completeCmd)
@@ -81,5 +78,11 @@ func Execute() error {
8178
rootCmd.AddCommand(latestCmd())
8279
rootCmd.AddCommand(sqlCmd())
8380

84-
return rootCmd.Execute()
81+
return rootCmd
82+
}
83+
84+
// Execute executes the root command.
85+
func Execute() error {
86+
cmd := Prepare()
87+
return cmd.Execute()
8588
}

cmd/sql.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ import (
1313

1414
func sqlCmd() *cobra.Command {
1515
sqlCmd := &cobra.Command{
16-
Use: "sql <sql statement>",
17-
Short: "Convert SQL statements to pgroll operations",
18-
Args: cobra.ExactArgs(1),
19-
Hidden: true,
16+
Use: "sql <sql statement>",
17+
Short: "Convert SQL statements to pgroll operations",
18+
Args: cobra.ExactArgs(1),
19+
ValidArgs: []string{"statement"},
20+
Hidden: true,
2021
RunE: func(cmd *cobra.Command, args []string) error {
2122
sql := args[0]
2223

cmd/start.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ func startCmd() *cobra.Command {
2121
var complete bool
2222

2323
startCmd := &cobra.Command{
24-
Use: "start <file>",
25-
Short: "Start a migration for the operations present in the given file",
26-
Args: cobra.ExactArgs(1),
24+
Use: "start <file>",
25+
Short: "Start a migration for the operations present in the given file",
26+
Args: cobra.ExactArgs(1),
27+
ValidArgs: []string{"file"},
2728
RunE: func(cmd *cobra.Command, args []string) error {
2829
fileName := args[0]
2930

0 commit comments

Comments
 (0)