diff --git a/api/controllers/builds.go b/api/controllers/builds.go index ea69b51fd4..0b16ab64bc 100644 --- a/api/controllers/builds.go +++ b/api/controllers/builds.go @@ -135,10 +135,22 @@ func BuildUpdate(rw http.ResponseWriter, r *http.Request) *httperr.Error { return httperr.Server(err) } - b.Ended = time.Now() - b.Manifest = r.FormValue("manifest") - b.Reason = r.FormValue("reason") - b.Status = r.FormValue("status") + if d := r.FormValue("description"); d != "" { + b.Description = d + } + + if m := r.FormValue("manifest"); m != "" { + b.Manifest = m + } + + if r := r.FormValue("reason"); r != "" { + b.Reason = r + } + + if s := r.FormValue("status"); s != "" { + b.Status = s + b.Ended = time.Now() + } // if build was successful create a release if b.Status == "complete" && b.Manifest != "" { @@ -146,8 +158,11 @@ func BuildUpdate(rw http.ResponseWriter, r *http.Request) *httperr.Error { if err != nil { return httperr.Server(err) } - } else { - provider.BuildSave(b) + } + + err = provider.BuildSave(b) + if err != nil { + return httperr.Server(err) } return RenderJson(rw, b) diff --git a/api/manifest.yml b/api/manifest.yml index 09436a92c3..2ff3cd3368 100644 --- a/api/manifest.yml +++ b/api/manifest.yml @@ -191,6 +191,48 @@ paths: description: not found schema: $ref: '#/definitions/error' + put: + description: Update build status + parameters: + - name: app + description: app name + type: string + in: path + required: true + - name: build + description: build id + type: string + in: path + required: true + - name: description + description: build description + type: string + in: formData + required: false + - name: manifest + description: release manifest extracted during build + type: string + in: formData + required: false + - name: reason + description: reason with status "failed" + type: string + in: formData + required: false + - name: status + description: final build status "complete" or "failed" + type: string + in: formData + required: false + responses: + 200: + description: build + schema: + $ref: '#/definitions/build' + 404: + description: not found + schema: + $ref: '#/definitions/error' /apps/{app}/environment: get: description: List environment for an app diff --git a/api/manifest/manifest.go b/api/manifest/manifest.go index 33e9e894dc..c98f9afb94 100644 --- a/api/manifest/manifest.go +++ b/api/manifest/manifest.go @@ -35,6 +35,8 @@ var ( Stderr = io.Writer(os.Stderr) Execer = exec.Command SignalWaiter = waitForSignal + + regexValidProcessName = regexp.MustCompile(`\A[a-zA-Z0-9][-a-zA-Z0-9]{0,29}\z`) // 'web', '1', 'web-1' valid; '-', 'web_1' invalid ) var ( @@ -157,6 +159,10 @@ func Read(dir, filename string) (*Manifest, error) { } for name, entry := range m { + if !regexValidProcessName.MatchString(name) { + return &m, fmt.Errorf("process name %q is invalid. It should contain only alphanumeric characters and dashes.", name) + } + for i, volume := range entry.Volumes { parts := strings.Split(volume, ":") @@ -218,7 +224,6 @@ func (m *Manifest) Build(app, dir string, cache bool) []error { builds := map[string]string{} pulls := []string{} tags := map[string]string{} - dockerfiles := map[string]string{} for name, entry := range *m { tag := fmt.Sprintf("%s/%s", app, name) @@ -232,21 +237,22 @@ func (m *Manifest) Build(app, dir string, cache bool) []error { } sym, err := filepath.EvalSymlinks(abs) - if err != nil { return []error{err} } - if _, ok := builds[sym]; !ok { - builds[sym] = randomString("convox-", 10) + + df := "Dockerfile" + if entry.Dockerfile != "" { + df = entry.Dockerfile } - tags[tag] = builds[sym] + sym = filepath.Join(sym, df) - // Dockerfile can only be specified if Build is also specified - if entry.Dockerfile != "" { - dockerfiles[sym] = entry.Dockerfile + if _, ok := builds[sym]; !ok { + builds[sym] = randomString("convox-", 10) } + tags[tag] = builds[sym] case entry.Image != "": err := Execer("docker", "inspect", entry.Image).Run() @@ -260,8 +266,9 @@ func (m *Manifest) Build(app, dir string, cache bool) []error { errors := []error{} - for source, tag := range builds { - err := buildSync(source, tag, cache, dockerfiles[source]) + for path, tag := range builds { + source, dockerfile := filepath.Split(path) + err := buildSync(source, tag, cache, dockerfile) if err != nil { return []error{err}