8000 Check that the DB version is set before deploying · glengemann/symfony-cli@5e6c0fa · GitHub
[go: up one dir, main page]

Skip to content

Commit 5e6c0fa

Browse files
committed
Check that the DB version is set before deploying
1 parent f0e4ef1 commit 5e6c0fa

File tree

3 files changed

+141
-1
lines changed

3 files changed

+141
-1
lines changed

commands/db_versions.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package commands
2+
3+
import (
4+
"io/ioutil"
5+
"path/filepath"
6+
"strings"
7+
8+
"gopkg.in/yaml.v2"
9+
)
10+
11+
func readDBVersionFromPlatformServiceYAML(projectDir string) (string, string, error) {
12+
servicesYAML, err := ioutil.ReadFile(filepath.Join(projectDir, ".platform", "services.yaml"))
13+
if err != nil {
14+
// no services.yaml or unreadable
15+
return "", "", err
16+
}
17+
var services map[string]struct {
18+
Type string `yaml:"type"`
19+
}
20+
if err := yaml.Unmarshal(servicesYAML, &services); err != nil {
21+
// services.yaml format is wrong
22+
return "", "", err
23+
}
24+
25+
dbName := ""
26+
dbVersion := ""
27+
for _, service := range services {
28+
if strings.HasPrefix(service.Type, "mysql") || strings.HasPrefix(service.Type, "mariadb") || strings.HasPrefix(service.Type, "postgresql") {
29+
if dbName != "" {
30+
// give up as there are multiple DBs
31+
return "", "", nil
32+
}
33+
34+
parts := strings.Split(service.Type, ":")
35+
dbName = parts[0]
36+
dbVersion = parts[1]
37+
}
38+
}
39+
return dbName, dbVersion, nil
40+
}
41+
42+
func readDBVersionFromDotEnv(projectDir string) (string, error) {
43+
dotEnv, err := ioutil.ReadFile(filepath.Join(projectDir, ".env"))
44+
if err != nil {
45+
return "", err
46+
}
47+
48+
lines := strings.Split(string(dotEnv), "\n")
49+
for _, line := range lines {
50+
if !strings.HasPrefix(line, "DATABASE_URL=") {
51+
continue
52+
}
53+
if !strings.Contains(line, "serverVersion=") {
54+
return "", nil
55+
}
56+
return strings.TrimRight(strings.Split(strings.Split(line, "serverVersion=")[1], "&")[0], "\""), nil
57+
}
58+
return "", nil
59+
}
60+
61+
func readDBVersionFromDoctrineConfigYAML(projectDir string) (string, error) {
62+
doctrineConfigYAML, err := ioutil.ReadFile(filepath.Join(projectDir, "config", "packages", "doctrine.yaml"))
63+
if err != nil {
64+
return "", err
65+
}
66+
67+
var doctrineConfig struct {
68+
Doctrine struct {
69+
Dbal struct {
70+
ServerVersion string `yaml:"server_version"`
71+
} `yaml:"dbal"`
72+
} `yaml:"doctrine"`
73+
}
74+
if err := yaml.Unmarshal(doctrineConfigYAML, &doctrineConfig); err != nil {
75+
// format is wrong
76+
return "", err
77+
}
78+
return doctrineConfig.Doctrine.Dbal.ServerVersion, nil
79+
}

commands/platformsh_hooks.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,75 @@
11
package commands
22

33
import (
4+
"errors"
5+
"fmt"
6+
47
"github.com/symfony-cli/console"
58
"github.com/symfony-cli/symfony-cli/envs"
69
"github.com/symfony-cli/symfony-cli/local/platformsh"
710
"github.com/symfony-cli/terminal"
811
)
912

1013
var platformshBeforeHooks = map[string]console.BeforeFunc{
14+
"cloud:environment:push": func(c *console.Context) error {
15+
// check that project has a DB and that server version is set properly
16+
projectDir, err := getProjectDir(c.String("dir"))
17+
if err != nil {
18+
return err
19+
}
20+
if len(platformsh.FindLocalApplications(projectDir)) > 0 {
21+
// not implemented yet as more complex
22+
return nil
23+
}
24+
25+
dbName, dbVersion, err := readDBVersionFromPlatformServiceYAML(projectDir)
26+
if err != nil {
27+
return nil
28+
}
29+
if dbName == "" {
30+
// no DB
31+
return nil
32+
}
33+
34+
errorTpl := fmt.Sprintf(`
35+
The ".platform/services.yaml" file defines
36+
a "%s" version %s database service
37+
but %%s.
38+
39+
Before deploying, fix the version mismatch.
40+
`, dbName, dbVersion)
41+
42+
dotEnvVersion, err := readDBVersionFromDotEnv(projectDir)
43+
if err != nil {
44+
return nil
45+
}
46+
if dotEnvVersion != "" && dotEnvVersion != dbVersion {
47+
return fmt.Errorf(errorTpl, fmt.Sprintf("the \".env\" file requires version %s", dotEnvVersion))
48+
}
49+
50+
doctrineConfigVersion, err := readDBVersionFromDoctrineConfigYAML(projectDir)
51+
if err != nil {
52+
return nil
53+
}
54+
if doctrineConfigVersion != "" && doctrineConfigVersion != dbVersion {
55+
return fmt.Errorf(errorTpl, fmt.Sprintf("the \"config/packages/doctrine.yaml\" file requires version %s", doctrineConfigVersion))
56+
}
57+
58+
if dotEnvVersion == "" && doctrineConfigVersion == "" {
59+
return errors.New(`
60+
The ".platform/services.yaml" file defines a "%s" database service.
61+
62+
When deploying, Doctrine needs to know the database version to determine the supported SQL syntax.
63+
64+
As the database is not available when Doctrine is warming up its cache on Platform.sh,
65+
you need to explicitely set the database version in the ".env" or "config/packages/doctrine.yaml" file.
66+
67+
The easiest is to set the "serverVersion" parameter in the "config/packages/doctrine.yaml" file.
68+
`)
69+
}
70+
71+
return nil
72+
},
1173
"cloud:tunnel:close": func(c *console.Context) error {
1274
terminal.Eprintln("Stop exposing tunnel service environment variables")
1375

commands/root.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,6 @@ Environment variables to use Platform.sh relationships or Docker services are au
183183
}
184184

185185
func getProjectDir(dir string) (string, error) {
186-
187186
var err error
188187
if dir, err = filepath.Abs(dir); err != nil {
189188
return "", err

0 commit comments

Comments
 (0)
0