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"
2020-05-31 13:14:12 +00:00
"github.com/qiniu/goc/pkg/cover"
2020-05-22 02:33:03 +00:00
"github.com/qiniu/goc/pkg/github"
2020-05-31 13:14:12 +00:00
"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" ,
2020-06-07 02:48:07 +00:00
Short : "Do coverage profile diff analysis, it can also work with prow and post comments to github pull request if needed" ,
2020-06-01 09:54:49 +00:00
Example : ` # Diff two local coverage profile and display
goc diff -- new - profile = < xxxx > -- base - profile = < xxxx >
# Diff local coverage profile with the remote one in prow job using default qiniu - credential
goc diff -- prow - postsubmit - job = < xxx > -- new - profile = < xxx >
# Calculate and display full diff coverage between new - profile and base - profile , not concerned github changed files
goc diff -- prow - postsubmit - job = < xxx > -- new - profile = < xxx > -- full - diff = true
# Diff local coverage profile with the remote one in prow job
2020-05-22 02:33:03 +00:00
goc diff -- prow - postsubmit - job = < xxx > -- prow - remote - profile - name = < xxx >
2020-06-01 09:54:49 +00:00
-- qiniu - credential = < xxx > -- new - profile = < xxxx >
# Diff coverage profile with the remote one in prow job , and post comments to github PR
2020-05-22 02:33:03 +00:00
goc diff -- prow - postsubmit - job = < xxx > -- prow - profile = < xxx >
-- github - token = < xxx > -- github - user = < xxx > -- github - comment - prefix = < xxx >
2020-06-01 09:54:49 +00:00
-- qiniu - credential = < xxx > -- coverage - threshold - percentage = < xxx > -- new - profile = < xxxx >
2020-05-22 02:33:03 +00:00
` ,
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 } )
}
2020-05-29 02:58:24 +00:00
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" )
}
2020-07-24 09:27:03 +00:00
var qc qiniu . Client
2020-05-22 02:33:03 +00:00
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 )
2020-07-24 11:24:07 +00:00
localArtifacts := qiniu . ProfileArtifacts {
2020-05-22 02:33:03 +00:00
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 )
}
}