feat(plugins/lines): add plugin_lines_sections and new features (#1151) [skip ci]
This commit is contained in:
@@ -1,7 +1,18 @@
|
||||
- name: Lines of code changed
|
||||
- name: Compact display in base plugin
|
||||
uses: lowlighter/metrics@latest
|
||||
with:
|
||||
filename: metrics.plugin.lines.svg
|
||||
token: ${{ secrets.METRICS_TOKEN }}
|
||||
base: repositories
|
||||
plugin_lines: yes
|
||||
|
||||
- name: Repositories and diff history
|
||||
uses: lowlighter/metrics@latest
|
||||
with:
|
||||
filename: metrics.plugin.lines.history.svg
|
||||
token: ${{ secrets.METRICS_TOKEN }}
|
||||
base: ""
|
||||
plugin_lines: yes
|
||||
plugin_lines_sections: repositories, history
|
||||
plugin_lines_repositories_limit: 2
|
||||
plugin_lines_history_limit: 1
|
||||
@@ -7,7 +7,7 @@ export default async function({login, data, imports, rest, q, account}, {enabled
|
||||
return null
|
||||
|
||||
//Load inputs
|
||||
let {skipped} = imports.metadata.plugins.lines.inputs({data, account, q})
|
||||
let {skipped, sections, "repositories.limit":_repositories_limit, "history.limit":_history_limit} = imports.metadata.plugins.lines.inputs({data, account, q})
|
||||
skipped.push(...data.shared["repositories.skipped"])
|
||||
|
||||
//Context
|
||||
@@ -22,23 +22,101 @@ export default async function({login, data, imports, rest, q, account}, {enabled
|
||||
|
||||
//Get contributors stats from repositories
|
||||
console.debug(`metrics/compute/${login}/plugins > lines > querying api`)
|
||||
const lines = {added: 0, deleted: 0, changed: 0}
|
||||
const response = [...await Promise.allSettled(repositories.map(({repo, owner}) => (skipped.includes(repo.toLocaleLowerCase())) || (skipped.includes(`${owner}/${repo}`.toLocaleLowerCase())) ? {} : rest.repos.getContributorsStats({owner, repo})))].filter(({status}) => status === "fulfilled").map(({value}) => value)
|
||||
const repos = {}, weeks = {}
|
||||
const response = [...await Promise.allSettled(repositories.map(async ({repo, owner}) => (skipped.includes(repo.toLocaleLowerCase())) || (skipped.includes(`${owner}/${repo}`.toLocaleLowerCase())) ? {} : {handle:`${owner}/${repo}`, stats:(await rest.repos.getContributorsStats({owner, repo})).data}))].filter(({status}) => status === "fulfilled").map(({value}) => value)
|
||||
|
||||
//Compute changed lines
|
||||
console.debug(`metrics/compute/${login}/plugins > lines > computing total diff`)
|
||||
response.map(({data: repository}) => {
|
||||
response.map(({handle, stats}) => {
|
||||
//Check if data are available
|
||||
if (!Array.isArray(repository))
|
||||
if (!Array.isArray(stats))
|
||||
return
|
||||
//Compute editions
|
||||
const contributors = repository.filter(({author}) => context.mode === "repository" ? true : author?.login?.toLocaleLowerCase() === login.toLocaleLowerCase())
|
||||
for (const contributor of contributors)
|
||||
contributor.weeks.forEach(({a = 0, d = 0, c = 0}) => (lines.added += a, lines.deleted += d, lines.changed += c))
|
||||
repos[handle] = {added:0, deleted:0, changed:0}
|
||||
const contributors = stats.filter(({author}) => context.mode === "repository" ? true : author?.login?.toLocaleLowerCase() === login.toLocaleLowerCase())
|
||||
for (const contributor of contributors) {
|
||||
let added = 0, changed = 0, deleted = 0
|
||||
contributor.weeks.forEach(({a = 0, d = 0, c = 0, w}) => {
|
||||
added += a
|
||||
deleted += d
|
||||
changed += c
|
||||
//Compute editions per week
|
||||
const date = new Date(w * 1000).toISOString().substring(0, 10)
|
||||
if (!weeks[date])
|
||||
weeks[date] = {added:0, deleted:0, changed:0}
|
||||
weeks[date].added += a
|
||||
weeks[date].deleted += d
|
||||
weeks[date].changed += c
|
||||
})
|
||||
console.debug(`metrics/compute/${login}/plugins > lines > ${handle}: @${contributor.author.login} +${added} -${deleted} ~${changed}`)
|
||||
repos[handle].added += added
|
||||
repos[handle].deleted += deleted
|
||||
repos[handle].changed += changed
|
||||
}
|
||||
})
|
||||
|
||||
//Results
|
||||
return lines
|
||||
const result = {
|
||||
sections,
|
||||
added: Object.entries(repos).map(([_, {added}]) => added).reduce((a, b) => a + b, 0),
|
||||
deleted: Object.entries(repos).map(([_, {deleted}]) => deleted).reduce((a, b) => a + b, 0),
|
||||
changed: Object.entries(repos).map(([_, {changed}]) => changed).reduce((a, b) => a + b, 0),
|
||||
repos:Object.entries(repos).map(([handle, stats]) => ({handle, ...stats})).sort((a, b) => (b.added + b.deleted + b.changed) - (a.added + a.deleted + a.changed)).slice(0, _repositories_limit),
|
||||
weeks:Object.entries(weeks).map(([date, stats]) => ({date, ...stats})).filter(({added, deleted, changed}) => added + deleted + changed).sort((a, b) => new Date(a.date) - new Date(b.date)),
|
||||
}
|
||||
|
||||
//Diff graphs
|
||||
if (sections.includes("history")) {
|
||||
//Generate SVG
|
||||
const height = 315, width = 480
|
||||
const margin = 5, offset = 34
|
||||
const {d3} = imports
|
||||
const weeks = result.weeks.filter(({date}) => !_history_limit ? true : new Date(date) > new Date(new Date().getFullYear() - _history_limit, 0, 0))
|
||||
const d3n = new imports.D3node()
|
||||
const svg = d3n.createSVG(width, height)
|
||||
|
||||
//Time range
|
||||
const start = new Date(weeks.at(0).date)
|
||||
const end = new Date(weeks.at(-1).date)
|
||||
const x = d3.scaleTime()
|
||||
.domain([start, end])
|
||||
.range([margin+offset, width-(offset+margin)])
|
||||
svg.append("g")
|
||||
.attr("transform", `translate(0,${height-(offset+margin)})`)
|
||||
.call(d3.axisBottom(x))
|
||||
.selectAll("text")
|
||||
.attr("transform", "translate(-5,5) rotate(-45)")
|
||||
.style("text-anchor", "end")
|
||||
.style("font-size", 20)
|
||||
|
||||
//Diff range
|
||||
const points = weeks.flatMap(({added, deleted, changed}) => [added+changed, deleted+changed])
|
||||
const extremum = Math.max(...points)
|
||||
const y = d3.scaleLinear()
|
||||
.domain([extremum, -extremum])
|
||||
.range([margin, height-(offset+margin)])
|
||||
svg.append("g")
|
||||
.attr("transform", `translate(${margin+offset},0)`)
|
||||
.call(d3.axisLeft(y).ticks(7).tickFormat(d3.format(".2s")))
|
||||
.selectAll("text")
|
||||
.style("font-size", 20)
|
||||
|
||||
//Generate history
|
||||
for (const {type, sign, fill} of [{type:"added", sign:+1, fill:"rgb(63, 185, 80)"}, {type:"deleted", sign:-1, fill:"rgb(218, 54, 51)"}]) {
|
||||
svg.append("path")
|
||||
.datum(weeks.map(({date, ...diff}) => [new Date(date), sign*(diff[type]+diff.changed)]))
|
||||
.attr("d", d3.area()
|
||||
.x(d => x(d[0]))
|
||||
.y0(d => y(d[1]))
|
||||
.y1(() => y(0))
|
||||
)
|
||||
.attr("fill", fill)
|
||||
}
|
||||
result.history = d3n.svgString()
|
||||
}
|
||||
|
||||
//Results
|
||||
return result
|
||||
}
|
||||
//Handle errors
|
||||
catch (error) {
|
||||
|
||||
@@ -3,7 +3,8 @@ category: github
|
||||
description: |
|
||||
This plugin displays the number of lines of code added and removed across repositories.
|
||||
examples:
|
||||
default: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.lines.svg
|
||||
+Repositories and diff history: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.lines.history.svg
|
||||
Compact display in base plugin: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.lines.svg
|
||||
index: 18
|
||||
supports:
|
||||
- user
|
||||
@@ -27,3 +28,35 @@ inputs:
|
||||
default: ""
|
||||
example: my-repo-1, my-repo-2, owner/repo-3, ...
|
||||
inherits: repositories_skipped
|
||||
|
||||
plugin_lines_sections:
|
||||
description: |
|
||||
Displayed sections
|
||||
|
||||
- `base` will display the total lines added and removed in `base.repositories` section
|
||||
- `repositories` will display repositories with the most lines added and removed
|
||||
- `history` will display a graph displaying lines added and removed over time
|
||||
type: array
|
||||
format: comma-separated
|
||||
default: base
|
||||
example: repositories, history
|
||||
values:
|
||||
- base
|
||||
- repositories
|
||||
- history
|
||||
|
||||
plugin_lines_repositories_limit:
|
||||
description: |
|
||||
Display limit
|
||||
type: number
|
||||
default: 4
|
||||
min: 0
|
||||
|
||||
plugin_lines_history_limit:
|
||||
description: |
|
||||
Years to display
|
||||
|
||||
Will display the last `n` years, relative to current year
|
||||
type: number
|
||||
default: 1
|
||||
zero: disable
|
||||
Reference in New Issue
Block a user