<commit_before>// Copyright 2017 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package buildstore

import (
	"fmt"
	"net/http"
	"strconv"
	"strings"

	"golang.org/x/net/context"

	"go.chromium.org/luci/buildbucket"
	bbapi "go.chromium.org/luci/common/api/buildbucket/buildbucket/v1"
	"go.chromium.org/luci/common/data/strpair"
	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/common/logging"
	"go.chromium.org/luci/logdog/common/types"
	"go.chromium.org/luci/milo/api/buildbot"
	"go.chromium.org/luci/milo/common"
	"go.chromium.org/luci/server/auth"
)

// This file implements conversion of buildbucket builds to buildbot builds.

// buildFromBuildbucket converts a buildbucket build to a buildbot build.
// If details is false, steps, text and properties are not guaranteed to be
// loaded.
//
// Does not populate OSFamily, OSVersion, Blame or SourceStamp.Changes
// fields.
func buildFromBuildbucket(c context.Context, master string, msg *bbapi.ApiCommonBuildMessage, fetchAnnotations bool) (*buildbot.Build, error) {
	var b buildbucket.Build
	if err := b.ParseMessage(msg); err != nil {
		return nil, err
	}
	num, err := buildNumber(&b)
	if err != nil {
		return nil, errors.Annotate(err, "parsing buildnumber").Err()
	}

	res := &buildbot.Build{
		Emulated:    true,
		Master:      master,
		Buildername: b.Builder,
		Number:      num,
		Results:     statusResult(b.Status),
		TimeStamp:   buildbot.Time{b.UpdateTime},
		Times: buildbot.TimeRange{
			Start:  buildbot.Time{b.StartTime},
			Finish: buildbot.Time{b.CompletionTime},
		},
		// TODO(nodir): use buildbucket access API when it is ready,
		// or, perhaps, just delete this code.
		// Note that this function should not be called on builds
		// that the requester does not have access to, in the first place.
		Internal:    b.Bucket != "luci.chromium.try",
		Finished:    b.Status.Completed(),
		Sourcestamp: &buildbot.SourceStamp{},
	}

	for _, bs := range b.BuildSets {
		if commit, ok := bs.(*buildbucket.GitilesCommit); ok {
			res.Sourcestamp.Repository = commit.RepoURL()
			res.Sourcestamp.Revision = commit.Revision
			break
		}
	}

	if fetchAnnotations && b.Status != buildbucket.StatusScheduled {
		addr, err := logLocation(&b)
		if err != nil {
			return nil, err
		}

		ann, err := fetchAnnotationProto(c, addr)
		switch {
		case err == errAnnotationNotFound:
		case err != nil:
			return nil, errors.Annotate(err, "could not load annotation proto").Err()<commit_msg>[milo] initialize step to empty slice<commit_after>// Copyright 2017 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package buildstore

import (
	"fmt"
	"net/http"
	"strconv"
	"strings"

	"golang.org/x/net/context"

	"go.chromium.org/luci/buildbucket"
	bbapi "go.chromium.org/luci/common/api/buildbucket/buildbucket/v1"
	"go.chromium.org/luci/common/data/strpair"
	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/common/logging"
	"go.chromium.org/luci/logdog/common/types"
	"go.chromium.org/luci/milo/api/buildbot"
	"go.chromium.org/luci/milo/common"
	"go.chromium.org/luci/server/auth"
)

// This file implements conversion of buildbucket builds to buildbot builds.

// buildFromBuildbucket converts a buildbucket build to a buildbot build.
// If details is false, steps, text and properties are not guaranteed to be
// loaded.
//
// Does not populate OSFamily, OSVersion, Blame or SourceStamp.Changes
// fields.
func buildFromBuildbucket(c context.Context, master string, msg *bbapi.ApiCommonBuildMessage, fetchAnnotations bool) (*buildbot.Build, error) {
	var b buildbucket.Build
	if err := b.ParseMessage(msg); err != nil {
		return nil, err
	}
	num, err := buildNumber(&b)
	if err != nil {
		return nil, errors.Annotate(err, "parsing buildnumber").Err()
	}

	res := &buildbot.Build{
		Emulated:    true,
		Master:      master,
		Buildername: b.Builder,
		Number:      num,
		Results:     statusResult(b.Status),
		TimeStamp:   buildbot.Time{b.UpdateTime},
		Times: buildbot.TimeRange{
			Start:  buildbot.Time{b.StartTime},
			Finish: buildbot.Time{b.CompletionTime},
		},
		// TODO(nodir): use buildbucket access API when it is ready,
		// or, perhaps, just delete this code.
		// Note that this function should not be called on builds
		// that the requester does not have access to, in the first place.
		Internal:    b.Bucket != "luci.chromium.try",
		Finished:    b.Status.Completed(),
		Sourcestamp: &buildbot.SourceStamp{},

		// non-nil slice because we want an array, not null,
		// when converted to JSON
		Steps: []buildbot.Step{},
	}

	for _, bs := range b.BuildSets {
		if commit, ok := bs.(*buildbucket.GitilesCommit); ok {
			res.Sourcestamp.Repository = commit.RepoURL()
			res.Sourcestamp.Revision = commit.Revision
			break
		}
	}

	if fetchAnnotations && b.Status != buildbucket.StatusScheduled {
		addr, err := logLocation(&b)
		if err != nil {
			return nil, err
		}

		ann, err := fetchAnnotationProto(c, addr)
		switch {
		case err == errAnnotationNotFound:
		case err != nil:
			return nil, errors.Annotate(err, "could not load annotation proto").Err()
{'fraction_non_alphanumeric': 0.11943717277486911, 'fraction_numerical': 0.0029450261780104713, 'mean_word_length': 3.631060606060606, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '410087', 'n_tokens_mistral': 2101, 'n_tokens_neox': 1953, 'n_words': 593}