Skip to content

Commit b7e54ed

Browse files
FEATURE: add migrate and bootstrap commands (#842)
Adds command for migrate only. Adds batch commands for bootstrap (build+migrate+configure)
1 parent 7c18fce commit b7e54ed

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed

launcher_go/v2/cli_build.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,51 @@ func (r *DockerConfigureCmd) Run(cli *Cli, ctx *context.Context) error {
9090
return pups.Run()
9191
}
9292

93+
type DockerMigrateCmd struct {
94+
Config string `arg:"" name:"config" help:"config" predictor:"config"`
95+
SkipPostDeploymentMigrations bool `env:"SKIP_POST_DEPLOYMENT_MIGRATIONS" help:"Skip post-deployment migrations. Runs safe migrations only. Defers breaking-change migrations. Make sure you run post-deployment migrations after a full deploy is complete if you use this option."`
96+
}
97+
98+
func (r *DockerMigrateCmd) Run(cli *Cli, ctx *context.Context) error {
99+
config, err := config.LoadConfig(cli.ConfDir, r.Config, true, cli.TemplatesDir)
100+
if err != nil {
101+
return errors.New("YAML syntax error. Please check your containers/*.yml config files.")
102+
}
103+
containerId := "discourse-build-" + uuid.NewString()
104+
env := []string{"SKIP_EMBER_CLI_COMPILE=1"}
105+
if r.SkipPostDeploymentMigrations {
106+
env = append(env, "SKIP_POST_DEPLOYMENT_MIGRATIONS=1")
107+
}
108+
pups := docker.DockerPupsRunner{
109+
Config: config,
110+
PupsArgs: "--tags=db,migrate",
111+
ExtraEnv: env,
112+
Ctx: ctx,
113+
ContainerId: containerId,
114+
}
115+
return pups.Run()
116+
}
117+
118+
type DockerBootstrapCmd struct {
119+
Config string `arg:"" name:"config" help:"config" predictor:"config"`
120+
}
121+
122+
func (r *DockerBootstrapCmd) Run(cli *Cli, ctx *context.Context) error {
123+
buildStep := DockerBuildCmd{Config: r.Config, BakeEnv: false}
124+
migrateStep := DockerMigrateCmd{Config: r.Config}
125+
configureStep := DockerConfigureCmd{Config: r.Config}
126+
if err := buildStep.Run(cli, ctx); err != nil {
127+
return err
128+
}
129+
if err := migrateStep.Run(cli, ctx); err != nil {
130+
return err
131+
}
132+
if err := configureStep.Run(cli, ctx); err != nil {
133+
return err
134+
}
135+
return nil
136+
}
137+
93138
type CleanCmd struct {
94139
Config string `arg:"" name:"config" help:"config to clean" predictor:"config"`
95140
}

launcher_go/v2/cli_build_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,19 @@ var _ = Describe("Build", func() {
5858
Expect(buf.String()).ToNot(ContainSubstring("SKIP_EMBER_CLI_COMPILE=1"))
5959
}
6060

61+
var checkMigrateCmd = func(cmd exec.Cmd) {
62+
Expect(cmd.String()).To(ContainSubstring("docker run"))
63+
Expect(cmd.String()).To(ContainSubstring("--env DISCOURSE_DEVELOPER_EMAILS"))
64+
Expect(cmd.String()).To(ContainSubstring("--env SKIP_EMBER_CLI_COMPILE=1"))
65+
// no commit after, we expect an --rm as the container isn't needed after it is stopped
66+
Expect(cmd.String()).To(ContainSubstring("--rm"))
67+
Expect(cmd.Env).To(ContainElement("DISCOURSE_DB_PASSWORD=SOME_SECRET"))
68+
buf := new(strings.Builder)
69+
io.Copy(buf, cmd.Stdin)
70+
// docker run's stdin is a pups config
71+
Expect(buf.String()).To(ContainSubstring("path: /etc/service/nginx/run"))
72+
}
73+
6174
var checkConfigureCmd = func(cmd exec.Cmd) {
6275
Expect(cmd.String()).To(Equal(
6376
"/usr/local/bin/docker run " +
@@ -151,6 +164,31 @@ var _ = Describe("Build", func() {
151164
checkBuildCmd(RanCmds[0])
152165
})
153166

167+
It("Should run docker migrate with correct arguments", func() {
168+
runner := ddocker.DockerMigrateCmd{Config: "test"}
169+
runner.Run(cli, &ctx)
170+
Expect(len(RanCmds)).To(Equal(1))
171+
checkMigrateCmd(RanCmds[0])
172+
})
173+
174+
It("Should allow skip post deployment migrations", func() {
175+
runner := ddocker.DockerMigrateCmd{Config: "test", SkipPostDeploymentMigrations: true}
176+
runner.Run(cli, &ctx)
177+
Expect(len(RanCmds)).To(Equal(1))
178+
cmd := RanCmds[0]
179+
Expect(cmd.String()).To(ContainSubstring("docker run"))
180+
Expect(cmd.String()).To(ContainSubstring("--env DISCOURSE_DEVELOPER_EMAILS"))
181+
Expect(cmd.String()).To(ContainSubstring("--env SKIP_POST_DEPLOYMENT_MIGRATIONS=1"))
182+
Expect(cmd.String()).To(ContainSubstring("--env SKIP_EMBER_CLI_COMPILE=1"))
183+
// no commit after, we expect an --rm as the container isn't needed after it is stopped
184+
Expect(cmd.String()).To(ContainSubstring("--rm"))
185+
Expect(cmd.Env).To(ContainElement("DISCOURSE_DB_PASSWORD=SOME_SECRET"))
186+
buf := new(strings.Builder)
187+
io.Copy(buf, cmd.Stdin)
188+
// docker run's stdin is a pups config
189+
Expect(buf.String()).To(ContainSubstring("path: /etc/service/nginx/run"))
190+
})
191+
154192
It("Should run docker run followed by docker commit and rm container when configuring", func() {
155193
runner := ddocker.DockerConfigureCmd{Config: "test"}
156194
runner.Run(cli, &ctx)
@@ -160,5 +198,16 @@ var _ = Describe("Build", func() {
160198
checkConfigureCommit(RanCmds[1])
161199
checkConfigureClean(RanCmds[2])
162200
})
201+
202+
It("Should run all docker commands for full bootstrap", func() {
203+
runner := ddocker.DockerBootstrapCmd{Config: "test"}
204+
runner.Run(cli, &ctx)
205+
Expect(len(RanCmds)).To(Equal(5))
206+
checkBuildCmd(RanCmds[0])
207+
checkMigrateCmd(RanCmds[1])
208+
checkConfigureCmd(RanCmds[2])
209+
checkConfigureCommit(RanCmds[3])
210+
checkConfigureClean(RanCmds[4])
211+
})
163212
})
164213
})

launcher_go/v2/main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ type Cli struct {
1818
BuildDir string `default:"./tmp" hidden:"" help:"Temporary build folder for building images." predictor:"dir"`
1919
BuildCmd DockerBuildCmd `cmd:"" name:"build" help:"Build a base image. This command does not need a running database. Saves resulting container."`
2020
ConfigureCmd DockerConfigureCmd `cmd:"" name:"configure" help:"Configure and save an image with all dependencies and environment baked in. Updates themes and precompiles all assets. Saves resulting container."`
21+
MigrateCmd DockerMigrateCmd `cmd:"" name:"migrate" help:"Run migration tasks for a site. Running container is temporary and is not saved."`
22+
BootstrapCmd DockerBootstrapCmd `cmd:"" name:"bootstrap" help:"Builds, migrates, and configures an image. Resulting image is a fully built and configured Discourse image."`
2123
}
2224

2325
func main() {

0 commit comments

Comments
 (0)