summaryrefslogtreecommitdiff
path: root/Biz/Devalloc.hs
diff options
context:
space:
mode:
authorBen Sima <ben@bsima.me>2021-03-30 16:05:41 -0400
committerBen Sima <ben@bsima.me>2021-03-30 16:05:41 -0400
commit2444dbaa079902f243744c0861d33cab9d1e5c4f (patch)
treee19387dc8c8d1f11db0a624d145a0f826ed8415e /Biz/Devalloc.hs
parentdb196536453668d2b07bb1456ebe842b3059fa4f (diff)
Move Analysis class instances near type definition
Diffstat (limited to 'Biz/Devalloc.hs')
-rw-r--r--Biz/Devalloc.hs428
1 files changed, 214 insertions, 214 deletions
diff --git a/Biz/Devalloc.hs b/Biz/Devalloc.hs
index b58068c..7112020 100644
--- a/Biz/Devalloc.hs
+++ b/Biz/Devalloc.hs
@@ -348,6 +348,220 @@ instance Indexable Analysis where
ixFun <| \Analysis {..} -> [repoVisibility]
]
+instance App.HasCss Analysis where
+ cssFor _ = do
+ "#analysis > *" ? do
+ Biz.Look.marginAll (rem 2)
+ ".score" ? do
+ Clay.display Clay.grid
+ Biz.Look.gridTemplateAreas
+ [ "title quantity details-collapsed",
+ "preview-chart preview-chart preview-chart",
+ "details details details"
+ ]
+ Clay.alignItems Clay.baseline
+ Clay.gridTemplateColumns [pct 30, 40, 30]
+ Biz.Look.gridTemplateRows ["auto"]
+ ".title" ? do
+ Biz.Look.gridArea "title"
+ Clay.fontSize (rem 1.4)
+ Clay.lineHeight (rem 2.4)
+ ".percentage" ? do
+ Biz.Look.gridArea "quantity"
+ Clay.display Clay.flex
+ Clay.alignItems Clay.baseline
+ ".centum" ? do
+ Clay.fontSize (rem 1.2)
+ Clay.lineHeight (rem 1.2)
+ ".quantity" ? do
+ Biz.Look.gridArea "quantity"
+ Clay.fontSize (rem 3)
+ Clay.lineHeight (rem 3)
+ ".preview-chart" ? do
+ Biz.Look.gridArea "preview-chart"
+ "details" ? do
+ Biz.Look.gridArea "details-collapsed"
+ Biz.Look.justifySelf <| Clay.JustifyContentValue "self-end"
+ "details[open]" ? do
+ Biz.Look.gridArea "details"
+ Biz.Look.justifySelf <| Clay.JustifyContentValue "auto"
+ ".preview-chart" ? do
+ Clay.height (px 2)
+ Clay.maxWidth (pct 100)
+ "table" ? do
+ Biz.Look.marginAll (px 0)
+ Clay.maxWidth (pct 100)
+ "#hotspots" ? do
+ ".preview-chart" ? do
+ Clay.height (rem 1)
+ "table" ? do
+ Clay.height (rem 4)
+ Clay.marginTop (rem (-3))
+ Clay.zIndex (-1)
+ ".bar" ? do
+ Clay.height (px 800)
+
+instance Lucid.ToHtml Analysis where
+ toHtmlRaw = Lucid.toHtml
+ toHtml Analysis {..} =
+ Lucid.div_ [Lucid.id_ "analysis"] <| do
+ Lucid.p_ [Lucid.class_ "analysisFor"] <| do
+ "Analysis for "
+ Lucid.a_ [Lucid.href_ <| (\(URL txt) -> txt) <| url] <| do
+ Lucid.toHtml url
+
+ score_ <| do
+ title_ "Total Score"
+ percentage_ <| do
+ 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"
+ quantity_ <| Lucid.toHtml <| tshow totalFiles
+
+ score_ <| do
+ title_ "Active authors"
+ quantity_ <| Lucid.toHtml <| slen activeAuthors
+ Lucid.details_ <| do
+ Lucid.summary_ "Details"
+ Lucid.ul_ <| forM_ activeAuthors <| \author -> do
+ Lucid.li_ <| Lucid.toHtml author
+
+ score_ <| do
+ title_ "Blackholes"
+ quantity_ <| Lucid.toHtml <| slen blackholes
+ 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
+
+ score_ <| do
+ title_ "Liabilities"
+ quantity_ <| Lucid.toHtml <| slen liabilities
+ 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
+
+ score_ <| do
+ title_ "Stale files"
+ quantity_ <| Lucid.toHtml <| slen stale
+ 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)"
+
+ Lucid.with score_ [Lucid.id_ "hotspots"] <| do
+ title_ "Hotspots"
+ quantity_ "" -- TODO
+ previewChart <| do
+ Lucid.table_ [Lucid.class_ "charts-css column"] <| do
+ Lucid.tr_ <| do
+ forM_ (Map.toList hotspotMap) <| \(_, n) -> do
+ 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
+ Lucid.td_ [Lucid.style_ <| size n totalCommits] <| do
+ Lucid.span_ [Lucid.class_ "tooltip"]
+ <| Lucid.toHtml
+ <| path <> ": " <> show n <> " commits"
+ where
+ simpleBar :: Monad m => Integer -> Integer -> Lucid.HtmlT m ()
+ simpleBar n total = do
+ Lucid.table_ [Lucid.class_ "charts-css bar stacked multiple"] <| do
+ Lucid.tr_ <| do
+ Lucid.td_ [Lucid.style_ <| size n total] ""
+ <> Lucid.td_ [Lucid.style_ <| size total total] ""
+
+ len = toInteger <. length
+ slen = tshow <. length
+ div_ c = Lucid.with Lucid.div_ [Lucid.class_ c]
+ score_ = div_ "score"
+ title_ = div_ "title"
+ quantity_ = div_ "quantity"
+ centum_ = div_ "centum"
+ 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 []
+
-- | The database.
data Keep = Keep
{ users :: IxSet User,
@@ -1411,220 +1625,6 @@ instance Lucid.ToHtml AnalysisDisplay where
Lucid.toHtml anal
footer
-instance App.HasCss Analysis where
- cssFor _ = do
- "#analysis > *" ? do
- Biz.Look.marginAll (rem 2)
- ".score" ? do
- Clay.display Clay.grid
- Biz.Look.gridTemplateAreas
- [ "title quantity details-collapsed",
- "preview-chart preview-chart preview-chart",
- "details details details"
- ]
- Clay.alignItems Clay.baseline
- Clay.gridTemplateColumns [pct 30, 40, 30]
- Biz.Look.gridTemplateRows ["auto"]
- ".title" ? do
- Biz.Look.gridArea "title"
- Clay.fontSize (rem 1.4)
- Clay.lineHeight (rem 2.4)
- ".percentage" ? do
- Biz.Look.gridArea "quantity"
- Clay.display Clay.flex
- Clay.alignItems Clay.baseline
- ".centum" ? do
- Clay.fontSize (rem 1.2)
- Clay.lineHeight (rem 1.2)
- ".quantity" ? do
- Biz.Look.gridArea "quantity"
- Clay.fontSize (rem 3)
- Clay.lineHeight (rem 3)
- ".preview-chart" ? do
- Biz.Look.gridArea "preview-chart"
- "details" ? do
- Biz.Look.gridArea "details-collapsed"
- Biz.Look.justifySelf <| Clay.JustifyContentValue "self-end"
- "details[open]" ? do
- Biz.Look.gridArea "details"
- Biz.Look.justifySelf <| Clay.JustifyContentValue "auto"
- ".preview-chart" ? do
- Clay.height (px 2)
- Clay.maxWidth (pct 100)
- "table" ? do
- Biz.Look.marginAll (px 0)
- Clay.maxWidth (pct 100)
- "#hotspots" ? do
- ".preview-chart" ? do
- Clay.height (rem 1)
- "table" ? do
- Clay.height (rem 4)
- Clay.marginTop (rem (-3))
- Clay.zIndex (-1)
- ".bar" ? do
- Clay.height (px 800)
-
-instance Lucid.ToHtml Analysis where
- toHtmlRaw = Lucid.toHtml
- toHtml Analysis {..} =
- Lucid.div_ [Lucid.id_ "analysis"] <| do
- Lucid.p_ [Lucid.class_ "analysisFor"] <| do
- "Analysis for "
- Lucid.a_ [Lucid.href_ <| (\(URL txt) -> txt) <| url] <| do
- Lucid.toHtml url
-
- score_ <| do
- title_ "Total Score"
- percentage_ <| do
- 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"
- quantity_ <| Lucid.toHtml <| tshow totalFiles
-
- score_ <| do
- title_ "Active authors"
- quantity_ <| Lucid.toHtml <| slen activeAuthors
- Lucid.details_ <| do
- Lucid.summary_ "Details"
- Lucid.ul_ <| forM_ activeAuthors <| \author -> do
- Lucid.li_ <| Lucid.toHtml author
-
- score_ <| do
- title_ "Blackholes"
- quantity_ <| Lucid.toHtml <| slen blackholes
- 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
-
- score_ <| do
- title_ "Liabilities"
- quantity_ <| Lucid.toHtml <| slen liabilities
- 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
-
- score_ <| do
- title_ "Stale files"
- quantity_ <| Lucid.toHtml <| slen stale
- 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)"
-
- Lucid.with score_ [Lucid.id_ "hotspots"] <| do
- title_ "Hotspots"
- quantity_ "" -- TODO
- previewChart <| do
- Lucid.table_ [Lucid.class_ "charts-css column"] <| do
- Lucid.tr_ <| do
- forM_ (Map.toList hotspotMap) <| \(_, n) -> do
- 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
- Lucid.td_ [Lucid.style_ <| size n totalCommits] <| do
- Lucid.span_ [Lucid.class_ "tooltip"]
- <| Lucid.toHtml
- <| path <> ": " <> show n <> " commits"
- where
- simpleBar :: Monad m => Integer -> Integer -> Lucid.HtmlT m ()
- simpleBar n total = do
- Lucid.table_ [Lucid.class_ "charts-css bar stacked multiple"] <| do
- Lucid.tr_ <| do
- Lucid.td_ [Lucid.style_ <| size n total] ""
- <> Lucid.td_ [Lucid.style_ <| size total total] ""
-
- len = toInteger <. length
- slen = tshow <. length
- div_ c = Lucid.with Lucid.div_ [Lucid.class_ c]
- score_ = div_ "score"
- title_ = div_ "title"
- quantity_ = div_ "quantity"
- centum_ = div_ "centum"
- 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
analyze keep askedBy activeAuthors url bareRepo repoPrivate = do