Analyzer takes in a valid repo URL and coordinates the analysis, returning a simple JSON report. The URL can be one of "https", "http", or "file". Note, that the latter scheme will only work an existing clone and won't remove the directory structure upon completion of analysis.
Summary
Functions
analyze/3: returns the LowEndInsight report as JSON for multiple_repos. Takes in a "list" of urls, a source id for the calling client, and the start_time of analysis as an optional way to capture the time actually started at whatever the client is (e.g. an async API).
create_empty_report/3: takes in a uuid, list of urls, and a start time and produces the repo report object to be returned immediately by asynchronous requestors (e.g. LowEndInsight-Get HTTP endpoint)
determine_risk_counts/1: takes in a full report of n-repo reports, and calculates the number or risk ratings, given the number of repos. It returns a new report with the risk_counts object populated with the count table. Have to accommodate both the atom and string elements, because the JSON gets parsed into the string format - so caching can be supported (as reports are stored in JSON).
determine_toplevel_risk/1: takes in a report and determines the highest criticality, and assigns it to the "risk" element for the repo report.
Whether a report is an analysis, or a record of one that could not be performed.
Functions
@spec analyze(binary() | maybe_improper_list(), any(), any()) :: {:ok, map()}
analyze/3: returns the LowEndInsight report as JSON for multiple_repos. Takes in a "list" of urls, a source id for the calling client, and the start_time of analysis as an optional way to capture the time actually started at whatever the client is (e.g. an async API).
Returns Map.
Examples
iex> {:ok, report} = AnalyzerModule.analyze(["https://github.com/kitplummer/xmpp4rails","https://github.com/kitplummer/lita-cron"], "iex")
iex> _count = report[:metadata][:repo_count]
2
create_empty_report/3: takes in a uuid, list of urls, and a start time and produces the repo report object to be returned immediately by asynchronous requestors (e.g. LowEndInsight-Get HTTP endpoint)
@spec determine_risk_counts(RepoReport.t()) :: map()
determine_risk_counts/1: takes in a full report of n-repo reports, and calculates the number or risk ratings, given the number of repos. It returns a new report with the risk_counts object populated with the count table. Have to accommodate both the atom and string elements, because the JSON gets parsed into the string format - so caching can be supported (as reports are stored in JSON).
@spec determine_toplevel_risk(RepoReport.t()) :: map()
determine_toplevel_risk/1: takes in a report and determines the highest criticality, and assigns it to the "risk" element for the repo report.
Whether a report is an analysis, or a record of one that could not be performed.
analyze/3 rescues a failed clone and returns {:ok, report} carrying
risk: "undetermined" and the reason in data.error. The rescue is right --
one unreachable repository must not fail a batch of two hundred -- but the
result is shaped exactly like a success, so every caller matching {:ok, _}
proceeds as though an analysis happened. This is how they are told apart
(#255).
Decided by the presence of data.error, which is set on exactly those
rescue paths, rather than by risk == "undetermined", which other code also
produces as a default for a missing value.
Anything that does not positively look like a report is not determined. Absence of an error is not evidence of an analysis, and defaulting the other way would let a malformed or empty value through as a real result.