From fad9538edbe92e88299d1222c056dfdf5c267251 Mon Sep 17 00:00:00 2001 From: MarkNahabedian Date: Mon, 16 Jan 2023 16:27:25 -0500 Subject: [PATCH 01/27] Add a registry Guideline to enforce thresholds against statistics gleaned by PackageAnalyzer. --- Project.toml | 2 ++ src/AutoMerge/guidelines.jl | 55 ++++++++++++++++++++++++++++++++++++ src/utils.jl | 56 +++++++++++++++++++++++++++++++++++++ test/runtests.jl | 21 ++++++++++++++ 4 files changed, 134 insertions(+) diff --git a/Project.toml b/Project.toml index 528a944d..05daac9b 100644 --- a/Project.toml +++ b/Project.toml @@ -11,6 +11,8 @@ HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" LibGit2 = "76f85450-5226-5b5a-8eaa-529ad045b433" LicenseCheck = "726dbf0d-6eb6-41af-b36c-cd770e0f00cc" +Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" +PackageAnalyzer = "e713c705-17e4-4cec-abe0-95bf5bf3e10c" Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" diff --git a/src/AutoMerge/guidelines.jl b/src/AutoMerge/guidelines.jl index a5b77a00..f25e3107 100644 --- a/src/AutoMerge/guidelines.jl +++ b/src/AutoMerge/guidelines.jl @@ -857,6 +857,60 @@ function meets_version_can_be_imported( end end + +function linecounts_meet_thresholds(data::GitHubAutoMergeData) + analysis = PackageAnalyzer.analyze(data.pkg_code_path) + if isempty(p.lines_of_code) + return false, "PackageAnalyzer didn't find any lines of code." + end + issues = [] + src_line_count = PackageAnalyzer.count_julia_loc(p, "src") + if !meets_threshold(env_threshold("README_MIN_LINES", 5), + PackageAnalyzer.count_readme(analysis), + src_line_count) + push!(issues, "Package README file is too short") + end + if !meets_threshold(env_threshold_count("SRC_MIN_LINES", 10), + src_line_count) + push!(issues, "Too few linwes of source code.") + end + test_line_count = count_julia_loc(p, "test") + if !!meets_threshold(env_threshold("TEST_MIN_LINES", 0.1f0), + test_line_count, + test_line_count + src_line_count) + push!(issues, "Too few lines of test code.") + end + docs_line_count = PackageAnalyzer.count_docs(p) + if !meets_threshold(env_threshold("DOC_MIN_LINES", 0.1f0), + docs_line_count, + docs_line_count + src_line_count) + push!(issues, "Too few lines of documentation.") + end + if isempty(issues) + return true, "" + else + return false, join(issues, "\n") + end +end + +const guideline_linecounts_meet_thresholds = Guideline(; + info="Test that lines of source, tests and documentation meet specified thresholds", + docs="""Make sure that various line counts meet or exceed specified thresholds. +Thresholds are controlled by these environment variables: + * SRC_MIN_LINES: Minimum number of lines of source code + * README_MIN_LINES: % Minimum number of lines in the README file + * TEST_MIN_LINES: % Minimum number of lines of code in the test directory + * DOC_MIN_LINES: # Minimum number of lines of documentation + +Those marked with a % can be expressed as a count, or as a percentage +of the number of lines of source code. For TEST_MIN_LINES and +DOC_MIN_LINES, the denominatttor of the percentage also includes the +number of lines of test code. +""", + check=linecounts_meet_thresholds +) + + function _run_pkg_commands( working_directory::String, pkg::String, @@ -1017,3 +1071,4 @@ function get_automerge_guidelines( ] return guidelines end + diff --git a/src/utils.jl b/src/utils.jl index 948a7e53..3a20823a 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -1,3 +1,5 @@ +using Logging + function with_temp_dir(f::Function) original_working_directory = pwd() @@ -25,3 +27,57 @@ function with_temp_depot(f::Function) end return result end + + +""" + env_threshold_count(envvar::String, default) + +Return an integer (intrerpreted as a number of lines) read +from the specified environment variable. +""" +function env_threshold_count(envvar::String, default) + v = get(ENV, envvar, nothing) + if v == nothing + return default + end + m = match(r"(?^[0-9]+)$", v) + if m != nothing + return parse(Int64, m["count"]) + end + @warn "Value $v of environment variable $envvar is not a line count. Using default of $default" + default +end + + +""" + env_threshold(envvar::String, default) + +Return an integer (intrerpreted as a number of lines) or a fraction read +from the specified environment variable. +""" +function env_threshold(envvar::String, default) + v = get(ENV, envvar, nothing) + if v == nothing + return default + end + m = match(r"(?^[0-9]+.?[0-9]*+)%$", v) + if m != nothing + return parse(Float32, m["pct"]) / 100 + end + m = match(r"(?^[0-9]+)$", v) + if m != nothing + return parse(Int64, m["count"]) + end + @warn "Value $v of environment variable $envvar is neither a percentage nor a line count. Using default of $default" + default +end + +meets_threshold(threshold::Integer, linecount::Integer) = + linecount >= threshhols + +meets_threshold(threshold::Integer, numerator::Integer, ::Integer) = + numerator >= threshold + +meets_threshold(thresholdr::AbstractFloat, numerator::Integer, denominator::Integer) = + numerator / denominator >= threshhols + diff --git a/test/runtests.jl b/test/runtests.jl index 26018ffd..2ac26646 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -45,4 +45,25 @@ ENV["JULIA_PKG_SERVER"] = "" include("automerge-integration.jl") end end + + @testset "env_threshold" begin + e = RegistryCI.env_threshold + ENV["zero"] = "0" + ENV["zerodotzero"] = "0.0" + ENV["zerodotzeropct"] = "0.0%" + ENV["pct"] = "12%" + ENV["fracpct"] = "20.5%" + ENV["negcount"] = "-1" + ENV["count"] = "123" + # How can we test if a warning was logged? + @test e("zero", 0.1) == 0 + @test e("zero", 0.1) isa Integer + @test e("zerodotzero", 0.1) == 0.1 # default + @test e("zerodotzeropct", 0.1) == 0.0 + @test e("zerodotzeropct", 0.1) isa Float32 + @test e("pct", 0) == 0.12f0 + @test e("fracpct", 0) == 0.205f0 + @test e("negcount", 10) == 10 # default + @test e("count", 0) == 123 + end end From ec8f5562154ee6b979eebbdf53b23f96b6a4414c Mon Sep 17 00:00:00 2001 From: MarkNahabedian Date: Tue, 17 Jan 2023 09:55:00 -0500 Subject: [PATCH 02/27] Unit test for linecounts_meet_thresholds. --- src/AutoMerge/guidelines.jl | 38 ++++++++++++++++++------------------- test/automerge-unit.jl | 7 +++++++ 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/src/AutoMerge/guidelines.jl b/src/AutoMerge/guidelines.jl index f25e3107..888a1d90 100644 --- a/src/AutoMerge/guidelines.jl +++ b/src/AutoMerge/guidelines.jl @@ -857,9 +857,25 @@ function meets_version_can_be_imported( end end +const guideline_linecounts_meet_thresholds = Guideline(; + info="Test that lines of source, tests and documentation meet specified thresholds", + docs="""Make sure that various line counts meet or exceed specified thresholds. +Thresholds are controlled by these environment variables: + * SRC_MIN_LINES: Minimum number of lines of source code + * README_MIN_LINES: % Minimum number of lines in the README file + * TEST_MIN_LINES: % Minimum number of lines of code in the test directory + * DOC_MIN_LINES: # Minimum number of lines of documentation -function linecounts_meet_thresholds(data::GitHubAutoMergeData) - analysis = PackageAnalyzer.analyze(data.pkg_code_path) +Those marked with a % can be expressed as a count, or as a percentage +of the number of lines of source code. For TEST_MIN_LINES and +DOC_MIN_LINES, the denominatttor of the percentage also includes the +number of lines of test code. +""", + check=data -> linecounts_meet_thresholds(data.pkg_code_path) +) + +function linecounts_meet_thresholds(pkg_code_path::String) + analysis = PackageAnalyzer.analyze(pkg_code_path) if isempty(p.lines_of_code) return false, "PackageAnalyzer didn't find any lines of code." end @@ -893,24 +909,6 @@ function linecounts_meet_thresholds(data::GitHubAutoMergeData) end end -const guideline_linecounts_meet_thresholds = Guideline(; - info="Test that lines of source, tests and documentation meet specified thresholds", - docs="""Make sure that various line counts meet or exceed specified thresholds. -Thresholds are controlled by these environment variables: - * SRC_MIN_LINES: Minimum number of lines of source code - * README_MIN_LINES: % Minimum number of lines in the README file - * TEST_MIN_LINES: % Minimum number of lines of code in the test directory - * DOC_MIN_LINES: # Minimum number of lines of documentation - -Those marked with a % can be expressed as a count, or as a percentage -of the number of lines of source code. For TEST_MIN_LINES and -DOC_MIN_LINES, the denominatttor of the percentage also includes the -number of lines of test code. -""", - check=linecounts_meet_thresholds -) - - function _run_pkg_commands( working_directory::String, pkg::String, diff --git a/test/automerge-unit.jl b/test/automerge-unit.jl index d1a758b4..83bacfdc 100644 --- a/test/automerge-unit.jl +++ b/test/automerge-unit.jl @@ -616,4 +616,11 @@ end result = has_osi_license_in_depot("VisualStringDistances") @test !result[1] end + + @testset "`AutoMerge.linecounts_meet_thresholds" begin + tmp_depot = mktempdir() + pkg_path = pkgdir_from_depot(tmp_depot, "VisualStringDistances") + result = AutoMerge.linecounts_meet_thresholds(pkg_path) + @test result = (true, "") + end end From 11026cdd8e6a8e489f713ed868b9ebc09d14c95b Mon Sep 17 00:00:00 2001 From: MarkNahabedian Date: Wed, 18 Jan 2023 20:57:03 -0500 Subject: [PATCH 03/27] Record all Guidelines in ALL_GUIDELINES. --- src/AutoMerge/types.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/AutoMerge/types.jl b/src/AutoMerge/types.jl index 7c95d41e..d5cf9f34 100644 --- a/src/AutoMerge/types.jl +++ b/src/AutoMerge/types.jl @@ -112,6 +112,8 @@ function GitHubAutoMergeData(; kwargs...) return GitHubAutoMergeData(getindex.(Ref(kwargs), fields)...) end +ALL_GUIDELINES = [] + Base.@kwdef mutable struct Guideline # Short description of the guideline. Only used for logging. info::String @@ -130,6 +132,12 @@ Base.@kwdef mutable struct Guideline # Saved output message from the `check` function. message::String = "Internal error. A check that was supposed to run never did: $(info)" + + function Guideline(info, docs, check, passed, message) + g = new(info, docs, check, passed, message) + push!(ALL_GUIDELINES, g) + g + end end passed(guideline::Guideline) = guideline.passed From 881dfbae55a40a1fedfc15a962d1357502e149c4 Mon Sep 17 00:00:00 2001 From: MarkNahabedian Date: Fri, 20 Jan 2023 13:56:22 -0500 Subject: [PATCH 04/27] Say which fields or keyargs are missing. --- src/AutoMerge/types.jl | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/AutoMerge/types.jl b/src/AutoMerge/types.jl index d5cf9f34..b0afff6b 100644 --- a/src/AutoMerge/types.jl +++ b/src/AutoMerge/types.jl @@ -100,6 +100,12 @@ struct GitHubAutoMergeData # Environment variables to pass to the subprocess that does `Pkg.add("Foo")` and `import Foo` environment_variables_to_pass::Vector{String} + + # Parameters for the linecounts_meet_thresholds guideline: + src_min_lines::Integer + readme_min_lines::Union{Integer, AbstractFloat} + test_min_lines::Union{Integer, AbstractFloat} + doc_min_lines::Union{Integer, AbstractFloat} end # Constructor that requires all fields (except `pkg_code_path`) as named arguments. @@ -107,7 +113,11 @@ function GitHubAutoMergeData(; kwargs...) pkg_code_path = mktempdir(; cleanup=true) kwargs = (; pkg_code_path=pkg_code_path, kwargs...) fields = fieldnames(GitHubAutoMergeData) - always_assert(Set(keys(kwargs)) == Set(fields)) + missing = setdiff(Set(keys(kwargs)), Set(fields)) + if !isempty(missing) + @warn "Keyword argument discrepancy in GitHubAutoMergeData: $(join(missing, ", "))" + end + always_assert(isempty(missing)) always_assert(kwargs[:authorization] ∈ (:normal, :jll)) return GitHubAutoMergeData(getindex.(Ref(kwargs), fields)...) end From ebf74b838a64515c920cbd7e2f042629f71c3707 Mon Sep 17 00:00:00 2001 From: MarkNahabedian Date: Fri, 20 Jan 2023 14:14:38 -0500 Subject: [PATCH 05/27] Hopefully better warning message. --- src/AutoMerge/types.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AutoMerge/types.jl b/src/AutoMerge/types.jl index b0afff6b..de08e5b5 100644 --- a/src/AutoMerge/types.jl +++ b/src/AutoMerge/types.jl @@ -115,7 +115,7 @@ function GitHubAutoMergeData(; kwargs...) fields = fieldnames(GitHubAutoMergeData) missing = setdiff(Set(keys(kwargs)), Set(fields)) if !isempty(missing) - @warn "Keyword argument discrepancy in GitHubAutoMergeData: $(join(missing, ", "))" + @warn "Keyword/field mismatch while constructing a GitHubAutoMergeData: $(join(missing, ", "))" end always_assert(isempty(missing)) always_assert(kwargs[:authorization] ∈ (:normal, :jll)) From a6a07ac2dadda2328e4af2786f1c4f2e5145c947 Mon Sep 17 00:00:00 2001 From: MarkNahabedian Date: Mon, 23 Jan 2023 09:59:12 -0500 Subject: [PATCH 06/27] Remove no longer applicable 'env_threshold' testset. --- test/runtests.jl | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 2ac26646..26018ffd 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -45,25 +45,4 @@ ENV["JULIA_PKG_SERVER"] = "" include("automerge-integration.jl") end end - - @testset "env_threshold" begin - e = RegistryCI.env_threshold - ENV["zero"] = "0" - ENV["zerodotzero"] = "0.0" - ENV["zerodotzeropct"] = "0.0%" - ENV["pct"] = "12%" - ENV["fracpct"] = "20.5%" - ENV["negcount"] = "-1" - ENV["count"] = "123" - # How can we test if a warning was logged? - @test e("zero", 0.1) == 0 - @test e("zero", 0.1) isa Integer - @test e("zerodotzero", 0.1) == 0.1 # default - @test e("zerodotzeropct", 0.1) == 0.0 - @test e("zerodotzeropct", 0.1) isa Float32 - @test e("pct", 0) == 0.12f0 - @test e("fracpct", 0) == 0.205f0 - @test e("negcount", 10) == 10 # default - @test e("count", 0) == 123 - end end From 94f7a69e620e965b3ed5f95066cadc83ad89d82b Mon Sep 17 00:00:00 2001 From: MarkNahabedian Date: Tue, 24 Jan 2023 14:53:39 -0500 Subject: [PATCH 07/27] Further work on new Guideline guideline_linecounts_meet_thresholds to check that a new package has enough test code and documentation. Use a Dict to pass Guideline parameters from the arglist of run opaquely through pull_request_build and check! to the various guidelines. Existing guideline parameters have not yet been moved to this Dict. Added this Dict parameter to every Guideline check function. Report which keyword arguments are missing from GitHubAutoMergeData using @warn. Moved new code from previous change in src/utils.jl to src/AutoMerge/util.jl. Extracted depot setup code from AutoMerge.parse_registry_pkg_info to new function setup_depot so that it is available to other guideline tests. "AutoMerge.linecounts_meet_thresholds" testset passes. --- src/AutoMerge/guidelines.jl | 113 +++++++++++++++++++-------------- src/AutoMerge/public.jl | 19 ++++++ src/AutoMerge/pull_requests.jl | 10 ++- src/AutoMerge/types.jl | 14 ++-- src/AutoMerge/util.jl | 32 ++++++++++ src/utils.jl | 33 ---------- test/automerge-unit.jl | 56 ++++++++++++---- 7 files changed, 174 insertions(+), 103 deletions(-) diff --git a/src/AutoMerge/guidelines.jl b/src/AutoMerge/guidelines.jl index 888a1d90..e48281ea 100644 --- a/src/AutoMerge/guidelines.jl +++ b/src/AutoMerge/guidelines.jl @@ -1,4 +1,5 @@ using HTTP: HTTP +import PackageAnalyzer const guideline_registry_consistency_tests_pass = Guideline(; info="Registy consistency tests", @@ -25,7 +26,8 @@ const guideline_compat_for_julia = Guideline(; "There is an upper-bounded `[compat]` entry for `julia` that ", "only includes a finite number of breaking releases of Julia.", ), - check=data -> meets_compat_for_julia(data.registry_head, data.pkg, data.version), + check=(data, guideline_parameters) -> + meets_compat_for_julia(data.registry_head, data.pkg, data.version), ) function meets_compat_for_julia(working_directory::AbstractString, pkg, version) @@ -73,7 +75,8 @@ const guideline_compat_for_all_deps = Guideline(; "are upper-bounded and only include a finite number of breaking releases. ", "For more information, please see the \"Upper-bounded `[compat]` entries\" subsection under \"Additional information\" below.", ), - check=data -> meets_compat_for_all_deps(data.registry_head, data.pkg, data.version), + check=(data, guideline_parameters) -> + meets_compat_for_all_deps(data.registry_head, data.pkg, data.version), ) function meets_compat_for_all_deps(working_directory::AbstractString, pkg, version) @@ -150,12 +153,13 @@ end const guideline_patch_release_does_not_narrow_julia_compat = Guideline(; info="If it is a patch release on a post-1.0 package, then it does not narrow the `[compat]` range for `julia`.", - check=data -> meets_patch_release_does_not_narrow_julia_compat( - data.pkg, - data.version; - registry_head=data.registry_head, - registry_master=data.registry_master, - ), + check=(data, guideline_parameters) -> + meets_patch_release_does_not_narrow_julia_compat( + data.pkg, + data.version; + registry_head=data.registry_head, + registry_master=data.registry_master, + ), ) function meets_patch_release_does_not_narrow_julia_compat( @@ -200,7 +204,7 @@ const _AUTOMERGE_NEW_PACKAGE_MINIMUM_NAME_LENGTH = 5 const guideline_name_length = Guideline(; info="Name not too short", docs="The name is at least $(_AUTOMERGE_NEW_PACKAGE_MINIMUM_NAME_LENGTH) characters long.", - check=data -> meets_name_length(data.pkg), + check=(data, guideline_parameters) -> meets_name_length(data.pkg), ) function meets_name_length(pkg) @@ -215,7 +219,7 @@ end const guideline_name_ascii = Guideline(; info="Name is composed of ASCII characters only.", - check=data -> meets_name_ascii(data.pkg), + check=(data, guideline_parameters) -> meets_name_ascii(data.pkg), ) function meets_name_ascii(pkg) @@ -228,7 +232,7 @@ end const guideline_julia_name_check = Guideline(; info="Name does not include \"julia\" or start with \"Ju\".", - check=data -> meets_julia_name_check(data.pkg), + check=(data, guideline_parameters) -> meets_julia_name_check(data.pkg), ) function meets_julia_name_check(pkg) @@ -263,7 +267,8 @@ To prevent confusion between similarly named packages, the names of new packages between the package name and any existing package must exceeds a certain a hand-chosen threshold (currently 2.5). """, - check=data -> meets_distance_check(data.pkg, data.registry_master), + check=(data, guideline_parameters) -> + meets_distance_check(data.pkg, data.registry_master), ) function meets_distance_check( @@ -377,7 +382,8 @@ const guideline_normal_capitalization = Guideline(; "contain only ASCII alphanumeric characters, ", "and contain at least one lowercase letter.", ), - check=data -> meets_normal_capitalization(data.pkg), + check=(data, guideline_parameters) -> + meets_normal_capitalization(data.pkg), ) function meets_normal_capitalization(pkg) @@ -392,7 +398,8 @@ end const guideline_repo_url_requirement = Guideline(; info="Repo URL ends with `/PackageName.jl.git`.", - check=data -> meets_repo_url_requirement(data.pkg; registry_head=data.registry_head), + check=(data, guideline_parameters) -> + meets_repo_url_requirement(data.pkg; registry_head=data.registry_head), ) function meets_repo_url_requirement(pkg::String; registry_head::String) @@ -446,7 +453,7 @@ const guideline_sequential_version_number = Guideline(; "Invalid new versions include `1.0.2` (skips `1.0.1`), ", "`1.3.0` (skips `1.2.0`), `3.0.0` (skips `2.0.0`) etc.", ), - check=data -> meets_sequential_version_number( + check=(data, guideline_parameters) -> meets_sequential_version_number( data.pkg, data.version; registry_head=data.registry_head, @@ -488,7 +495,8 @@ end const guideline_standard_initial_version_number = Guideline(; info="Standard initial version number. Must be one of: `0.0.1`, `0.1.0`, `1.0.0`, or `X.0.0`.", - check=data -> meets_standard_initial_version_number(data.version), + check=(data, guideline_parameters) -> + meets_standard_initial_version_number(data.version), ) function meets_standard_initial_version_number(version) @@ -540,7 +548,7 @@ end const guideline_code_can_be_downloaded = Guideline(; info="Code can be downloaded.", - check=data -> meets_code_can_be_downloaded( + check=(data, guideline_parameters) -> meets_code_can_be_downloaded( data.registry_head, data.pkg, data.version, @@ -609,7 +617,7 @@ end const guideline_src_names_OK = Guideline(; info="`src` files and directories names are OK", - check=data -> meets_src_names_ok(data.pkg_code_path), + check=(data, guideline_parameters) -> meets_src_names_ok(data.pkg_code_path), ) function meets_code_can_be_downloaded(registry_head, pkg, version, pr; pkg_code_path) @@ -662,7 +670,7 @@ is_valid_url(str::AbstractString) = !isempty(HTTP.URI(str).scheme) && isvalid(HT const guideline_version_can_be_pkg_added = Guideline(; info="Version can be `Pkg.add`ed", docs="Package installation: The package should be installable (`Pkg.add(\"PackageName\")`).", - check=data -> meets_version_can_be_pkg_added( + check=(data, guideline_parameters) -> meets_version_can_be_pkg_added( data.registry_head, data.pkg, data.version; @@ -731,7 +739,8 @@ const guideline_version_has_osi_license = Guideline(; "This check is required for the General registry. ", "For other registries, registry maintainers have the option to disable this check.", ), - check=data -> meets_version_has_osi_license(data.pkg; pkg_code_path=data.pkg_code_path), + check=(data, guideline_parameters) -> + meets_version_has_osi_license(data.pkg; pkg_code_path=data.pkg_code_path), ) function meets_version_has_osi_license(pkg::String; pkg_code_path) @@ -793,7 +802,7 @@ end const guideline_version_can_be_imported = Guideline(; info="Version can be `import`ed", docs="Package loading: The package should be loadable (`import PackageName`).", - check=data -> meets_version_can_be_imported( + check=(data, guideline_parameters) -> meets_version_can_be_imported( data.registry_head, data.pkg, data.version; @@ -860,46 +869,53 @@ end const guideline_linecounts_meet_thresholds = Guideline(; info="Test that lines of source, tests and documentation meet specified thresholds", docs="""Make sure that various line counts meet or exceed specified thresholds. -Thresholds are controlled by these environment variables: - * SRC_MIN_LINES: Minimum number of lines of source code - * README_MIN_LINES: % Minimum number of lines in the README file - * TEST_MIN_LINES: % Minimum number of lines of code in the test directory - * DOC_MIN_LINES: # Minimum number of lines of documentation - -Those marked with a % can be expressed as a count, or as a percentage -of the number of lines of source code. For TEST_MIN_LINES and -DOC_MIN_LINES, the denominatttor of the percentage also includes the +Thresholds are controlled by these fields of GitHubAutoMergeData: + * src_min_lines: Minimum number of lines of source code + * readme_min_lines: % Minimum number of lines in the README file + * test_min_lines: % Minimum number of lines of code in the test directory + * doc_min_lines: # Minimum number of lines of documentation + +Those marked with a % can be expressed as a count, or as a fraction +of the number of lines of source code. For test_min_lines and +doc_min_lines, the denominator of the fraction also includes the number of lines of test code. """, - check=data -> linecounts_meet_thresholds(data.pkg_code_path) + check=(data, guideline_parameters) -> + linecounts_meet_thresholds(data.pkg_code_path, guideline_parameters) ) -function linecounts_meet_thresholds(pkg_code_path::String) - analysis = PackageAnalyzer.analyze(pkg_code_path) - if isempty(p.lines_of_code) +function linecounts_meet_thresholds(pkg_code_path, + guideline_parameters) + analysis = PackageAnalyzer.analyze(pkg_code_path;) + # @info analysis + if isempty(analysis.lines_of_code) return false, "PackageAnalyzer didn't find any lines of code." end + # get parameters: + src_min_lines = get(guideline_parameters, :src_min_lines, 10) + readme_min_lines = get(guideline_parameters, :readme_min_lines, 5) + test_min_lines = get(guideline_parameters, :test_min_lines, 0.1f0) + doc_min_lines = get(guideline_parameters, :doc_min_lines, 0.1f0) issues = [] - src_line_count = PackageAnalyzer.count_julia_loc(p, "src") - if !meets_threshold(env_threshold("README_MIN_LINES", 5), + src_line_count = PackageAnalyzer.count_julia_loc(analysis, "src") + if !meets_threshold(readme_min_lines, PackageAnalyzer.count_readme(analysis), src_line_count) push!(issues, "Package README file is too short") end - if !meets_threshold(env_threshold_count("SRC_MIN_LINES", 10), - src_line_count) - push!(issues, "Too few linwes of source code.") + if !meets_threshold(src_min_lines, src_line_count) + push!(issues, "Too few lines of source code.") end - test_line_count = count_julia_loc(p, "test") - if !!meets_threshold(env_threshold("TEST_MIN_LINES", 0.1f0), - test_line_count, - test_line_count + src_line_count) + test_line_count = PackageAnalyzer.count_julia_loc(analysis, "test") + if !meets_threshold(test_min_lines, + test_line_count, + test_line_count + src_line_count) push!(issues, "Too few lines of test code.") end - docs_line_count = PackageAnalyzer.count_docs(p) - if !meets_threshold(env_threshold("DOC_MIN_LINES", 0.1f0), - docs_line_count, - docs_line_count + src_line_count) + docs_line_count = PackageAnalyzer.count_docs(analysis) + if !meets_threshold(doc_min_lines, + docs_line_count, + docs_line_count + src_line_count) push!(issues, "Too few lines of documentation.") end if isempty(issues) @@ -1034,6 +1050,7 @@ function get_automerge_guidelines( # the automerge comment. To make the comment easy # to read, we want this list to be at the end. (guideline_distance_check, true), + (guideline_linecounts_meet_thresholds, true), ] return guidelines end @@ -1066,6 +1083,8 @@ function get_automerge_guidelines( (guideline_version_has_osi_license, check_license), (guideline_src_names_OK, true), (guideline_version_can_be_imported, true), + # Do we want to check this for new versions? + # (guideline_linecounts_meet_thresholds, true), ] return guidelines end diff --git a/src/AutoMerge/public.jl b/src/AutoMerge/public.jl index c1024733..463b61e5 100644 --- a/src/AutoMerge/public.jl +++ b/src/AutoMerge/public.jl @@ -61,6 +61,11 @@ RegistryCI.AutoMerge.run( additional_check_runs = String[], check_license = true, public_registries = String["https://github.com/HolyLab/HolyLabRegistry"], + # Parameters for guideline_linecounts_meet_thresholds + src_min_lines::Integer, + readme_min_linges::Union{Integer, AbstractFloat}, + test_min_lines::Union{Integer, AbstractFloat}, + doc_min_lines::Union{Integer, AbstractFloat}, ) ``` """ @@ -99,7 +104,20 @@ function run(; public_registries::Vector{<:AbstractString}=String[], read_only::Bool=false, environment_variables_to_pass::Vector{<:AbstractString}=String[], + # Four parameters for guideline_linecounts_meet_thresholds + src_min_lines, + readme_min_lines, + test_min_lines, + doc_min_lines, )::Nothing + # guideline_parameters is for parameters that are passed directly + # from run through to the various Guidelines without modification: + guideline_parameters = Dict{Symbol, Any}( + :src_min_lines => src_min_lines, + :readme_min_lines => readme_min_lines, + :test_min_lines => test_min_lines, + :doc_min_lines => doc_min_lines, + ) all_statuses = deepcopy(additional_statuses) all_check_runs = deepcopy(additional_check_runs) push!(all_statuses, "automerge/decision") @@ -140,6 +158,7 @@ function run(; pr_head_commit_sha = current_pr_head_commit_sha(cicfg; env=env) pull_request_build( api, + guideline_parameters, pr_number, pr_head_commit_sha, registry_repo, diff --git a/src/AutoMerge/pull_requests.jl b/src/AutoMerge/pull_requests.jl index 92671bc7..950e7dc5 100644 --- a/src/AutoMerge/pull_requests.jl +++ b/src/AutoMerge/pull_requests.jl @@ -71,6 +71,7 @@ end function pull_request_build( api::GitHub.GitHubAPI, + guideline_parameters::Dict{Symbol, Any}, pr_number::Integer, current_pr_head_commit_sha::String, registry::GitHub.Repo, @@ -163,12 +164,15 @@ function pull_request_build( read_only=read_only, environment_variables_to_pass=environment_variables_to_pass, ) - pull_request_build(data; check_license=check_license) + pull_request_build(data, guideline_parameters; + check_license=check_license) rm(registry_master; force=true, recursive=true) return nothing end -function pull_request_build(data::GitHubAutoMergeData; check_license)::Nothing +function pull_request_build(data::GitHubAutoMergeData, + guideline_parameters::Dict{Symbol, Any},; + check_license)::Nothing kind = package_or_version(data.registration_type) this_is_jll_package = is_jll_name(data.pkg) @info( @@ -208,7 +212,7 @@ function pull_request_build(data::GitHubAutoMergeData; check_license)::Nothing ) end else - check!(guideline, data) + check!(guideline, data, guideline_parameters) @info( guideline.info, meets_this_guideline = passed(guideline), diff --git a/src/AutoMerge/types.jl b/src/AutoMerge/types.jl index de08e5b5..1fe137d7 100644 --- a/src/AutoMerge/types.jl +++ b/src/AutoMerge/types.jl @@ -113,11 +113,11 @@ function GitHubAutoMergeData(; kwargs...) pkg_code_path = mktempdir(; cleanup=true) kwargs = (; pkg_code_path=pkg_code_path, kwargs...) fields = fieldnames(GitHubAutoMergeData) - missing = setdiff(Set(keys(kwargs)), Set(fields)) - if !isempty(missing) - @warn "Keyword/field mismatch while constructing a GitHubAutoMergeData: $(join(missing, ", "))" + mismatch = setdiff(Set(keys(kwargs)), Set(fields)) + if !isempty(mismatch) + @warn "Keyword/field mismatch while constructing a GitHubAutoMergeData: $(join(mismatchmissing, ", "))" end - always_assert(isempty(missing)) + always_assert(isempty(mismatch)) always_assert(kwargs[:authorization] ∈ (:normal, :jll)) return GitHubAutoMergeData(getindex.(Ref(kwargs), fields)...) end @@ -152,6 +152,8 @@ end passed(guideline::Guideline) = guideline.passed message(guideline::Guideline) = guideline.message -function check!(guideline::Guideline, data::GitHubAutoMergeData) - return guideline.passed, guideline.message = guideline.check(data) +function check!(guideline::Guideline, data::GitHubAutoMergeData, + guideline_parameters::Dict{Symbol, Any},) + return guideline.passed, guideline.message = + guideline.check(data, guideline_parameters) end diff --git a/src/AutoMerge/util.jl b/src/AutoMerge/util.jl index 99d15472..7b72ce99 100644 --- a/src/AutoMerge/util.jl +++ b/src/AutoMerge/util.jl @@ -292,3 +292,35 @@ function get_all_non_jll_package_names(registry_dir::AbstractString) unique!(packages) return packages end + + +""" + meets_threshold(threshold, numerator, [denominator]) + +Test the value of `numerator` or `numerator / denominaror` against +some threshold to be satisfed. + +If the value is an integer then it must be greater than or equal to numerator +to satisfy the test. + +If the value is a float, it must be greater than or equal to ``numerator/denominator` +to satisfy the test. +""" +function meets_threshold end + +function meets_threshold(threshold::Integer, linecount::Integer) + # @info("meets_threshold", threshold, linecount, linecount >= threshold) + linecount >= threshold +end + +function meets_threshold(threshold::Integer, numerator::Integer, ::Integer) + # @info("meets_threshold", threshold, numerator, numerator >= threshold) + numerator >= threshold +end + +function meets_threshold(threshold::AbstractFloat, numerator::Integer, denominator::Integer) + # @info("meets_threshold", threshold, numerator, denominator, + (numerator / denominator) >= threshold) + (numerator / denominator) >= threshold +end + diff --git a/src/utils.jl b/src/utils.jl index 3a20823a..099c714e 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -48,36 +48,3 @@ function env_threshold_count(envvar::String, default) default end - -""" - env_threshold(envvar::String, default) - -Return an integer (intrerpreted as a number of lines) or a fraction read -from the specified environment variable. -""" -function env_threshold(envvar::String, default) - v = get(ENV, envvar, nothing) - if v == nothing - return default - end - m = match(r"(?^[0-9]+.?[0-9]*+)%$", v) - if m != nothing - return parse(Float32, m["pct"]) / 100 - end - m = match(r"(?^[0-9]+)$", v) - if m != nothing - return parse(Int64, m["count"]) - end - @warn "Value $v of environment variable $envvar is neither a percentage nor a line count. Using default of $default" - default -end - -meets_threshold(threshold::Integer, linecount::Integer) = - linecount >= threshhols - -meets_threshold(threshold::Integer, numerator::Integer, ::Integer) = - numerator >= threshold - -meets_threshold(thresholdr::AbstractFloat, numerator::Integer, denominator::Integer) = - numerator / denominator >= threshhols - diff --git a/test/automerge-unit.jl b/test/automerge-unit.jl index 83bacfdc..9f0d9f69 100644 --- a/test/automerge-unit.jl +++ b/test/automerge-unit.jl @@ -10,6 +10,27 @@ using TimeZones const AutoMerge = RegistryCI.AutoMerge +TEMP_DEPOT_FOR_TESTING = nothing + +function setup_depot()::String + global TEMP_DEPOT_FOR_TESTING + if TEMP_DEPOT_FOR_TESTING isa String + return TEMP_DEPOT_FOR_TESTING + end + tmp_depot = mktempdir() + env1 = copy(ENV) + env1["JULIA_DEPOT_PATH"] = tmp_depot + delete!(env1, "JULIA_LOAD_PATH") + delete!(env1, "JULIA_PROJECT") + env2 = copy(env1) + env2["JULIA_PKG_SERVER"] = "" + run(setenv(`julia -e 'import Pkg; Pkg.Registry.add("General")'`, env2)) + run(setenv(`julia -e 'import Pkg; Pkg.add(["RegistryCI"])'`, env1)) + TEMP_DEPOT_FOR_TESTING = tmp_depot + tmp_depot +end + + # helper for testing `AutoMerge.meets_version_has_osi_license` function pkgdir_from_depot(depot_path::String, pkg::String) pkgdir_parent = joinpath(depot_path, "packages", pkg) @@ -23,6 +44,7 @@ function pkgdir_from_depot(depot_path::String, pkg::String) return only_pkdir end + @testset "Utilities" begin @testset "`AutoMerge.parse_registry_pkg_info`" begin registry_path = joinpath(DEPOT_PATH[1], "registries", "General") @@ -573,20 +595,12 @@ end @testset "`AutoMerge.meets_version_has_osi_license`" begin # Let's install a fresh depot in a temporary directory # and add some packages to inspect. - tmp_depot = mktempdir() + tmp_depot = setup_depot() function has_osi_license_in_depot(pkg) return AutoMerge.meets_version_has_osi_license( pkg; pkg_code_path=pkgdir_from_depot(tmp_depot, pkg) ) end - env1 = copy(ENV) - env1["JULIA_DEPOT_PATH"] = tmp_depot - delete!(env1, "JULIA_LOAD_PATH") - delete!(env1, "JULIA_PROJECT") - env2 = copy(env1) - env2["JULIA_PKG_SERVER"] = "" - run(setenv(`julia -e 'import Pkg; Pkg.Registry.add("General")'`, env2)) - run(setenv(`julia -e 'import Pkg; Pkg.add(["RegistryCI"])'`, env1)) # Let's test ourselves and some of our dependencies that just have MIT licenses: result = has_osi_license_in_depot("RegistryCI") @test result[1] @@ -617,10 +631,24 @@ end @test !result[1] end - @testset "`AutoMerge.linecounts_meet_thresholds" begin - tmp_depot = mktempdir() - pkg_path = pkgdir_from_depot(tmp_depot, "VisualStringDistances") - result = AutoMerge.linecounts_meet_thresholds(pkg_path) - @test result = (true, "") + @testset "AutoMerge.linecounts_meet_thresholds" begin + registry = "JuliaRegistries/General" + tmp_depot = setup_depot() + package_name = "RegistryCI" + pkg_code_path = pkgdir_from_depot(tmp_depot, package_name) + guideline_parameters = Dict{Symbol, Any}( + :src_min_lines => 10, + :readme_min_lines => 5, + :test_min_lines => 0.1f0, + :doc_min_lines => 0.1f0, + ) + @test pkg_code_path isa AbstractString + result = AutoMerge.linecounts_meet_thresholds( + pkg_code_path, guideline_parameters) + @test result == (false, "Too few lines of documentation.") + guideline_parameters[:doc_min_lines] = 0.05f0 + result = AutoMerge.linecounts_meet_thresholds( + pkg_code_path, guideline_parameters) + @test result == (true, "") end end From eee7c517ab8b9e5ec0e363c3ac4e378678d416b0 Mon Sep 17 00:00:00 2001 From: MarkNahabedian Date: Tue, 24 Jan 2023 18:49:23 -0500 Subject: [PATCH 08/27] Oops, I need to be more carefful commenting out loggins. --- src/AutoMerge/util.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/AutoMerge/util.jl b/src/AutoMerge/util.jl index 7b72ce99..79313245 100644 --- a/src/AutoMerge/util.jl +++ b/src/AutoMerge/util.jl @@ -319,8 +319,7 @@ function meets_threshold(threshold::Integer, numerator::Integer, ::Integer) end function meets_threshold(threshold::AbstractFloat, numerator::Integer, denominator::Integer) - # @info("meets_threshold", threshold, numerator, denominator, - (numerator / denominator) >= threshold) + # @info("meets_threshold", threshold, numerator, denominator, (numerator / denominator) >= threshold) (numerator / denominator) >= threshold end From 37bf9b6aef186c652f054db652d1e019807ad7c7 Mon Sep 17 00:00:00 2001 From: MarkNahabedian Date: Tue, 24 Jan 2023 22:58:02 -0500 Subject: [PATCH 09/27] PackageAnalyzer constrains Julia version to 1.6 or greater. --- src/AutoMerge/guidelines.jl | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/AutoMerge/guidelines.jl b/src/AutoMerge/guidelines.jl index e48281ea..fa14be80 100644 --- a/src/AutoMerge/guidelines.jl +++ b/src/AutoMerge/guidelines.jl @@ -1050,7 +1050,9 @@ function get_automerge_guidelines( # the automerge comment. To make the comment easy # to read, we want this list to be at the end. (guideline_distance_check, true), - (guideline_linecounts_meet_thresholds, true), + (guideline_linecounts_meet_thresholds, + # PackageAnalyzer constrains Julia version to 1.6 or newer: + VERSION >= v"1.6"), ] return guidelines end @@ -1083,8 +1085,11 @@ function get_automerge_guidelines( (guideline_version_has_osi_license, check_license), (guideline_src_names_OK, true), (guideline_version_can_be_imported, true), - # Do we want to check this for new versions? - # (guideline_linecounts_meet_thresholds, true), + #= Do we want to check this for new versions? + (guideline_linecounts_meet_thresholds, + # PackageAnalyzer constrains Julia version to 1.6 or newer: + VERSION >= v"1.6") + =# ] return guidelines end From 1b9e848bde8bd5df94676f3bf014a803ef1c50c2 Mon Sep 17 00:00:00 2001 From: Mark Nahabedian <33787283+MarkNahabedian@users.noreply.github.com> Date: Wed, 25 Jan 2023 19:57:04 -0500 Subject: [PATCH 10/27] Update src/AutoMerge/guidelines.jl Co-authored-by: Eric Hanson <5846501+ericphanson@users.noreply.github.com> --- src/AutoMerge/guidelines.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AutoMerge/guidelines.jl b/src/AutoMerge/guidelines.jl index fa14be80..4fa06518 100644 --- a/src/AutoMerge/guidelines.jl +++ b/src/AutoMerge/guidelines.jl @@ -901,7 +901,7 @@ function linecounts_meet_thresholds(pkg_code_path, if !meets_threshold(readme_min_lines, PackageAnalyzer.count_readme(analysis), src_line_count) - push!(issues, "Package README file is too short") + push!(issues, "Package README file is too short. Counted $(src_line_count) lines, but at least $(readme_min_lines) lines are required.") end if !meets_threshold(src_min_lines, src_line_count) push!(issues, "Too few lines of source code.") From 75cbbf36fd6d54a7030a976f1b8ca7bd85dd6768 Mon Sep 17 00:00:00 2001 From: Mark Nahabedian <33787283+MarkNahabedian@users.noreply.github.com> Date: Wed, 25 Jan 2023 20:03:23 -0500 Subject: [PATCH 11/27] Update src/AutoMerge/guidelines.jl Co-authored-by: Eric Hanson <5846501+ericphanson@users.noreply.github.com> --- src/AutoMerge/guidelines.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AutoMerge/guidelines.jl b/src/AutoMerge/guidelines.jl index 4fa06518..c727a470 100644 --- a/src/AutoMerge/guidelines.jl +++ b/src/AutoMerge/guidelines.jl @@ -894,8 +894,8 @@ function linecounts_meet_thresholds(pkg_code_path, # get parameters: src_min_lines = get(guideline_parameters, :src_min_lines, 10) readme_min_lines = get(guideline_parameters, :readme_min_lines, 5) - test_min_lines = get(guideline_parameters, :test_min_lines, 0.1f0) - doc_min_lines = get(guideline_parameters, :doc_min_lines, 0.1f0) + test_min_lines = get(guideline_parameters, :test_min_lines, 10) + doc_min_lines = get(guideline_parameters, :doc_min_lines, 10) issues = [] src_line_count = PackageAnalyzer.count_julia_loc(analysis, "src") if !meets_threshold(readme_min_lines, From 48eb3481ec555b7ca201020f091b0a02289e3912 Mon Sep 17 00:00:00 2001 From: MarkNahabedian Date: Wed, 25 Jan 2023 22:16:00 -0500 Subject: [PATCH 12/27] Revert 37bf9b6aef186c652f054db652d1e019807ad7c7 since the problem it was intended to fix happens much earlier. Make sure guideline_distance_check is last, as the comment says it should be. --- src/AutoMerge/guidelines.jl | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/AutoMerge/guidelines.jl b/src/AutoMerge/guidelines.jl index fa14be80..ad6d46dd 100644 --- a/src/AutoMerge/guidelines.jl +++ b/src/AutoMerge/guidelines.jl @@ -1044,15 +1044,13 @@ function get_automerge_guidelines( (guideline_version_can_be_imported, true), (:update_status, true), (guideline_dependency_confusion, true), + (guideline_linecounts_meet_thresholds, true), # We always run the `guideline_distance_check` # check last, because if the check fails, it # prints the list of similar package names in # the automerge comment. To make the comment easy # to read, we want this list to be at the end. (guideline_distance_check, true), - (guideline_linecounts_meet_thresholds, - # PackageAnalyzer constrains Julia version to 1.6 or newer: - VERSION >= v"1.6"), ] return guidelines end @@ -1086,9 +1084,7 @@ function get_automerge_guidelines( (guideline_src_names_OK, true), (guideline_version_can_be_imported, true), #= Do we want to check this for new versions? - (guideline_linecounts_meet_thresholds, - # PackageAnalyzer constrains Julia version to 1.6 or newer: - VERSION >= v"1.6") + (guideline_linecounts_meet_thresholds, true*) =# ] return guidelines From 6484879e52c6de64a60ae955196846d95526d3ca Mon Sep 17 00:00:00 2001 From: MarkNahabedian Date: Wed, 25 Jan 2023 22:19:24 -0500 Subject: [PATCH 13/27] Compat entry for PackageAnalyzer. --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index dc6a60e6..361ec44a 100644 --- a/Project.toml +++ b/Project.toml @@ -31,6 +31,7 @@ GitHub = "5.2" HTTP = "0.8, 0.9.1, 1" JSON = "0.19, 0.20, 0.21" LicenseCheck = "0.2" +PackageAnalyzer = "1" RegistryTools = "1.5.5" SimpleMock = "1" StringDistances = "0.9, 0.10, 0.11" From f36a8e00fd088a8ed37ee858848cea881cf5a198 Mon Sep 17 00:00:00 2001 From: MarkNahabedian Date: Wed, 25 Jan 2023 22:27:31 -0500 Subject: [PATCH 14/27] Set defaults parameter values for guideline_linecounts_meet_thresholds in fun, as well as in the guideline function. Set the defaults to 0 so that once this code isa in place, the guideline is a no-op until configured in a workflow. --- src/AutoMerge/guidelines.jl | 8 ++++---- src/AutoMerge/public.jl | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/AutoMerge/guidelines.jl b/src/AutoMerge/guidelines.jl index 39e97106..6877215a 100644 --- a/src/AutoMerge/guidelines.jl +++ b/src/AutoMerge/guidelines.jl @@ -892,10 +892,10 @@ function linecounts_meet_thresholds(pkg_code_path, return false, "PackageAnalyzer didn't find any lines of code." end # get parameters: - src_min_lines = get(guideline_parameters, :src_min_lines, 10) - readme_min_lines = get(guideline_parameters, :readme_min_lines, 5) - test_min_lines = get(guideline_parameters, :test_min_lines, 10) - doc_min_lines = get(guideline_parameters, :doc_min_lines, 10) + src_min_lines = get(guideline_parameters, :src_min_lines, 0) + readme_min_lines = get(guideline_parameters, :readme_min_lines, 0) + test_min_lines = get(guideline_parameters, :test_min_lines, 0) + doc_min_lines = get(guideline_parameters, :doc_min_lines, 0) issues = [] src_line_count = PackageAnalyzer.count_julia_loc(analysis, "src") if !meets_threshold(readme_min_lines, diff --git a/src/AutoMerge/public.jl b/src/AutoMerge/public.jl index 463b61e5..d91fa0ea 100644 --- a/src/AutoMerge/public.jl +++ b/src/AutoMerge/public.jl @@ -105,10 +105,10 @@ function run(; read_only::Bool=false, environment_variables_to_pass::Vector{<:AbstractString}=String[], # Four parameters for guideline_linecounts_meet_thresholds - src_min_lines, - readme_min_lines, - test_min_lines, - doc_min_lines, + src_min_lines=0, + readme_min_lines=0, + test_min_lines=0, + doc_min_lines=0, )::Nothing # guideline_parameters is for parameters that are passed directly # from run through to the various Guidelines without modification: From 4ed3e65419f9d6d600cc45ca7d91208b60a99474 Mon Sep 17 00:00:00 2001 From: MarkNahabedian Date: Wed, 25 Jan 2023 22:29:49 -0500 Subject: [PATCH 15/27] Remove env_threshold_count which is no longer used. --- src/utils.jl | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/utils.jl b/src/utils.jl index 099c714e..43ebddd6 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -28,23 +28,3 @@ function with_temp_depot(f::Function) return result end - -""" - env_threshold_count(envvar::String, default) - -Return an integer (intrerpreted as a number of lines) read -from the specified environment variable. -""" -function env_threshold_count(envvar::String, default) - v = get(ENV, envvar, nothing) - if v == nothing - return default - end - m = match(r"(?^[0-9]+)$", v) - if m != nothing - return parse(Int64, m["count"]) - end - @warn "Value $v of environment variable $envvar is not a line count. Using default of $default" - default -end - From edcf26dc746189e8bf1e4f57935458400eaa225a Mon Sep 17 00:00:00 2001 From: MarkNahabedian Date: Wed, 25 Jan 2023 22:37:58 -0500 Subject: [PATCH 16/27] meets_threshold now asserts bounds on thresholds. --- src/AutoMerge/util.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/AutoMerge/util.jl b/src/AutoMerge/util.jl index 79313245..622724e3 100644 --- a/src/AutoMerge/util.jl +++ b/src/AutoMerge/util.jl @@ -309,16 +309,19 @@ to satisfy the test. function meets_threshold end function meets_threshold(threshold::Integer, linecount::Integer) + @assert threshold >= 0 # @info("meets_threshold", threshold, linecount, linecount >= threshold) linecount >= threshold end function meets_threshold(threshold::Integer, numerator::Integer, ::Integer) + @assert threshold >= 0 # @info("meets_threshold", threshold, numerator, numerator >= threshold) numerator >= threshold end function meets_threshold(threshold::AbstractFloat, numerator::Integer, denominator::Integer) + @assert threshold >= 0.0 && threshold < 1.0 # @info("meets_threshold", threshold, numerator, denominator, (numerator / denominator) >= threshold) (numerator / denominator) >= threshold end From f8b127555bdf927b93fa190d048d3b78f7fa3073 Mon Sep 17 00:00:00 2001 From: Eric Hanson <5846501+ericphanson@users.noreply.github.com> Date: Thu, 26 Jan 2023 14:29:49 +0100 Subject: [PATCH 17/27] Update Project.toml --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 361ec44a..2daf3309 100644 --- a/Project.toml +++ b/Project.toml @@ -31,7 +31,7 @@ GitHub = "5.2" HTTP = "0.8, 0.9.1, 1" JSON = "0.19, 0.20, 0.21" LicenseCheck = "0.2" -PackageAnalyzer = "1" +PackageAnalyzer = "0.2, 1" RegistryTools = "1.5.5" SimpleMock = "1" StringDistances = "0.9, 0.10, 0.11" From 8c1dd574ecbb43d73daa3eaa5f3bea222c610433 Mon Sep 17 00:00:00 2001 From: MarkNahabedian Date: Thu, 26 Jan 2023 15:22:05 -0500 Subject: [PATCH 18/27] Oops. Meant to remove the linecount thresholds from GitHubAutoMergeData when I created the parameters Dict. --- src/AutoMerge/types.jl | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/AutoMerge/types.jl b/src/AutoMerge/types.jl index 1fe137d7..ee687c74 100644 --- a/src/AutoMerge/types.jl +++ b/src/AutoMerge/types.jl @@ -100,12 +100,6 @@ struct GitHubAutoMergeData # Environment variables to pass to the subprocess that does `Pkg.add("Foo")` and `import Foo` environment_variables_to_pass::Vector{String} - - # Parameters for the linecounts_meet_thresholds guideline: - src_min_lines::Integer - readme_min_lines::Union{Integer, AbstractFloat} - test_min_lines::Union{Integer, AbstractFloat} - doc_min_lines::Union{Integer, AbstractFloat} end # Constructor that requires all fields (except `pkg_code_path`) as named arguments. From 507a16c352eb9c6486848474a2bc51422575c07b Mon Sep 17 00:00:00 2001 From: MarkNahabedian Date: Thu, 26 Jan 2023 15:30:11 -0500 Subject: [PATCH 19/27] Version gate for guideline_linecounts_meet_thresholds because PackageAnalyzer requires Julia version >= 1.6. --- src/AutoMerge/guidelines.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/AutoMerge/guidelines.jl b/src/AutoMerge/guidelines.jl index 6877215a..8738b5ec 100644 --- a/src/AutoMerge/guidelines.jl +++ b/src/AutoMerge/guidelines.jl @@ -1044,7 +1044,9 @@ function get_automerge_guidelines( (guideline_version_can_be_imported, true), (:update_status, true), (guideline_dependency_confusion, true), - (guideline_linecounts_meet_thresholds, true), + (guideline_linecounts_meet_thresholds, + # PackageAnalyzer constrains Julia version to 1.6 or newer: + VERSION >= v"1.6"), # We always run the `guideline_distance_check` # check last, because if the check fails, it # prints the list of similar package names in @@ -1084,7 +1086,9 @@ function get_automerge_guidelines( (guideline_src_names_OK, true), (guideline_version_can_be_imported, true), #= Do we want to check this for new versions? - (guideline_linecounts_meet_thresholds, true*) + (guideline_linecounts_meet_thresholds, + # PackageAnalyzer constrains Julia version to 1.6 or newer: + VERSION >= v"1.6") =# ] return guidelines From d1e04e6637dc8fa0a89fe9ebac8a2f1ea73e4754 Mon Sep 17 00:00:00 2001 From: MarkNahabedian Date: Wed, 1 Feb 2023 20:05:48 -0500 Subject: [PATCH 20/27] Add a separate set of parameters for ratio thresholds. Failure messages with too much information. Remove meets_threshold, which is no longer needed. --- Project.toml | 1 + src/AutoMerge/AutoMerge.jl | 1 + src/AutoMerge/guidelines.jl | 70 ++++++++++++++++++++++--------------- src/AutoMerge/public.jl | 6 ++++ src/AutoMerge/util.jl | 33 ----------------- test/automerge-unit.jl | 59 ++++++++++++++++++++++++++----- 6 files changed, 99 insertions(+), 71 deletions(-) diff --git a/Project.toml b/Project.toml index 2daf3309..1e8da585 100644 --- a/Project.toml +++ b/Project.toml @@ -12,6 +12,7 @@ JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" LibGit2 = "76f85450-5226-5b5a-8eaa-529ad045b433" LicenseCheck = "726dbf0d-6eb6-41af-b36c-cd770e0f00cc" Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" +OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" PackageAnalyzer = "e713c705-17e4-4cec-abe0-95bf5bf3e10c" Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" diff --git a/src/AutoMerge/AutoMerge.jl b/src/AutoMerge/AutoMerge.jl index d1888afd..4e27f22f 100644 --- a/src/AutoMerge/AutoMerge.jl +++ b/src/AutoMerge/AutoMerge.jl @@ -16,6 +16,7 @@ using Printf: Printf using RegistryTools: RegistryTools using ..RegistryCI: RegistryCI using Tar: Tar +using Printf include("types.jl") include("ciservice.jl") diff --git a/src/AutoMerge/guidelines.jl b/src/AutoMerge/guidelines.jl index 8738b5ec..42de2a25 100644 --- a/src/AutoMerge/guidelines.jl +++ b/src/AutoMerge/guidelines.jl @@ -871,14 +871,15 @@ const guideline_linecounts_meet_thresholds = Guideline(; docs="""Make sure that various line counts meet or exceed specified thresholds. Thresholds are controlled by these fields of GitHubAutoMergeData: * src_min_lines: Minimum number of lines of source code - * readme_min_lines: % Minimum number of lines in the README file - * test_min_lines: % Minimum number of lines of code in the test directory - * doc_min_lines: # Minimum number of lines of documentation - -Those marked with a % can be expressed as a count, or as a fraction -of the number of lines of source code. For test_min_lines and -doc_min_lines, the denominator of the fraction also includes the -number of lines of test code. + * readme_min_lines: Minimum number of lines in the README file + * test_min_lines: Minimum number of lines of code in the test directory + * doc_min_lines: Minimum number of lines of documentation + * readme_min_fraction minimum ratio of readme lines to src lines + * test_min_fraction minimum ratio of test lines to src lines + * doc_min_fraction minimum ratio of doc to src lines + +For test_min_fraction and doc_min_fraction, the denominator of the fraction +also includes the number of lines of test or docs respectively. """, check=(data, guideline_parameters) -> linecounts_meet_thresholds(data.pkg_code_path, guideline_parameters) @@ -892,32 +893,43 @@ function linecounts_meet_thresholds(pkg_code_path, return false, "PackageAnalyzer didn't find any lines of code." end # get parameters: - src_min_lines = get(guideline_parameters, :src_min_lines, 0) - readme_min_lines = get(guideline_parameters, :readme_min_lines, 0) - test_min_lines = get(guideline_parameters, :test_min_lines, 0) - doc_min_lines = get(guideline_parameters, :doc_min_lines, 0) + src_min_lines = get(guideline_parameters, :src_min_lines, 0) + readme_min_lines = get(guideline_parameters, :readme_min_lines, 0) + test_min_lines = get(guideline_parameters, :test_min_lines, 0) + doc_min_lines = get(guideline_parameters, :doc_min_lines, 0) + readme_min_fraction = get(guideline_parameters, :readme_min_fraction, 0.0) + test_min_fraction = get(guideline_parameters, :test_min_fraction, 0.0) + doc_min_fraction = get(guideline_parameters, :doc_min_fraction, 0.0) issues = [] src_line_count = PackageAnalyzer.count_julia_loc(analysis, "src") - if !meets_threshold(readme_min_lines, - PackageAnalyzer.count_readme(analysis), - src_line_count) - push!(issues, "Package README file is too short. Counted $(src_line_count) lines, but at least $(readme_min_lines) lines are required.") - end - if !meets_threshold(src_min_lines, src_line_count) - push!(issues, "Too few lines of source code.") - end test_line_count = PackageAnalyzer.count_julia_loc(analysis, "test") - if !meets_threshold(test_min_lines, - test_line_count, - test_line_count + src_line_count) - push!(issues, "Too few lines of test code.") - end docs_line_count = PackageAnalyzer.count_docs(analysis) - if !meets_threshold(doc_min_lines, - docs_line_count, - docs_line_count + src_line_count) - push!(issues, "Too few lines of documentation.") + readme_line_count = PackageAnalyzer.count_readme(analysis) + + function check_count(desc, got, want) + if got < want + push!(issues, "Too few lines of $desc: $got, where $want is required.") + end + end + check_count("source code", src_line_count, src_min_lines) + check_count("README file", readme_line_count, readme_min_lines) + check_count("documentation", docs_line_count, doc_min_lines) + check_count("test code", test_line_count, test_min_lines) + function check_fraction(desc, got, want) + if got < want + push!(issues, + @sprintf("The ratio of %s is less than required: %1.2f%% versus %1.2f%%.", + desc, 100 * got, 100 * want)) + end end + check_fraction("README lines to source code", + readme_line_count / src_line_count, readme_min_fraction) + check_fraction("documentation lines to documentation plus src lines", + docs_line_count / (docs_line_count + src_line_count), + doc_min_fraction) + check_fraction("test lines to test plus src lines", + test_line_count / (test_line_count + src_line_count), + test_min_fraction) if isempty(issues) return true, "" else diff --git a/src/AutoMerge/public.jl b/src/AutoMerge/public.jl index d91fa0ea..b986f289 100644 --- a/src/AutoMerge/public.jl +++ b/src/AutoMerge/public.jl @@ -107,16 +107,22 @@ function run(; # Four parameters for guideline_linecounts_meet_thresholds src_min_lines=0, readme_min_lines=0, + readme_min_fraction=0.0, test_min_lines=0, + test_min_fraction=0.0, doc_min_lines=0, + doc_min_fraction=0.0, )::Nothing # guideline_parameters is for parameters that are passed directly # from run through to the various Guidelines without modification: guideline_parameters = Dict{Symbol, Any}( :src_min_lines => src_min_lines, :readme_min_lines => readme_min_lines, + :readme_min_fraction => readme_min_fraction, :test_min_lines => test_min_lines, + :test_min_fraction => test_min_fraction, :doc_min_lines => doc_min_lines, + :doc_min_fraction => doc_min_fraction, ) all_statuses = deepcopy(additional_statuses) all_check_runs = deepcopy(additional_check_runs) diff --git a/src/AutoMerge/util.jl b/src/AutoMerge/util.jl index 622724e3..1e0d8e5b 100644 --- a/src/AutoMerge/util.jl +++ b/src/AutoMerge/util.jl @@ -293,36 +293,3 @@ function get_all_non_jll_package_names(registry_dir::AbstractString) return packages end - -""" - meets_threshold(threshold, numerator, [denominator]) - -Test the value of `numerator` or `numerator / denominaror` against -some threshold to be satisfed. - -If the value is an integer then it must be greater than or equal to numerator -to satisfy the test. - -If the value is a float, it must be greater than or equal to ``numerator/denominator` -to satisfy the test. -""" -function meets_threshold end - -function meets_threshold(threshold::Integer, linecount::Integer) - @assert threshold >= 0 - # @info("meets_threshold", threshold, linecount, linecount >= threshold) - linecount >= threshold -end - -function meets_threshold(threshold::Integer, numerator::Integer, ::Integer) - @assert threshold >= 0 - # @info("meets_threshold", threshold, numerator, numerator >= threshold) - numerator >= threshold -end - -function meets_threshold(threshold::AbstractFloat, numerator::Integer, denominator::Integer) - @assert threshold >= 0.0 && threshold < 1.0 - # @info("meets_threshold", threshold, numerator, denominator, (numerator / denominator) >= threshold) - (numerator / denominator) >= threshold -end - diff --git a/test/automerge-unit.jl b/test/automerge-unit.jl index 9f0d9f69..0c7f6f73 100644 --- a/test/automerge-unit.jl +++ b/test/automerge-unit.jl @@ -7,6 +7,8 @@ using Printf using RegistryCI using Test using TimeZones +using Base.Iterators: product +using OrderedCollections: OrderedSet const AutoMerge = RegistryCI.AutoMerge @@ -634,21 +636,60 @@ end @testset "AutoMerge.linecounts_meet_thresholds" begin registry = "JuliaRegistries/General" tmp_depot = setup_depot() + # I don't know of a package we can rely on as static. Test + # this package and update the thresholds and issue messages as + # needed. package_name = "RegistryCI" pkg_code_path = pkgdir_from_depot(tmp_depot, package_name) + # The PackageAnalyzer results last measured are + # src: 3412, tests: 1336, docs: 309, readme: 23 guideline_parameters = Dict{Symbol, Any}( - :src_min_lines => 10, - :readme_min_lines => 5, - :test_min_lines => 0.1f0, - :doc_min_lines => 0.1f0, + # Initial setup for all metrrics to pass: + :src_min_lines => 100, + :readme_min_lines => 5, + :test_min_lines => 100, + :doc_min_lines => 200, + :readme_min_fraction => 0.001, + :test_min_fraction => 0.01, + :doc_min_fraction => 0.05, ) @test pkg_code_path isa AbstractString + # Test that all pass + @test AutoMerge.linecounts_meet_thresholds( + pkg_code_path, guideline_parameters) == (true, "") + # test that all fail and verify messages + guideline_parameters = Dict{Symbol, Any}( + :src_min_lines => 10000, + :readme_min_lines => 100, + :test_min_lines => 5000, + :doc_min_lines => 5000, + :readme_min_fraction => 0.8, + :test_min_fraction => 0.8, + :doc_min_fraction => 0.6, + ) result = AutoMerge.linecounts_meet_thresholds( pkg_code_path, guideline_parameters) - @test result == (false, "Too few lines of documentation.") - guideline_parameters[:doc_min_lines] = 0.05f0 - result = AutoMerge.linecounts_meet_thresholds( - pkg_code_path, guideline_parameters) - @test result == (true, "") + @test result[1] == false + let + messages = split(result[2], '\n') + want = [ + "Too few lines of source code", + "Too few lines of README file", + "Too few lines of documentation", + "Too few lines of test code", + "The ratio of README lines to source code is less than required", + "The ratio of documentation lines to documentation plus src lines", + "The ratio of test lines to test plus src lines" + ] + matched = filter(collect(product(messages, want))) do x + startswith(x[1], x[2]) + end + extra_messages = setdiff(OrderedSet(messages), + OrderedSet(map(x -> x[1], matched))) + missing_messages = setdiff(OrderedSet(want), + OrderedSet(map(x -> x[2], matched))) + @test isempty(extra_messages) + @test isempty(missing_messages) + end end end From fc1d378afa67df15dabe9f00856b200b6ccb2179 Mon Sep 17 00:00:00 2001 From: MarkNahabedian Date: Wed, 1 Feb 2023 21:46:36 -0500 Subject: [PATCH 21/27] Can't test guideline_linecounts_meet_thresholds on Julia versions older than 1.6. --- test/automerge-unit.jl | 112 +++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 55 deletions(-) diff --git a/test/automerge-unit.jl b/test/automerge-unit.jl index 0c7f6f73..bc268faf 100644 --- a/test/automerge-unit.jl +++ b/test/automerge-unit.jl @@ -634,62 +634,64 @@ end end @testset "AutoMerge.linecounts_meet_thresholds" begin - registry = "JuliaRegistries/General" - tmp_depot = setup_depot() - # I don't know of a package we can rely on as static. Test - # this package and update the thresholds and issue messages as - # needed. - package_name = "RegistryCI" - pkg_code_path = pkgdir_from_depot(tmp_depot, package_name) - # The PackageAnalyzer results last measured are - # src: 3412, tests: 1336, docs: 309, readme: 23 - guideline_parameters = Dict{Symbol, Any}( - # Initial setup for all metrrics to pass: - :src_min_lines => 100, - :readme_min_lines => 5, - :test_min_lines => 100, - :doc_min_lines => 200, - :readme_min_fraction => 0.001, - :test_min_fraction => 0.01, - :doc_min_fraction => 0.05, - ) - @test pkg_code_path isa AbstractString - # Test that all pass - @test AutoMerge.linecounts_meet_thresholds( - pkg_code_path, guideline_parameters) == (true, "") - # test that all fail and verify messages - guideline_parameters = Dict{Symbol, Any}( - :src_min_lines => 10000, - :readme_min_lines => 100, - :test_min_lines => 5000, - :doc_min_lines => 5000, - :readme_min_fraction => 0.8, - :test_min_fraction => 0.8, - :doc_min_fraction => 0.6, - ) - result = AutoMerge.linecounts_meet_thresholds( - pkg_code_path, guideline_parameters) - @test result[1] == false - let - messages = split(result[2], '\n') - want = [ - "Too few lines of source code", - "Too few lines of README file", - "Too few lines of documentation", - "Too few lines of test code", - "The ratio of README lines to source code is less than required", - "The ratio of documentation lines to documentation plus src lines", - "The ratio of test lines to test plus src lines" - ] - matched = filter(collect(product(messages, want))) do x - startswith(x[1], x[2]) + if VERSION >= v"1.6" + registry = "JuliaRegistries/General" + tmp_depot = setup_depot() + # I don't know of a package we can rely on as static. Test + # this package and update the thresholds and issue messages as + # needed. + package_name = "RegistryCI" + pkg_code_path = pkgdir_from_depot(tmp_depot, package_name) + # The PackageAnalyzer results last measured are + # src: 3412, tests: 1336, docs: 309, readme: 23 + guideline_parameters = Dict{Symbol, Any}( + # Initial setup for all metrrics to pass: + :src_min_lines => 100, + :readme_min_lines => 5, + :test_min_lines => 100, + :doc_min_lines => 200, + :readme_min_fraction => 0.001, + :test_min_fraction => 0.01, + :doc_min_fraction => 0.05, + ) + @test pkg_code_path isa AbstractString + # Test that all pass + @test AutoMerge.linecounts_meet_thresholds( + pkg_code_path, guideline_parameters) == (true, "") + # test that all fail and verify messages + guideline_parameters = Dict{Symbol, Any}( + :src_min_lines => 10000, + :readme_min_lines => 100, + :test_min_lines => 5000, + :doc_min_lines => 5000, + :readme_min_fraction => 0.8, + :test_min_fraction => 0.8, + :doc_min_fraction => 0.6, + ) + result = AutoMerge.linecounts_meet_thresholds( + pkg_code_path, guideline_parameters) + @test result[1] == false + let + messages = split(result[2], '\n') + want = [ + "Too few lines of source code", + "Too few lines of README file", + "Too few lines of documentation", + "Too few lines of test code", + "The ratio of README lines to source code is less than required", + "The ratio of documentation lines to documentation plus src lines", + "The ratio of test lines to test plus src lines" + ] + matched = filter(collect(product(messages, want))) do x + startswith(x[1], x[2]) + end + extra_messages = setdiff(OrderedSet(messages), + OrderedSet(map(x -> x[1], matched))) + missing_messages = setdiff(OrderedSet(want), + OrderedSet(map(x -> x[2], matched))) + @test isempty(extra_messages) + @test isempty(missing_messages) end - extra_messages = setdiff(OrderedSet(messages), - OrderedSet(map(x -> x[1], matched))) - missing_messages = setdiff(OrderedSet(want), - OrderedSet(map(x -> x[2], matched))) - @test isempty(extra_messages) - @test isempty(missing_messages) end end end From 04ef6f3f737d8c1546012d9b8d1a3f773163df30 Mon Sep 17 00:00:00 2001 From: Mark Nahabedian <33787283+MarkNahabedian@users.noreply.github.com> Date: Tue, 11 Apr 2023 17:26:19 -0400 Subject: [PATCH 22/27] Update Project.toml --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 1e8da585..fd43c0b6 100644 --- a/Project.toml +++ b/Project.toml @@ -33,7 +33,7 @@ HTTP = "0.8, 0.9.1, 1" JSON = "0.19, 0.20, 0.21" LicenseCheck = "0.2" PackageAnalyzer = "0.2, 1" -RegistryTools = "1.5.5" +RegistryTools = "2.2" SimpleMock = "1" StringDistances = "0.9, 0.10, 0.11" TOML = "1" From 009fae825671d6a1e16e4c250eba656a30b86590 Mon Sep 17 00:00:00 2001 From: Mark Nahabedian <33787283+MarkNahabedian@users.noreply.github.com> Date: Tue, 18 Apr 2023 15:20:40 -0400 Subject: [PATCH 23/27] Update src/AutoMerge/guidelines.jl documentation of parameters for guideline_linecounts_meet_thresholds. Co-authored-by: Eric Hanson <5846501+ericphanson@users.noreply.github.com> --- src/AutoMerge/guidelines.jl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/AutoMerge/guidelines.jl b/src/AutoMerge/guidelines.jl index fa92777b..fd7ea5f2 100644 --- a/src/AutoMerge/guidelines.jl +++ b/src/AutoMerge/guidelines.jl @@ -872,16 +872,16 @@ end const guideline_linecounts_meet_thresholds = Guideline(; info="Test that lines of source, tests and documentation meet specified thresholds", docs="""Make sure that various line counts meet or exceed specified thresholds. -Thresholds are controlled by these fields of GitHubAutoMergeData: - * src_min_lines: Minimum number of lines of source code - * readme_min_lines: Minimum number of lines in the README file - * test_min_lines: Minimum number of lines of code in the test directory - * doc_min_lines: Minimum number of lines of documentation - * readme_min_fraction minimum ratio of readme lines to src lines - * test_min_fraction minimum ratio of test lines to src lines - * doc_min_fraction minimum ratio of doc to src lines - -For test_min_fraction and doc_min_fraction, the denominator of the fraction + + * `src_min_lines`: Minimum number of lines of source code + * `readme_min_lines`: Minimum number of lines in the README file + * `test_min_lines`: Minimum number of lines of code in the test directory + * `doc_min_lines`: Minimum number of lines of documentation + * `readme_min_fraction`: minimum ratio of readme lines to src lines + * `test_min_fraction`: minimum ratio of test lines to src lines + * `doc_min_fraction`: minimum ratio of doc to src lines + +For `test_min_fraction` and `doc_min_fraction`, the denominator of the fraction also includes the number of lines of test or docs respectively. """, check=(data, guideline_parameters) -> From c8ea113b43046fb0e5671b7c57694c22171df5c2 Mon Sep 17 00:00:00 2001 From: MarkNahabedian Date: Tue, 18 Apr 2023 15:22:01 -0400 Subject: [PATCH 24/27] Update guideline parameter count. --- src/AutoMerge/public.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AutoMerge/public.jl b/src/AutoMerge/public.jl index 57994a26..27b0a420 100644 --- a/src/AutoMerge/public.jl +++ b/src/AutoMerge/public.jl @@ -107,7 +107,7 @@ function run(; public_registries::Vector{<:AbstractString}=String[], read_only::Bool=false, environment_variables_to_pass::Vector{<:AbstractString}=String[], - # Four parameters for guideline_linecounts_meet_thresholds + # Seven parameters for guideline_linecounts_meet_thresholds src_min_lines=0, readme_min_lines=0, readme_min_fraction=0.0, From 5d45493caabfae656e6d025b6750a8ac9e3529cc Mon Sep 17 00:00:00 2001 From: MarkNahabedian Date: Tue, 18 Apr 2023 15:28:29 -0400 Subject: [PATCH 25/27] remove using Logging. --- src/utils.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils.jl b/src/utils.jl index 43ebddd6..450bcf3b 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -1,4 +1,3 @@ -using Logging function with_temp_dir(f::Function) original_working_directory = pwd() From 5f2d56545c08c783f3318816fd144b4a94925f10 Mon Sep 17 00:00:00 2001 From: Mark Nahabedian <33787283+MarkNahabedian@users.noreply.github.com> Date: Tue, 18 Apr 2023 15:36:59 -0400 Subject: [PATCH 26/27] Fix typo. Co-authored-by: Eric Hanson <5846501+ericphanson@users.noreply.github.com> --- test/automerge-unit.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/automerge-unit.jl b/test/automerge-unit.jl index 0d5ae8ae..ed746c46 100644 --- a/test/automerge-unit.jl +++ b/test/automerge-unit.jl @@ -653,7 +653,7 @@ end # The PackageAnalyzer results last measured are # src: 3412, tests: 1336, docs: 309, readme: 23 guideline_parameters = Dict{Symbol, Any}( - # Initial setup for all metrrics to pass: + # Initial setup for all metrics to pass: :src_min_lines => 100, :readme_min_lines => 5, :test_min_lines => 100, From 58eb4be85b7efa5e94f0066b2c8eb0d9be2d6a56 Mon Sep 17 00:00:00 2001 From: MarkNahabedian Date: Wed, 19 Apr 2023 18:15:30 -0400 Subject: [PATCH 27/27] Attempt to accomodate those projects which shoose to put all of their documentation in their README file rather than using conventional Julia documentation. --- src/AutoMerge/guidelines.jl | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/AutoMerge/guidelines.jl b/src/AutoMerge/guidelines.jl index fd7ea5f2..d7fdf1f5 100644 --- a/src/AutoMerge/guidelines.jl +++ b/src/AutoMerge/guidelines.jl @@ -916,8 +916,12 @@ function linecounts_meet_thresholds(pkg_code_path, end check_count("source code", src_line_count, src_min_lines) check_count("README file", readme_line_count, readme_min_lines) - check_count("documentation", docs_line_count, doc_min_lines) check_count("test code", test_line_count, test_min_lines) + # Some projects might put adequate documentation in their README + # file and not have any other documentation. + check_count("documentation", + max(readme_line_count, docs_line_count), + doc_min_lines) function check_fraction(desc, got, want) if got < want push!(issues, @@ -927,12 +931,14 @@ function linecounts_meet_thresholds(pkg_code_path, end check_fraction("README lines to source code", readme_line_count / src_line_count, readme_min_fraction) - check_fraction("documentation lines to documentation plus src lines", - docs_line_count / (docs_line_count + src_line_count), - doc_min_fraction) check_fraction("test lines to test plus src lines", test_line_count / (test_line_count + src_line_count), test_min_fraction) + # See the comment above regarding README vs. docs. + check_fraction("documentation lines to documentation plus src lines", + max(readme_line_count, docs_line_count) / + (docs_line_count + src_line_count), + doc_min_fraction) if isempty(issues) return true, "" else