Beispiel #1
0
// BuildSave creates or updates a build item in DynamoDB. It takes an optional
// bucket argument, which if set indicates to PUT Log data into S3
func (p *AWSProvider) BuildSave(b *structs.Build) error {
	a, err := p.AppGet(b.App)
	if err != nil {
		return err
	}

	if b.Id == "" {
		return fmt.Errorf("Id can not be blank")
	}

	if b.Started.IsZero() {
		b.Started = time.Now()
	}

	req := &dynamodb.PutItemInput{
		Item: map[string]*dynamodb.AttributeValue{
			"id":      &dynamodb.AttributeValue{S: aws.String(b.Id)},
			"app":     &dynamodb.AttributeValue{S: aws.String(b.App)},
			"status":  &dynamodb.AttributeValue{S: aws.String(b.Status)},
			"created": &dynamodb.AttributeValue{S: aws.String(b.Started.Format(SortableTime))},
		},
		TableName: aws.String(buildsTable(b.App)),
	}

	if b.Description != "" {
		req.Item["description"] = &dynamodb.AttributeValue{S: aws.String(b.Description)}
	}

	if b.Manifest != "" {
		req.Item["manifest"] = &dynamodb.AttributeValue{S: aws.String(b.Manifest)}
	}

	if b.Release != "" {
		req.Item["release"] = &dynamodb.AttributeValue{S: aws.String(b.Release)}
	}

	if !b.Ended.IsZero() {
		req.Item["ended"] = &dynamodb.AttributeValue{S: aws.String(b.Ended.Format(SortableTime))}
	}

	if b.Logs != "" {
		_, err := p.s3().PutObject(&s3.PutObjectInput{
			Body:          bytes.NewReader([]byte(b.Logs)),
			Bucket:        aws.String(a.Outputs["Settings"]),
			ContentLength: aws.Int64(int64(len(b.Logs))),
			Key:           aws.String(fmt.Sprintf("builds/%s.log", b.Id)),
		})
		if err != nil {
			return err
		}
	}

	_, err = p.dynamodb().PutItem(req)

	return err
}
Beispiel #2
0
func (p *AWSProvider) buildWait(a *structs.App, b *structs.Build, cmd *exec.Cmd, stdout io.ReadCloser) {
	// scan all output
	out := ""
	scanner := bufio.NewScanner(stdout)

	for scanner.Scan() {
		text := scanner.Text()
		out += text + "\n"

		p.kinesis().PutRecord(&kinesis.PutRecordInput{
			Data:         []byte(text),
			PartitionKey: aws.String(string(time.Now().UnixNano())),
			StreamName:   aws.String(a.Outputs["Kinesis"]),
		})
	}
	if err := scanner.Err(); err != nil {
		helpers.Error(nil, err) // send internal error to rollbar
	}

	// and wait for a return code
	werr := cmd.Wait()

	// reload build item to get data from BuildUpdate callback
	b, err := p.BuildGet(b.App, b.Id)
	if err != nil {
		helpers.Error(nil, err) // send internal error to rollbar
		return
	}

	// Wait / return code are errors, consider the build failed
	if werr != nil {
		b.Status = "failed"
	}

	// save final build logs / status
	b.Logs = string(out)
	err = p.BuildSave(b)
	if err != nil {
		helpers.Error(nil, err) // send internal error to rollbar
		return
	}
}
Beispiel #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
}
Beispiel #4
0
// BuildSave creates or updates a build item in DynamoDB. It takes an optional
// bucket argument, which if set indicates to PUT Log data into S3
func (p *AWSProvider) BuildSave(b *structs.Build) error {
	_, err := p.AppGet(b.App)
	if err != nil {
		return err
	}

	if b.Id == "" {
		return fmt.Errorf("Id can not be blank")
	}

	if b.Started.IsZero() {
		b.Started = time.Now()
	}

	if p.IsTest() {
		b.Started = time.Unix(1473028693, 0).UTC()
		b.Ended = time.Unix(1473028892, 0).UTC()
	}

	req := &dynamodb.PutItemInput{
		Item: map[string]*dynamodb.AttributeValue{
			"id":      {S: aws.String(b.Id)},
			"app":     {S: aws.String(b.App)},
			"status":  {S: aws.String(b.Status)},
			"created": {S: aws.String(b.Started.Format(sortableTime))},
		},
		TableName: aws.String(p.DynamoBuilds),
	}

	if b.Description != "" {
		req.Item["description"] = &dynamodb.AttributeValue{S: aws.String(b.Description)}
	}

	if b.Manifest != "" {
		req.Item["manifest"] = &dynamodb.AttributeValue{S: aws.String(b.Manifest)}
	}

	if b.Logs != "" {
		req.Item["logs"] = &dynamodb.AttributeValue{S: aws.String(b.Logs)}
	}

	if b.Reason != "" {
		req.Item["reason"] = &dynamodb.AttributeValue{S: aws.String(b.Reason)}
	}

	if b.Release != "" {
		req.Item["release"] = &dynamodb.AttributeValue{S: aws.String(b.Release)}
	}

	if !b.Ended.IsZero() {
		req.Item["ended"] = &dynamodb.AttributeValue{S: aws.String(b.Ended.Format(sortableTime))}
	}

	if len(b.Tags) > 0 {
		tags, err := json.Marshal(b.Tags)
		if err != nil {
			return err
		}

		req.Item["tags"] = &dynamodb.AttributeValue{B: tags}
	}

	_, err = p.dynamodb().PutItem(req)

	return err
}
Beispiel #5
0
func (p *AWSProvider) buildWait(a *structs.App, b *structs.Build, cmd *exec.Cmd, stdout io.ReadCloser) {

	// scan all output
	scanner := bufio.NewScanner(stdout)
	out := ""
	for scanner.Scan() {
		text := scanner.Text()
		out += text + "\n"
	}
	if err := scanner.Err(); err != nil {
		helpers.Error(nil, err) // send internal error to rollbar
	}

	var cmdStatus string
	waitErr := make(chan error)
	timeout := time.After(1 * time.Hour)

	go func() {
		err := cmd.Wait()

		switch err.(type) {
		case *exec.ExitError:
			waitErr <- err
		default:
			waitErr <- nil
		}
	}()

	select {

	case werr := <-waitErr:
		// Wait / return code are errors, consider the build failed
		if werr != nil {
			cmdStatus = "failed"
		}

	case <-timeout:
		cmdStatus = "timeout"
		// Force kill the build container since its taking way to long
		killCmd := exec.Command("docker", "kill", fmt.Sprintf("build-%s", b.Id))
		killCmd.Start()
	}

	// reload build item to get data from BuildUpdate callback
	b, err := p.BuildGet(b.App, b.Id)
	if err != nil {
		helpers.Error(nil, err) // send internal error to rollbar
		return
	}

	if cmdStatus != "" { // Careful not to override the status set by BuildUpdate
		b.Status = cmdStatus
	}

	// save final build logs / status
	b.Logs = out
	err = p.BuildSave(b)
	if err != nil {
		helpers.Error(nil, err) // send internal error to rollbar
		return
	}
}