github.com/munnerz/test-infra@v0.0.0-20190108210205-ce3d181dc989/robots/coverage/cmd/diff/diff.go (about) 1 /* 2 Copyright 2018 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package diff 18 19 import ( 20 "fmt" 21 "io" 22 "os" 23 24 "github.com/spf13/cobra" 25 "k8s.io/test-infra/gopherage/pkg/util" 26 "k8s.io/test-infra/robots/coverage/diff" 27 ) 28 29 type flags struct { 30 outputFile string 31 threshold float32 32 jobName string 33 } 34 35 // MakeCommand returns a `diff` command. 36 func MakeCommand() *cobra.Command { 37 flags := &flags{} 38 cmd := &cobra.Command{ 39 Use: "diff [base-profile] [new-profile]", 40 Short: "Calculate the file level difference between two coverage profiles", 41 Long: `Calculate the file level difference between two coverage profiles. 42 Produce the result in a markdown table`, 43 Run: func(cmd *cobra.Command, args []string) { 44 run(flags, cmd, args) 45 }, 46 } 47 cmd.Flags().StringVarP(&flags.outputFile, "output", "o", "-", "output file") 48 cmd.Flags().StringVarP(&flags.jobName, "jobname", "j", "", "prow job name") 49 cmd.Flags().Float32VarP(&flags.threshold, "threshold", "t", .8, "code coverage threshold") 50 return cmd 51 } 52 53 func run(flags *flags, cmd *cobra.Command, args []string) { 54 if len(args) != 2 { 55 fmt.Fprintln(os.Stderr, "Expected exactly two arguments: base-profile & new-profile") 56 cmd.Usage() 57 os.Exit(2) 58 } 59 60 if flags.threshold < 0 || flags.threshold > 1 { 61 fmt.Fprintln(os.Stderr, "coverage threshold must be a float number between 0 to 1, inclusive") 62 os.Exit(1) 63 } 64 65 baseProfilePath := args[0] 66 newProfilePath := args[1] 67 68 baseProfiles, err := util.LoadProfile(baseProfilePath) 69 if err != nil { 70 fmt.Fprintf(os.Stderr, "Failed to parse base profile file: %v.\n", err) 71 os.Exit(1) 72 } 73 74 newProfiles, err := util.LoadProfile(newProfilePath) 75 if err != nil { 76 fmt.Fprintf(os.Stderr, "Failed to parse new profile file: %v.\n", err) 77 os.Exit(1) 78 } 79 80 postContent, isCoverageLow := diff.ContentForGithubPost(baseProfiles, newProfiles, flags.jobName, flags.threshold) 81 82 var file io.WriteCloser 83 if flags.outputFile == "-" { 84 file = os.Stdout 85 } else { 86 file, err = os.Create(flags.outputFile) 87 if err != nil { 88 fmt.Fprintf(os.Stderr, "Failed to create output file: %v.", err) 89 os.Exit(1) 90 } 91 defer file.Close() 92 } 93 94 _, err = io.WriteString(file, fmt.Sprintf("isCoverageLow = %v\n", isCoverageLow)) 95 96 if err != nil { 97 fmt.Fprintf(os.Stderr, "Failed to write low coverage check: %v.\n", err) 98 os.Exit(1) 99 } 100 101 _, err = io.WriteString(file, fmt.Sprintf("Post content:\n%v", postContent)) 102 if err != nil { 103 fmt.Fprintf(os.Stderr, "Failed to write post content: %v.\n", err) 104 os.Exit(1) 105 } 106 }