summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Biz/Bild/Deps/Haskell.nix1
-rw-r--r--Biz/Devalloc.hs75
2 files changed, 74 insertions, 2 deletions
diff --git a/Biz/Bild/Deps/Haskell.nix b/Biz/Bild/Deps/Haskell.nix
index 4434cb3..4fd2d85 100644
--- a/Biz/Bild/Deps/Haskell.nix
+++ b/Biz/Bild/Deps/Haskell.nix
@@ -33,6 +33,7 @@ with hpkgs;
monad-logger
monad-metrics
mtl
+ neat-interpolation
network-uri
optparse-simple
parsec
diff --git a/Biz/Devalloc.hs b/Biz/Devalloc.hs
index 0f6bf94..4e2efdb 100644
--- a/Biz/Devalloc.hs
+++ b/Biz/Devalloc.hs
@@ -34,6 +34,7 @@
-- : dep http-api-data
-- : dep ixset
-- : dep lucid
+-- : dep neat-interpolation
-- : dep protolude
-- : dep rainbow
-- : dep req
@@ -101,6 +102,7 @@ import qualified GitHub
import qualified Lucid
import qualified Lucid.Base as Lucid
import qualified Lucid.Servant as Lucid
+import NeatInterpolation
import Network.HTTP.Req ((/:), (=:))
import qualified Network.HTTP.Req as Req
import qualified Network.Wai as Wai
@@ -1073,10 +1075,10 @@ instance Lucid.ToHtml Home where
\ This happens too often with legacy code, and then it turns into a huge source of tech debt. \
\ Devalloc finds these \"blackholes\" and warns you about them so you can be proactive in eliminating tech debt."
section <| do
- h2 "Find developer hot spots"
+ h2 "Find developer hotspots"
p
"Which pieces of code get continually rewritten, taking up valuable dev time? \
- \ Find these module hot spots before they become a costly time-sink."
+ \ Find these module hotspots before they become a costly time-sink."
section <| do
h2 "See an example analysis"
maybe
@@ -1411,6 +1413,20 @@ instance Lucid.ToHtml Analysis where
quantity_ <| Lucid.toHtml <| tshow score
centum_ "/100"
previewChart <| simpleBar score 100
+ Lucid.details_ <| do
+ Lucid.summary_ "Details"
+ desc
+ [text|
+ Your score is a weighted composite of the below metrics.
+ What your score means:
+ - 0-30: very high risk, most of your codebase is unknown or ephemeral
+ - 30-60: medium-high risk, tasks that involve working on this
+ codebase will take longer than they should, and we should expect
+ a few unforeseen bugs
+ - 60-80: medium-low risk, tasks in this codebase can be expected to
+ complete in the estimated time, and it probably doesn't have many bugs
+ - 80+: low risk, your codebase is super clean, give your devs a raise
+ |]
score_ <| do
title_ "Total Files"
@@ -1430,6 +1446,19 @@ instance Lucid.ToHtml Analysis where
previewChart <| simpleBar (len blackholes) totalFiles
Lucid.details_ <| do
Lucid.summary_ "Details"
+ desc
+ [text|
+ A blackhole has zero active contributors, so none of your current team
+ members have touched this code. These are very high risk. If there is
+ a problem with this area of the codebase, it will take longer for your
+ team to diagnose and fix the root cause; new features that interact
+ with a blackhole will take longer to deploy.
+
+ **What you can do:** Start a project to ensure these blackholes are
+ well-defined and documented. If anything is completely unknown, write
+ tests against that part of the code as it currently stands, then decide
+ if a rewrite is necessary.
+ |]
Lucid.ul_ <| do
traverse_ (Lucid.toHtml .> Lucid.li_) blackholes
@@ -1439,6 +1468,20 @@ instance Lucid.ToHtml Analysis where
previewChart <| simpleBar (len liabilities) totalFiles
Lucid.details_ <| do
Lucid.summary_ "Details"
+ desc
+ [text|
+ Files with < 3 active contributors. These are at risk of becoming
+ blackholes if contributors change teams or leave the company.
+
+ **What you can do:** Next time a task involves one of these files,
+ pull in some team members that haven't worked on this area of the
+ codebase.
+
+ In general, when assigning tasks, ensure developers are occasionally
+ working on areas of the codebase that are new to them. Not only will
+ this decrease your liability, it will also improve your developers
+ by helping them learn new areas of the code and share techniques.
+ |]
Lucid.ul_ <| do
traverse_ (Lucid.toHtml .> Lucid.li_) liabilities
@@ -1448,6 +1491,18 @@ instance Lucid.ToHtml Analysis where
previewChart <| simpleBar (len stale) totalFiles
Lucid.details_ <| do
Lucid.summary_ "Details"
+ desc
+ [text|
+ Files that haven't been touched in 6 months. These aren't necessarily
+ a risk: unchanging files could just be really well-defined and stable.
+ On the other hand, they could also be places that nobody wants to go
+ because nobody knows how they work.
+
+ **What you can do:** Run this list by your team and find out who has
+ knowledge of this area. If nobody does, start a project to
+ investigate and re-define this part of the codebase, ensuring good
+ documentation practices along the way.
+ |]
Lucid.ul_ <| do
forM_ stale <| \(path, days) ->
Lucid.li_ <| Lucid.toHtml <| path <> " (" <> show days <> " days)"
@@ -1462,6 +1517,20 @@ instance Lucid.ToHtml Analysis where
Lucid.td_ [Lucid.style_ <| size n totalCommits] ""
Lucid.details_ <| do
Lucid.summary_ "Details"
+ desc
+ [text|
+ A hotspot is an over-active code module: developers are continually
+ reworking this part of the code, wasting time redoing work instead
+ of progressing.
+ The flamegraph below plots files by how often they are changed, a
+ longer horizontal line means more changes. Hover over the bars to
+ see filenames and change count.
+
+ **What you can do:** After identifying the hotspots, discuss with your
+ team how to improve the code. Why does the code change so often? Does
+ it need a more well-defined spec? Does it need a deep refactor? Maybe
+ part of it can be abstracted into a more solid module?
+ |]
Lucid.table_ [Lucid.class_ "charts-css bar"] <| do
Lucid.tr_ <| do
forM_ (Map.toList hotspotMap) <| \(path, n) -> do
@@ -1487,6 +1556,8 @@ instance Lucid.ToHtml Analysis where
percentage_ = div_ "percentage"
size n total = "--size: calc(" <> show n <> "/" <> show total <> ")"
previewChart = div_ "preview-chart"
+ desc :: Monad m => Text -> Lucid.HtmlT m ()
+ desc = Lucid.p_ <. Cmark.renderNode [] <. Cmark.commonmarkToNode []
-- | Run a full analysis on a git repo
analyze :: Acid.AcidState Keep -> Id.Id User -> [Text] -> URL -> FilePath -> Bool -> IO Analysis