Example #1
0
File: app.go Project: convox/rack
func (a *App) ForkRelease() (*Release, error) {
	release := structs.NewRelease(a.Name)

	if a.Release != "" {
		r, err := Provider().ReleaseGet(a.Name, a.Release)
		if err != nil {
			return nil, err
		}
		release = r
	}

	release.Id = generateId("R", 10)
	release.Created = time.Now()

	env, err := Provider().EnvironmentGet(a.Name)
	if err != nil {
		fmt.Printf("fn=ForkRelease level=error msg=\"error getting environment: %s\"", err)
	}

	release.Env = env.Raw()

	return &Release{
		Id:       release.Id,
		App:      release.App,
		Build:    release.Build,
		Env:      release.Env,
		Manifest: release.Manifest,
		Created:  release.Created,
	}, nil
}
Example #2
0
// ForkRelease creates a new release based on the app's release
func ForkRelease(app *structs.App) (*structs.Release, error) {
	release := structs.NewRelease(app.Name)

	if app.Release != "" {
		r, err := models.Provider().ReleaseGet(app.Name, app.Release)
		if err != nil {
			return nil, err
		}
		id := release.Id
		created := release.Created

		release = r
		release.Id = id
		release.Created = created
	}

	env, err := models.Provider().EnvironmentGet(app.Name)
	if err != nil {
		fmt.Printf("fn=ForkRelease level=error msg=\"error getting environment: %s\"", err)
	}

	release.Env = env.Raw()

	return &structs.Release{
		Id:       release.Id,
		App:      release.App,
		Build:    release.Build,
		Env:      release.Env,
		Manifest: release.Manifest,
		Created:  release.Created,
	}, nil
}
Example #3
0
func (p *AWSProvider) BuildRelease(b *structs.Build) (*structs.Release, error) {
	releases, err := p.ReleaseList(b.App)
	if err != nil {
		return nil, err
	}

	r := structs.NewRelease(b.App)
	newId := r.Id

	if len(releases) > 0 {
		r = &releases[0]
	}

	r.Id = newId
	r.Created = time.Time{}
	r.Build = b.Id
	r.Manifest = b.Manifest

	a, err := p.AppGet(b.App)
	if err != nil {
		return r, err
	}

	err = p.ReleaseSave(r, a.Outputs["Settings"], a.Parameters["Key"])
	if err != nil {
		return r, err
	}

	b.Release = r.Id
	err = p.BuildSave(b)

	if err == nil {
		p.EventSend(&structs.Event{
			Action: "release:create",
			Data: map[string]string{
				"app": r.App,
				"id":  r.Id,
			},
		}, nil)
	}

	return r, err
}
Example #4
0
// BuildImport imports a build artifact
func (p *AWSProvider) BuildImport(app string, r io.Reader) (*structs.Build, error) {
	log := Logger.At("BuildImport").Namespace("app=%s", app).Start()

	var sourceBuild structs.Build

	// set up the new build
	targetBuild := structs.NewBuild(app)
	targetBuild.Started = time.Now()
	targetBuild.Status = "complete"

	if p.IsTest() {
		targetBuild.Id = "B12345"
	}

	repo, err := p.appRepository(app)
	if err != nil {
		log.Error(err)
		return nil, err
	}

	if err := p.dockerLogin(); err != nil {
		log.Error(err)
		return nil, err
	}

	gz, err := gzip.NewReader(r)
	if err != nil {
		log.Error(err)
		return nil, err
	}

	tr := tar.NewReader(gz)

	for {
		header, err := tr.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Error(err)
			return nil, err
		}
		if header.Typeflag != tar.TypeReg {
			continue
		}

		if header.Name == "build.json" {
			var buf bytes.Buffer

			io.Copy(&buf, tr)

			if err := json.Unmarshal(buf.Bytes(), &sourceBuild); err != nil {
				log.Error(err)
				return nil, err
			}
		}

		if strings.HasSuffix(header.Name, ".tar") {
			log.Step("load").Logf("tar=%q", header.Name)

			cmd := exec.Command("docker", "load")

			pr, pw := io.Pipe()
			tee := io.TeeReader(tr, pw)
			outb := &bytes.Buffer{}

			cmd.Stdin = pr
			cmd.Stdout = outb

			if err := cmd.Start(); err != nil {
				log.Error(err)
				return nil, err
			}

			log.Step("manifest").Logf("tar=%q", header.Name)
			manifest, err := extractImageManifest(tee)
			if err != nil {
				log.Error(err)
				return nil, err
			}

			if err := pw.Close(); err != nil {
				log.Error(err)
				return nil, err
			}

			if err := cmd.Wait(); err != nil {
				return nil, log.Errorf("%s: %s\n", lastline(outb.Bytes()), err.Error())
			}

			if len(manifest) != 1 || len(manifest[0].RepoTags) != 1 {
				log.Errorf("invalid image manifest")
				return nil, fmt.Errorf("invalid image manifest")
			}

			image := manifest[0].RepoTags[0]
			ps := strings.Split(header.Name, ".")[0]
			target := fmt.Sprintf("%s:%s.%s", repo.URI, ps, targetBuild.Id)

			log.Step("tag").Logf("from=%q to=%q", image, target)
			if out, err := exec.Command("docker", "tag", image, target).CombinedOutput(); err != nil {
				return nil, log.Error(fmt.Errorf("%s: %s\n", lastline(out), err.Error()))
			}

			log.Step("push").Logf("to=%q", target)
			if out, err := exec.Command("docker", "push", target).CombinedOutput(); err != nil {
				return nil, log.Error(fmt.Errorf("%s: %s\n", lastline(out), err.Error()))
			}
		}
	}

	env, err := p.EnvironmentGet(app)
	if err != nil {
		log.Error(err)
		return nil, err
	}

	release := structs.NewRelease(app)

	if p.IsTest() {
		release.Id = "R23456"
	}

	targetBuild.Description = sourceBuild.Description
	targetBuild.Ended = time.Now()
	targetBuild.Logs = sourceBuild.Logs
	targetBuild.Manifest = sourceBuild.Manifest
	targetBuild.Release = release.Id

	if err := p.BuildSave(targetBuild); err != nil {
		log.Error(err)
		return nil, err
	}

	release.Env = env.Raw()
	release.Build = targetBuild.Id
	release.Manifest = targetBuild.Manifest

	if err := p.ReleaseSave(release); err != nil {
		log.Error(err)
		return nil, err
	}

	log.Successf("build=%q release=%q", targetBuild.Id, release.Id)

	return targetBuild, nil
}