The great refactor (#82)

This commit is contained in:
Simon Lecoq
2021-01-30 12:31:09 +01:00
committed by GitHub
parent f8c6d19a4e
commit 682e43e10b
158 changed files with 6738 additions and 5022 deletions

View File

@@ -0,0 +1,38 @@
### 💡 Coding habits
The coding *habits* plugin display metrics based on your recent activity, such as active hours or languages recently used.
<table>
<td align="center">
<img src="https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.habits.facts.svg">
<details open><summary>Charts version</summary>
<img src="https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.habits.charts.svg">
</details>
<img width="900" height="1" alt="">
</td>
</table>
Using more events will improve accuracy of these metrics, although it'll increase the number of GitHub requests used.
Active hours and days are computed through your commit history, while indent style is deduced from your recent diffs.
Recent languages activity is also computed from your recent diffs, using [github/linguist](https://github.com/github/linguist).
Use a full `repo` scope token to access **private** events.
By default, dates use Greenwich meridian (GMT/UTC). Be sure to set your timezone (see [here](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) for a list of supported timezones) for accurate metrics.
#### Examples workflows
[➡️ Available options for this plugin](metadata.yml)
```yaml
- uses: lowlighter/metrics@latest
with:
# ... other options
plugin_habits: yes
plugin_habits_from: 200 # Use 200 events to compute habits
plugin_habits_days: 14 # Keep only events from last 14 days
plugin_habits_facts: yes # Display facts section
plugin_habits_charts: yes # Display charts section
config_timezone: Europe/Paris # Set timezone
```

View File

@@ -1,20 +1,19 @@
//Setup
export default async function ({login, rest, imports, data, q, account}, {enabled = false, from:defaults = 100} = {}) {
export default async function ({login, data, rest, imports, q, account}, {enabled = false, ...defaults} = {}) {
//Plugin execution
try {
//Check if plugin is enabled and requirements are met
if ((!enabled)||(!q.habits))
return null
//Parameters override
let {"habits.from":from = defaults.from ?? 500, "habits.days":days = 14, "habits.facts":facts = true, "habits.charts":charts = false} = q
//Events
from = Math.max(1, Math.min(1000, Number(from)))
//Days
days = Math.max(1, Math.min(30, Number(days)))
//Load inputs
let {from, days, facts, charts} = imports.metadata.plugins.habits.inputs({data, account, q}, defaults)
//Initialization
const habits = {facts, charts, commits:{hour:NaN, hours:{}, day:NaN, days:{}}, indents:{style:"", spaces:0, tabs:0}, linguist:{available:false, ordered:[], languages:{}}}
const pages = Math.ceil(from/100)
const offset = data.config.timezone?.offset ?? 0
//Get user recent activity
console.debug(`metrics/compute/${login}/plugins > habits > querying api`)
const events = []
@@ -25,12 +24,14 @@
}
} catch { console.debug(`metrics/compute/${login}/plugins > habits > no more page to load`) }
console.debug(`metrics/compute/${login}/plugins > habits > ${events.length} events loaded`)
//Get user recent commits
const commits = events
.filter(({type}) => type === "PushEvent")
.filter(({actor}) => account === "organization" ? true : actor.login === login)
.filter(({created_at}) => new Date(created_at) > new Date(Date.now()-days*24*60*60*1000))
console.debug(`metrics/compute/${login}/plugins > habits > filtered out ${commits.length} push events over last ${days} days`)
//Retrieve edited files and filter edited lines (those starting with +/-) from patches
console.debug(`metrics/compute/${login}/plugins > habits > loading patches`)
const patches = [...await Promise.allSettled(commits
@@ -41,6 +42,7 @@
.map(({value}) => value)
.flatMap(files => files.map(file => ({name:imports.paths.basename(file.filename), patch:file.patch ?? ""})))
.map(({name, patch}) => ({name, patch:patch.split("\n").filter(line => /^[-+]/.test(line)).map(line => line.substring(1)).join("\n")}))
//Commit day
{
//Compute commit days
@@ -52,6 +54,7 @@
//Compute day with most commits
habits.commits.day = days.length ? ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][Object.entries(habits.commits.days).sort(([an, a], [bn, b]) => b - a).map(([day, occurence]) => day)[0]] ?? NaN : NaN
}
//Commit hour
{
//Compute commit hours
@@ -63,6 +66,7 @@
//Compute hour with most commits
habits.commits.hour = hours.length ? `${Object.entries(habits.commits.hours).sort(([an, a], [bn, b]) => b - a).map(([hour, occurence]) => hour)[0]}`.padStart(2, "0") : NaN
}
//Indent style
{
//Attempt to guess whether tabs or spaces are used in patches
@@ -72,6 +76,7 @@
.forEach(indent => habits.indents[/^\t/.test(indent) ? "tabs" : "spaces"]++)
habits.indents.style = habits.indents.spaces > habits.indents.tabs ? "spaces" : habits.indents.tabs > habits.indents.spaces ? "tabs" : ""
}
//Linguist
if (charts) {
//Check if linguist exists
@@ -87,7 +92,7 @@
await Promise.all(patches.map(async ({name, patch}, i) => await imports.fs.writeFile(imports.paths.join(path, `${i}${imports.paths.extname(name)}`), patch)))
//Create temporary git repository
console.debug(`metrics/compute/${login}/plugins > habits > creating temp git repository`)
await imports.run(`git init && git add . && git config user.name "linguist" && git config user.email "null@github.com" && git commit -m "linguist"`, {cwd:path}).catch(console.debug)
await imports.run(`git init && git add . && git config user.name "linguist" && git config user.email "<>" && git commit -m "linguist"`, {cwd:path}).catch(console.debug)
await imports.run(`git status`, {cwd:path})
//Spawn linguist process
console.debug(`metrics/compute/${login}/plugins > habits > running linguist`)
@@ -100,6 +105,7 @@
else
console.debug(`metrics/compute/${login}/plugins > habits > linguist not available`)
}
//Results
return habits
}

View File

@@ -0,0 +1,43 @@
name: "💡 Coding habits"
cost: 1 REST request per 100 events + 1 REST request pet commit
supports:
- user
- organization
inputs:
# Enable or disable plugin
plugin_habits:
description: Display coding habits metrics
type: boolean
default: no
# Number of events to use to computes habits
# Using more will result in more accurate metrics, but you may hit GitHub rate-limit more easily
plugin_habits_from:
description: Number of events to use
type: number
default: 200
min: 1
max: 1000
# Filter used events to compute habits by age
plugin_habits_days:
description: Maximum event age
type: number
default: 14
min: 1
max: 30
# Display tidbits about your most active hours/days, indents used (spaces/tabs), etc.
# This is deduced from your recent activity
plugin_habits_facts:
description: Display coding habits collected facts based on recent activity
type: boolean
default: yes
# Display charts of most active time of the day and most active day of the week
# Also display languages recently used (this is not the same as plugin_languages, as the latter is an all-time stats)
plugin_habits_charts:
description: Display coding habits charts based on recent activity
type: boolean
default: no