forked from semgrep/semgrep
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreport_pysemgrep_loc.ml
executable file
·136 lines (110 loc) · 3.98 KB
/
report_pysemgrep_loc.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/usr/bin/env ocaml
#use "topfind"
#require "cmdliner"
#require "fmt"
#require "fmt.tty"
#require "logs"
#require "logs.fmt"
#require "ppx_deriving.show"
#load "unix.cma"
#load "threads/threads.cma"
#require "feather"
open Cmdliner
module F = Feather
open Feather (* for |. *)
(*****************************************************************************)
(* Prelude *)
(*****************************************************************************)
(* Report the remaining lines of code (LOC) in pysemgrep to port and upload
* the count to dashboard.semgrep.dev/metrics/semgrep.pysemgrep.loc
*
* usage:
* $ ./scripts/report_pysemgrep_loc --upload cli/src/semgrep/
*
* This is also run in a cron in .circleci/config.yml
* Note that we're not using any semgrep libs here, just
* pretty standard OCaml libraries.
*
* alternatives:
* - a bash script, like in report_test_metrics.sh
*
* See also ../tools/hello_script.ml.
*)
(*****************************************************************************)
(* Types and constants *)
(*****************************************************************************)
let host = "https://dashboard.semgrep.dev"
let metric = "semgrep.pysemgrep.loc"
(* no more ppx_deriving_cmdliner :( see toplevel comment in hello_script.ml
* old:
* see https://github.com/hammerlab/ppx_deriving_cmdliner
* type conf = {
* path : string; [@pos 0] [@docv "CMD"]
* upload : bool; [@default false]
* verbose : bool; [@default false]
* }
* [@@deriving cmdliner, show]
*)
type conf = { path : string; upload : bool; verbose : bool } [@@deriving show]
(*****************************************************************************)
(* Helpers *)
(*****************************************************************************)
let upload conf loc =
let url = Printf.sprintf "%s/api/metric/%s" host metric in
(* TODO: use Logs library *)
Logs.debug (fun m -> m "uploading to %s" url);
let cmd =
F.process "curl"
[ "--fail"; "-L"; "-X"; "POST"; url; "-d"; string_of_int loc ]
in
F.run cmd
(*****************************************************************************)
(* Entry point *)
(*****************************************************************************)
let run conf =
if conf.verbose then Logs.set_level (Some Logs.Debug);
Logs.debug (fun m -> m "debug: params = %s" (show_conf conf));
let out =
(* alt: could also use F.find and F.grep builtins *)
F.process "find" [ conf.path; "-type"; "f"; "-name"; "*.py" ]
(* alt: could also use F.filter_lines *)
|. F.process "grep" [ "-v"; "semgrep_interfaces/" ]
|. F.process "grep" [ "-v"; "semdep/" ]
(* --total is actually a recent flag so old 'wc' might not work *)
|. F.process "xargs" [ "wc"; "-l"; "--total=only" ]
|> F.collect F.stdout
in
let loc = int_of_string out in
Logs.app (fun m ->
m "LOC in %s (without semgrep_interfaces and semdep) = %d" conf.path loc);
if conf.upload then upload conf loc
(*****************************************************************************)
(* Cmdliner boilerplate *)
(*****************************************************************************)
(* this used to be autogenerated by ppx_deriving_cmdliner *)
let conf_cmdliner_term : conf Term.t =
let o_upload : bool Term.t =
let doc = "" in
Arg.(value & flag & info [ "u"; "upload" ] ~doc)
in
let o_verbose : bool Term.t =
let doc = "" in
Arg.(value & flag & info [ "v"; "verbose" ] ~doc)
in
let o_path : string Term.t =
let doc = "" in
Arg.(value & pos 0 string "TODO" & info [] ~docv:"CMD" ~doc)
in
let combine upload verbose path = { upload; verbose; path } in
Term.(const combine $ o_upload $ o_verbose $ o_path)
let main () =
(* logging setup *)
Fmt_tty.setup_std_outputs ();
Logs.set_reporter (Logs_fmt.reporter ());
(* cmdliner setup *)
let info = Cmd.info Sys.argv.(0) in
let term = Term.(const run $ conf_cmdliner_term) in
let cmd = Cmd.v info term in
(* Let's go! *)
exit (Cmd.eval cmd)
let () = main ()