diff --git a/.goreleaser.yml b/.goreleaser.yml
index 54e73ff3..82ab262c 100644
--- a/.goreleaser.yml
+++ b/.goreleaser.yml
@@ -63,7 +63,7 @@ source:
enabled: true
snapshot:
- name_template: "next"
+ version_template: "next"
universal_binaries:
- replace: true
diff --git a/README.md b/README.md
index 198d9965..a84d6fad 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,7 @@ Security Issues
If you discover a security vulnerability, please follow our [disclosure procedure][11].
-Sponsorship [
](https://cloudsmith.io/)
+Sponsorship [
](https://cloudsmith.io/)
-----------
Package repository hosting is graciously provided by
diff --git a/commands/local_server_start.go b/commands/local_server_start.go
index 04ddf087..5e24c816 100644
--- a/commands/local_server_start.go
+++ b/commands/local_server_start.go
@@ -52,6 +52,7 @@ import (
var localWebServerProdWarningMsg = "The local web server is optimized for local development and MUST never be used in a production setup."
var localWebServerTlsKeyLogWarningMsg = "Logging TLS master key is enabled. It means TLS connections between the client and this server will be INSECURE. This is NOT recommended unless you are debugging the connections."
+var localWebServerAllowsCORSLogWarningMsg = "Cross-origin resource sharing (CORS) is enabled for all requests.\nYou may want to use https://github.com/nelmio/NelmioCorsBundle to have better control over HTTP headers."
var localServerStartCmd = &console.Command{
Category: "local",
@@ -83,6 +84,7 @@ var localServerStartCmd = &console.Command{
EnvVars: []string{"SSLKEYLOGFILE"},
},
&console.BoolFlag{Name: "no-workers", Usage: "Do not start workers"},
+ &console.BoolFlag{Name: "allow-cors", Usage: "Allow Cross-origin resource sharing (CORS) requests"},
},
Action: func(c *console.Context) error {
ui := terminal.SymfonyStyle(terminal.Stdout, terminal.Stdin)
@@ -188,6 +190,10 @@ var localServerStartCmd = &console.Command{
ui.Warning(localWebServerTlsKeyLogWarningMsg)
}
+ if config.AllowCORS {
+ ui.Warning(localWebServerAllowsCORSLogWarningMsg)
+ }
+
lw, err := pidFile.LogWriter()
if err != nil {
return err
diff --git a/envs/local.go b/envs/local.go
index b687f7c8..2eee8089 100644
--- a/envs/local.go
+++ b/envs/local.go
@@ -48,7 +48,7 @@ func NewLocal(path string, debug bool) (*Local, error) {
return nil, errors.WithStack(err)
}
return &Local{
- Dir: guessProjectDir(path),
+ Dir: path,
Debug: debug,
}, nil
}
@@ -283,20 +283,3 @@ func (l *Local) webServer() Envs {
return env
}
-
-func guessProjectDir(dir string) string {
- for {
- f, err := os.Stat(filepath.Join(dir, ".git"))
- if err == nil && f.IsDir() {
- return dir
- }
-
- upDir := filepath.Dir(dir)
- if upDir == dir || upDir == "." {
- break
- }
- dir = upDir
- }
-
- return ""
-}
diff --git a/local/http/cors.go b/local/http/cors.go
new file mode 100644
index 00000000..56abf2bd
--- /dev/null
+++ b/local/http/cors.go
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021-present Fabien Potencier
+ *
+ * This file is part of Symfony CLI project
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package http
+
+import (
+ "net/http"
+
+ "github.com/rs/zerolog"
+)
+
+func corsWrapper(h http.Handler, logger zerolog.Logger) http.Handler {
+ var corsHeaders = []string{"Access-Control-Allow-Origin", "Access-Control-Allow-Methods", "Access-Control-Allow-Headers"}
+
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ for _, corsHeader := range corsHeaders {
+ w.Header().Set(corsHeader, "*")
+ }
+
+ h.ServeHTTP(w, r)
+
+ for _, corsHeader := range corsHeaders {
+ if headers, exists := w.Header()[corsHeader]; !exists || len(headers) < 2 {
+ continue
+ }
+
+ logger.Warn().Msgf(`Multiple entries detected for header "%s". Only one should be set: you should enable CORS handling in the CLI only if the application does not handle them.`, corsHeader)
+ }
+ })
+}
diff --git a/local/http/http.go b/local/http/http.go
index 859dd25b..650ed678 100644
--- a/local/http/http.go
+++ b/local/http/http.go
@@ -56,6 +56,7 @@ type Server struct {
Appversion string
UseGzip bool
TlsKeyLogFile string
+ AllowCORS bool
httpserver *http.Server
httpsserver *http.Server
@@ -98,6 +99,10 @@ func (s *Server) Start(errChan chan error) (int, error) {
proxyHandler = gzipWrapper(proxyHandler)
}
+ if s.AllowCORS {
+ proxyHandler = corsWrapper(proxyHandler, s.Logger)
+ }
+
s.httpserver = &http.Server{
Handler: proxyHandler,
}
diff --git a/local/php/symfony.go b/local/php/symfony.go
index 14e83c22..4ae705f0 100644
--- a/local/php/symfony.go
+++ b/local/php/symfony.go
@@ -4,24 +4,34 @@ import (
"os"
"github.com/pkg/errors"
+ "path/filepath"
)
// ComposerExecutor returns an Executor prepared to run Symfony Console.
// It returns an error if no console binary is found.
func SymonyConsoleExecutor(args []string) (*Executor, error) {
- consolePath := "bin/console"
+ dir, err := os.Getwd()
+ if err != nil {
+ return nil, errors.WithStack(err)
+ }
- if _, err := os.Stat(consolePath); err != nil {
- // Fallback to app/console for projects created with older versions of Symfony
- consolePath = "app/console"
+ for {
+ for _, consolePath := range []string{"bin/console", "app/console"} {
+ consolePath = filepath.Join(dir, consolePath)
+ if _, err := os.Stat(consolePath); err == nil {
+ return &Executor{
+ BinName: "php",
+ Args: append([]string{"php", consolePath}, args...),
+ }, nil
+ }
+ }
- if _, err2 := os.Stat(consolePath); err2 != nil {
- return nil, errors.WithStack(err)
+ upDir := filepath.Dir(dir)
+ if upDir == dir || upDir == "." {
+ break
}
+ dir = upDir
}
- return &Executor{
- BinName: "php",
- Args: append([]string{"php", consolePath}, args...),
- }, nil
+ return nil, errors.New("No console binary found")
}
diff --git a/local/platformsh/commands.go b/local/platformsh/commands.go
index 7123ad78..a1a03d75 100644
--- a/local/platformsh/commands.go
+++ b/local/platformsh/commands.go
@@ -1772,6 +1772,7 @@ var Commands = []*console.Command{
&console.BoolFlag{Name: "no-header",},
&console.StringFlag{Name: "org", Aliases: []string{"o"},},
&console.StringFlag{Name: "project", Aliases: []string{"p"},},
+ &console.BoolFlag{Name: "refresh",},
},
},
{
@@ -1941,6 +1942,7 @@ var Commands = []*console.Command{
Flags: []console.Flag{
&console.StringFlag{Name: "default-branch", DefaultValue: "main",},
&console.StringFlag{Name: "environments",},
+ &console.StringFlag{Name: "init-repo",},
&console.BoolFlag{Name: "no-set-remote",},
&console.StringFlag{Name: "org", Aliases: []string{"o"},},
&console.StringFlag{Name: "plan",},
diff --git a/local/platformsh/config.go b/local/platformsh/config.go
index aa6f3681..bb6b5402 100644
--- a/local/platformsh/config.go
+++ b/local/platformsh/config.go
@@ -105,7 +105,7 @@ var availablePHPExts = map[string][]string{
"snmp": {"5.4", "5.5", "5.6", "7.0", "7.1", "7.2", "7.3", "7.4", "8.0", "8.1", "8.2", "8.3"},
"soap": {"7.0", "7.1", "7.2", "7.3", "7.4", "8.0", "8.1", "8.2", "8.3", "8.4"},
"sockets": {"7.0", "7.1", "7.2", "7.3", "7.4", "8.0", "8.1", "8.2", "8.3", "8.4"},
- "sodium": {"7.2", "7.3", "7.4", "8.0", "8.1", "8.2", "8.3"},
+ "sodium": {"7.2", "7.3", "7.4", "8.0", "8.1", "8.2", "8.3", "8.4"},
"sourceguardian": {"7.0", "7.1", "7.2", "7.3", "7.4", "8.0", "8.1", "8.2", "8.3", "8.4"},
"spplus": {"5.4", "5.5"},
"sqlite3": {"5.4", "5.5", "5.6", "7.0", "7.1", "7.2", "7.3", "7.4", "8.0", "8.1", "8.2", "8.3", "8.4"},
@@ -253,7 +253,7 @@ var availableServices = []*service{
Type: "varnish",
Versions: serviceVersions{
Deprecated: []string{"5.1", "5.2", "6.3", "6.4", "7.1"},
- Supported: []string{"6.0", "7.2", "7.3"},
+ Supported: []string{"6.0", "7.2", "7.3", "7.6"},
},
},
{
diff --git a/local/project/config.go b/local/project/config.go
index 307f01bf..82049342 100644
--- a/local/project/config.go
+++ b/local/project/config.go
@@ -49,6 +49,7 @@ type Config struct {
UseGzip bool `yaml:"use_gzip"`
TlsKeyLogFile string `yaml:"tls_key_log_file"`
NoWorkers bool `yaml:"no_workers"`
+ AllowCORS bool `yaml:"allow_cors"`
}
type FileConfig struct {
@@ -122,6 +123,9 @@ func NewConfigFromContext(c *console.Context, projectDir string) (*Config, *File
if c.IsSet("no-workers") {
config.NoWorkers = c.Bool("no-workers")
}
+ if c.IsSet("allow-cors") {
+ config.AllowCORS = c.Bool("allow-cors")
+ }
return config, fileConfig, nil
}
diff --git a/local/project/project.go b/local/project/project.go
index a4fbbc88..53ad6e9f 100644
--- a/local/project/project.go
+++ b/local/project/project.go
@@ -63,6 +63,7 @@ func New(c *Config) (*Project, error) {
UseGzip: c.UseGzip,
Appversion: c.AppVersion,
TlsKeyLogFile: c.TlsKeyLogFile,
+ AllowCORS: c.AllowCORS,
},
}
if err != nil {