goc/pkg/qiniu/qnPresubmit.go

131 lines
3.6 KiB
Go
Raw Normal View History

2020-05-22 02:33:03 +00:00
/*
Copyright 2020 Qiniu Cloud (qiniu.com)
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 qiniu
import (
"encoding/json"
"fmt"
"log"
"os"
"path"
"sort"
"strconv"
)
const (
//statusJSON is the JSON file that stores build success info
statusJSON = "finished.json"
// ArtifactsDirName is the name of directory defined in prow to store test artifacts
ArtifactsDirName = "artifacts"
//default prow coverage file
PostSubmitCoverProfile = "filtered.cov"
//default to save changed file related coverage profile
ChangedProfileName = "changed-file-profile.cov"
)
// sortBuilds converts all build from str to int and sorts all builds in descending order and
// returns the sorted slice
func sortBuilds(strBuilds []string) []int {
var res []int
for _, buildStr := range strBuilds {
num, err := strconv.Atoi(buildStr)
if err != nil {
log.Printf("Non-int build number found: '%s'", buildStr)
} else {
res = append(res, num)
}
}
sort.Sort(sort.Reverse(sort.IntSlice(res)))
return res
}
type finishedStatus struct {
Timestamp int
Passed bool
}
func isBuildSucceeded(jsonText []byte) bool {
var status finishedStatus
err := json.Unmarshal(jsonText, &status)
return err == nil && status.Passed
}
// FindBaseProfileFromQiniu finds the coverage profile file from the latest healthy build
// stored in given gcs directory
func FindBaseProfileFromQiniu(qc *Client, prowJobName, covProfileName string) ([]byte, error) {
dirOfJob := path.Join("logs", prowJobName)
prefix := dirOfJob + "/"
strBuilds, err := qc.ListSubDirs(prefix)
if err != nil {
return nil, fmt.Errorf("error listing qiniu objects, prowjob:%v, err:%v", prowJobName, err)
}
if len(strBuilds) == 0 {
log.Printf("no cover profiles found from remote, do nothing")
return nil, nil
}
log.Printf("total sub dirs: %d", len(strBuilds))
builds := sortBuilds(strBuilds)
profilePath := ""
for _, build := range builds {
buildDirPath := path.Join(dirOfJob, strconv.Itoa(build))
dirOfStatusJSON := path.Join(buildDirPath, statusJSON)
statusText, err := qc.ReadObject(dirOfStatusJSON)
if err != nil {
log.Printf("Cannot read finished.json (%s) ", dirOfStatusJSON)
} else if isBuildSucceeded(statusText) {
artifactsDirPath := path.Join(buildDirPath, ArtifactsDirName)
profilePath = path.Join(artifactsDirPath, covProfileName)
break
}
}
if profilePath == "" {
log.Printf("no cover profiles found from remote job %s, do nothing", prowJobName)
return nil, nil
}
log.Printf("base cover profile path: %s", profilePath)
return qc.ReadObject(profilePath)
}
type Artifacts struct {
Directory string
ProfileName string
ChangedProfileName string // create temporary to save changed file related coverage profile
}
func (a *Artifacts) ProfilePath() string {
return path.Join(a.Directory, a.ProfileName)
}
func (a *Artifacts) CreateChangedProfile() *os.File {
if a.ChangedProfileName == "" {
log.Fatalf("param Artifacts.ChangedProfileName should not be empty")
}
p, err := os.Create(a.ChangedProfileName)
log.Printf("os create: %s", a.ChangedProfileName)
if err != nil {
log.Fatalf("file(%s) create failed: %v", a.ChangedProfileName, err)
}
return p
}