goc/cmd/diff.go

201 lines
8.0 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 cmd
import (
"encoding/json"
"io/ioutil"
"os"
"github.com/olekukonko/tablewriter"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/qiniu/goc/pkg/cover"
2020-05-22 02:33:03 +00:00
"github.com/qiniu/goc/pkg/github"
"github.com/qiniu/goc/pkg/prow"
"github.com/qiniu/goc/pkg/qiniu"
2020-05-22 02:33:03 +00:00
)
var diffCmd = &cobra.Command{
Use: "diff",
Short: "do coverage profile diff analysis, it can also work with prow and post comments to github pull request if needed",
Example: ` goc diff --new-profile=<xxxx> --base-profile=<xxxx> // diff two local coverage profile and display
goc diff --prow-postsubmit-job=<xxx> --new-profile=<xxx> // diff local coverage profile with the remote one in prow job using default qiniu-credential
goc diff --prow-postsubmit-job=<xxx> --new-profile=<xxx> --full-diff=true // calculate and display full diff coverage between new-profile and base-profile, not concerned github changed files
goc diff --prow-postsubmit-job=<xxx> --prow-remote-profile-name=<xxx>
--qiniu-credential=<xxx> --new-profile=<xxxx> // diff local coverage profile with the remote one in prow job
goc diff --prow-postsubmit-job=<xxx> --prow-profile=<xxx>
--github-token=<xxx> --github-user=<xxx> --github-comment-prefix=<xxx>
--qiniu-credential=<xxx> --coverage-threshold-percentage=<xxx> --new-profile=<xxxx> // diff coverage profile with the remote one in prow job, and post comments to github PR
`,
Run: func(cmd *cobra.Command, args []string) {
if baseProfile != "" {
doDiffForLocalProfiles(cmd, args)
} else if prowPostSubmitJob != "" {
doDiffUnderProw(cmd, args)
} else {
logrus.Fatalf("either base-profile or prow-postsubmit-job must be provided")
}
},
}
var (
newProfile string
baseProfile string
coverageThreshold int
prowPostSubmitJob string
prowProfile string
githubToken string
githubUser string
githubCommentPrefix string
qiniuCredential string
robotName string
fullDiff bool
)
func init() {
diffCmd.Flags().StringVarP(&newProfile, "new-profile", "n", "", "local profile which works as the target to analysis")
diffCmd.MarkFlagRequired("new-profile")
diffCmd.Flags().StringVarP(&baseProfile, "base-profile", "b", "", "another local profile which works as baseline to compare with the target")
diffCmd.Flags().IntVarP(&coverageThreshold, "coverage-threshold-percentage", "", 0, "coverage threshold percentage")
diffCmd.Flags().StringVarP(&prowPostSubmitJob, "prow-postsubmit-job", "", "", "prow postsubmit job which used to find the base profile")
diffCmd.Flags().StringVarP(&prowProfile, "prow-remote-profile-name", "", "filtered.cov", "the name of profile in prow postsubmit job, which used as the base profile to compare")
diffCmd.Flags().StringVarP(&githubToken, "github-token", "", "/etc/github/oauth", "path to token to access github repo")
diffCmd.Flags().StringVarP(&githubUser, "github-user", "", "", "github user name when comments in github")
diffCmd.Flags().StringVarP(&githubCommentPrefix, "github-comment-prefix", "", "", "specific comment flag you provided")
diffCmd.Flags().StringVarP(&qiniuCredential, "qiniu-credential", "", "/etc/qiniuconfig/qiniu.json", "path to credential file to access qiniu cloud")
diffCmd.Flags().StringVarP(&robotName, "robot-name", "", "qiniu-bot", "github user name for coverage robot")
diffCmd.Flags().BoolVarP(&fullDiff, "full-diff", "", false, "when set true,calculate and display full diff coverage between new-profile and base-profile")
rootCmd.AddCommand(diffCmd)
}
//goc diff --new-profile=./new.cov --base-profile=./base.cov
//+------------------------------------------------------+---------------+--------------+--------+
//| File | Base Coverage | New Coverage | Delta |
//+------------------------------------------------------+---------------+--------------+--------+
//| qiniu.com/kodo/bd/pfd/pfdstg/cursor/mgr.go | 53.5% | 50.5% | -3.0% |
//| qiniu.com/kodo/bd/pfd/pfdstg/svr/getstripe.go | 0.5% | 0.0% | -0.5% |
//| Total | 35.7% | 35.7% | -0.0% |
//+------------------------------------------------------+---------------+--------------+--------+
func doDiffForLocalProfiles(cmd *cobra.Command, args []string) {
localP, err := cover.ReadFileToCoverList(newProfile)
if err != nil {
logrus.Fatal(err)
}
baseP, err := cover.ReadFileToCoverList(baseProfile)
if err != nil {
logrus.Fatal(err)
}
//calculate diff file cov and display
rows := cover.GetDeltaCov(localP, baseP)
rows.Sort()
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"File", "Base Coverage", "New Coverage", "Delta"})
table.SetAutoFormatHeaders(false)
table.SetColumnAlignment([]int{tablewriter.ALIGN_LEFT, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER})
for _, row := range rows {
table.Append([]string{row.FileName, row.BasePer, row.NewPer, row.DeltaPer})
}
totalDelta := cover.PercentStr(cover.TotalDelta(localP, baseP))
2020-05-22 02:33:03 +00:00
table.Append([]string{"Total", baseP.TotalPercentage(), localP.TotalPercentage(), totalDelta})
table.Render()
}
func doDiffUnderProw(cmd *cobra.Command, args []string) {
var (
prNumStr = os.Getenv("PULL_NUMBER")
pullSha = os.Getenv("PULL_PULL_SHA")
baseSha = os.Getenv("PULL_BASE_SHA")
repoOwner = os.Getenv("REPO_OWNER")
repoName = os.Getenv("REPO_NAME")
jobType = os.Getenv("JOB_TYPE")
jobName = os.Getenv("JOB_NAME")
buildStr = os.Getenv("BUILD_NUMBER")
artifacts = os.Getenv("ARTIFACTS")
)
logrus.Printf("Running coverage for PR = %s; PR commit SHA = %s;base SHA = %s", prNumStr, pullSha, baseSha)
switch jobType {
case "periodic":
logrus.Printf("job type %s, do nothing", jobType)
case "postsubmit":
logrus.Printf("job type %s, do nothing", jobType)
case "presubmit":
if githubToken == "" {
logrus.Fatalf("github token not provided")
}
prClient := github.NewPrClient(githubToken, repoOwner, repoName, prNumStr, robotName, githubCommentPrefix)
if qiniuCredential == "" {
logrus.Fatalf("qiniu credential not provided")
}
var qc *qiniu.Client
var conf qiniu.Config
files, err := ioutil.ReadFile(*&qiniuCredential)
if err != nil {
logrus.WithError(err).Fatal("Error reading qiniu config file")
}
if err := json.Unmarshal(files, &conf); err != nil {
logrus.Fatal("Error unmarshal qiniu config file")
}
if conf.Bucket == "" {
logrus.Fatal("no qiniu bucket provided")
}
if conf.AccessKey == "" || conf.SecretKey == "" {
logrus.Fatal("either qiniu access key or secret key was not provided")
}
if conf.Domain == "" {
logrus.Fatal("no qiniu bucket domain was provided")
}
qc = qiniu.NewClient(&conf)
localArtifacts := qiniu.Artifacts{
Directory: artifacts,
ProfileName: newProfile,
ChangedProfileName: qiniu.ChangedProfileName,
}
job := prow.Job{
JobName: jobName,
BuildId: buildStr,
Org: repoOwner,
RepoName: repoName,
PRNumStr: prNumStr,
PostSubmitJob: prowPostSubmitJob,
LocalProfilePath: newProfile,
PostSubmitCoverProfile: prowProfile,
QiniuClient: qc,
LocalArtifacts: &localArtifacts,
GithubComment: prClient,
FullDiff: fullDiff,
}
if err := job.RunPresubmit(); err != nil {
logrus.Fatalf("run presubmit job failed, err: %v", err)
}
default:
logrus.Printf("Unknown job type: %s, do nothing.", jobType)
}
}