Add support for lines and traffic plugins
This commit is contained in:
34
README.md
34
README.md
@@ -64,6 +64,10 @@ jobs:
|
|||||||
token: ${{ secrets.METRICS_TOKEN }}
|
token: ${{ secrets.METRICS_TOKEN }}
|
||||||
# Your GitHub user name
|
# Your GitHub user name
|
||||||
user: my-github-user
|
user: my-github-user
|
||||||
|
# If you own a website and you added it to your GitHub profile,
|
||||||
|
# You can provide a PageSpeed token to add your site's performance results on the metrics SVG image
|
||||||
|
# See https://developers.google.com/speed/docs/insights/v5/get-started to obtain a key
|
||||||
|
# pagespeed_token: ${{ secrets.PAGESPEED_TOKEN }}
|
||||||
```
|
```
|
||||||
|
|
||||||
On each run, a new SVG image will be generated and committed to your repository.
|
On each run, a new SVG image will be generated and committed to your repository.
|
||||||
@@ -99,6 +103,7 @@ Since GitHub API has rate limitations and to avoid abuse, the shared instance ha
|
|||||||
* Images are cached for 1 day (meaning that your metrics won't be updated until the next day)
|
* Images are cached for 1 day (meaning that your metrics won't be updated until the next day)
|
||||||
* A maximum of 1000 users can use this service
|
* A maximum of 1000 users can use this service
|
||||||
* You're limited to 3 requests per hour (cached metrics are not counted)
|
* You're limited to 3 requests per hour (cached metrics are not counted)
|
||||||
|
* Plugins are not available
|
||||||
|
|
||||||
You should consider deploying your own instance or use GitHub Action if you're planning using this service.
|
You should consider deploying your own instance or use GitHub Action if you're planning using this service.
|
||||||
|
|
||||||
@@ -197,6 +202,34 @@ Open and edit `settings.json` to configure your instance.
|
|||||||
//This is intendend for easier development which allows to see your changes quickly
|
//This is intendend for easier development which allows to see your changes quickly
|
||||||
//Defaults to false
|
//Defaults to false
|
||||||
"debug":false,
|
"debug":false,
|
||||||
|
|
||||||
|
//Plugins configuration
|
||||||
|
//Most of plugins are disabled by default
|
||||||
|
//Enabling them can add additional informations and metrics about you, but increases response time
|
||||||
|
"plugins":{
|
||||||
|
//Pagespeed plugin
|
||||||
|
"pagespeed":{
|
||||||
|
//Enable or disable this plugin
|
||||||
|
//When enabled, pass "?pagespeed=1" in url to generate website's performances
|
||||||
|
"enabled":false,
|
||||||
|
//Pagespeed token
|
||||||
|
//See https://developers.google.com/speed/docs/insights/v5/get-started to obtain a key
|
||||||
|
"token":"****************************************"
|
||||||
|
},
|
||||||
|
//Lines plugin
|
||||||
|
"lines":{
|
||||||
|
//Enable or disable this plugin
|
||||||
|
//When enabled, pass "?lines=1" in url to compute total lines added/removed in your repositories by you
|
||||||
|
"enabled":true
|
||||||
|
},
|
||||||
|
//Traffic plugin
|
||||||
|
"traffic":{
|
||||||
|
//Enable or disable this plugin
|
||||||
|
//When enabled, pass "?traffic=1" in url to compute total page views in your repositories in last two weeks
|
||||||
|
//Note that this requires that the passed GitHub API token requires a push access
|
||||||
|
"enabled":true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -289,6 +322,7 @@ Below is a list of useful documentations links :
|
|||||||
|
|
||||||
* [GitHub GraphQL API](https://docs.github.com/en/graphql)
|
* [GitHub GraphQL API](https://docs.github.com/en/graphql)
|
||||||
* [GitHub GraphQL Explorer](https://developer.github.com/v4/explorer/)
|
* [GitHub GraphQL Explorer](https://developer.github.com/v4/explorer/)
|
||||||
|
* [GitHub Rest API](https://docs.github.com/en/rest)
|
||||||
|
|
||||||
## 📦 Used packages
|
## 📦 Used packages
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,10 @@ inputs:
|
|||||||
description: Name of SVG image output
|
description: Name of SVG image output
|
||||||
default: github-metrics.svg
|
default: github-metrics.svg
|
||||||
pagespeed_token:
|
pagespeed_token:
|
||||||
description: Pagespeed Personal Token (optional, will generate user's website performances if provided). See https://developers.google.com/speed/docs/insights/v5/get-started for more information.
|
description: Pagespeed Personal Token (optional, see https://developers.google.com/speed/docs/insights/v5/get-started for more information)
|
||||||
|
plugins:
|
||||||
|
description: List of additional plugins to enabled. Supported values are "lines", "pagespeed" (requires "pagespeed_token") and "traffic" (require "token" with "repository" permissions)
|
||||||
|
default: []
|
||||||
runs:
|
runs:
|
||||||
using: node12
|
using: node12
|
||||||
main: action/dist/index.js
|
main: action/dist/index.js
|
||||||
122
action/dist/index.js
vendored
122
action/dist/index.js
vendored
@@ -142,6 +142,12 @@ __webpack_require__.r(__webpack_exports__);
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M8.878.392a1.75 1.75 0 00-1.756 0l-5.25 3.045A1.75 1.75 0 001 4.951v6.098c0 .624.332 1.2.872 1.514l5.25 3.045a1.75 1.75 0 001.756 0l5.25-3.045c.54-.313.872-.89.872-1.514V4.951c0-.624-.332-1.2-.872-1.514L8.878.392zM7.875 1.69a.25.25 0 01.25 0l4.63 2.685L8 7.133 3.245 4.375l4.63-2.685zM2.5 5.677v5.372c0 .09.047.171.125.216l4.625 2.683V8.432L2.5 5.677zm6.25 8.271l4.625-2.683a.25.25 0 00.125-.216V5.677L8.75 8.432v5.516z"></path></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M8.878.392a1.75 1.75 0 00-1.756 0l-5.25 3.045A1.75 1.75 0 001 4.951v6.098c0 .624.332 1.2.872 1.514l5.25 3.045a1.75 1.75 0 001.756 0l5.25-3.045c.54-.313.872-.89.872-1.514V4.951c0-.624-.332-1.2-.872-1.514L8.878.392zM7.875 1.69a.25.25 0 01.25 0l4.63 2.685L8 7.133 3.245 4.375l4.63-2.685zM2.5 5.677v5.372c0 .09.047.171.125.216l4.625 2.683V8.432L2.5 5.677zm6.25 8.271l4.625-2.683a.25.25 0 00.125-.216V5.677L8.75 8.432v5.516z"></path></svg>
|
||||||
\${data.user.packages.totalCount} Package\${data.user.packages.totalCount > 1 ? "s" : ""}
|
\${data.user.packages.totalCount} Package\${data.user.packages.totalCount > 1 ? "s" : ""}
|
||||||
</div>
|
</div>
|
||||||
|
\${computed.plugins.lines ? \`
|
||||||
|
<div class="field">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M4.72 3.22a.75.75 0 011.06 1.06L2.06 8l3.72 3.72a.75.75 0 11-1.06 1.06L.47 8.53a.75.75 0 010-1.06l4.25-4.25zm6.56 0a.75.75 0 10-1.06 1.06L13.94 8l-3.72 3.72a.75.75 0 101.06 1.06l4.25-4.25a.75.75 0 000-1.06l-4.25-4.25z"></path></svg>
|
||||||
|
\${computed.plugins.lines.added} added, \${computed.plugins.lines.deleted} removed
|
||||||
|
</div>\` : ""
|
||||||
|
}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
@@ -153,6 +159,12 @@ __webpack_require__.r(__webpack_exports__);
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M1.679 7.932c.412-.621 1.242-1.75 2.366-2.717C5.175 4.242 6.527 3.5 8 3.5c1.473 0 2.824.742 3.955 1.715 1.124.967 1.954 2.096 2.366 2.717a.119.119 0 010 .136c-.412.621-1.242 1.75-2.366 2.717C10.825 11.758 9.473 12.5 8 12.5c-1.473 0-2.824-.742-3.955-1.715C2.92 9.818 2.09 8.69 1.679 8.068a.119.119 0 010-.136zM8 2c-1.981 0-3.67.992-4.933 2.078C1.797 5.169.88 6.423.43 7.1a1.619 1.619 0 000 1.798c.45.678 1.367 1.932 2.637 3.024C4.329 13.008 6.019 14 8 14c1.981 0 3.67-.992 4.933-2.078 1.27-1.091 2.187-2.345 2.637-3.023a1.619 1.619 0 000-1.798c-.45-.678-1.367-1.932-2.637-3.023C11.671 2.992 9.981 2 8 2zm0 8a2 2 0 100-4 2 2 0 000 4z"></path></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M1.679 7.932c.412-.621 1.242-1.75 2.366-2.717C5.175 4.242 6.527 3.5 8 3.5c1.473 0 2.824.742 3.955 1.715 1.124.967 1.954 2.096 2.366 2.717a.119.119 0 010 .136c-.412.621-1.242 1.75-2.366 2.717C10.825 11.758 9.473 12.5 8 12.5c-1.473 0-2.824-.742-3.955-1.715C2.92 9.818 2.09 8.69 1.679 8.068a.119.119 0 010-.136zM8 2c-1.981 0-3.67.992-4.933 2.078C1.797 5.169.88 6.423.43 7.1a1.619 1.619 0 000 1.798c.45.678 1.367 1.932 2.637 3.024C4.329 13.008 6.019 14 8 14c1.981 0 3.67-.992 4.933-2.078 1.27-1.091 2.187-2.345 2.637-3.023a1.619 1.619 0 000-1.798c-.45-.678-1.367-1.932-2.637-3.023C11.671 2.992 9.981 2 8 2zm0 8a2 2 0 100-4 2 2 0 000 4z"></path></svg>
|
||||||
\${data.computed.repositories.watchers} Watcher\${data.computed.repositories.watchers > 1 ? "s" : ""}
|
\${data.computed.repositories.watchers} Watcher\${data.computed.repositories.watchers > 1 ? "s" : ""}
|
||||||
</div>
|
</div>
|
||||||
|
\${computed.plugins.traffic ? \`
|
||||||
|
<div class="field">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M0 1.75A.75.75 0 01.75 1h4.253c1.227 0 2.317.59 3 1.501A3.744 3.744 0 0111.006 1h4.245a.75.75 0 01.75.75v10.5a.75.75 0 01-.75.75h-4.507a2.25 2.25 0 00-1.591.659l-.622.621a.75.75 0 01-1.06 0l-.622-.621A2.25 2.25 0 005.258 13H.75a.75.75 0 01-.75-.75V1.75zm8.755 3a2.25 2.25 0 012.25-2.25H14.5v9h-3.757c-.71 0-1.4.201-1.992.572l.004-7.322zm-1.504 7.324l.004-5.073-.002-2.253A2.25 2.25 0 005.003 2.5H1.5v9h3.757a3.75 3.75 0 011.994.574z"></path></svg>
|
||||||
|
\${computed.plugins.traffic.views.count} views in last two weeks
|
||||||
|
</div>\` : ""
|
||||||
|
}
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -440,6 +452,7 @@ __webpack_require__.r(__webpack_exports__);
|
|||||||
repositories(last: 100, isFork: false, ownerAffiliations: OWNER) {
|
repositories(last: 100, isFork: false, ownerAffiliations: OWNER) {
|
||||||
totalCount
|
totalCount
|
||||||
nodes {
|
nodes {
|
||||||
|
name
|
||||||
watchers {
|
watchers {
|
||||||
totalCount
|
totalCount
|
||||||
}
|
}
|
||||||
@@ -528,11 +541,13 @@ __webpack_require__.r(__webpack_exports__);
|
|||||||
const rest = github.getOctokit(token)
|
const rest = github.getOctokit(token)
|
||||||
|
|
||||||
//Additional plugins
|
//Additional plugins
|
||||||
const plugins = {}, q = {}
|
const enabled = new Set(core.getInput("plugins", {default:[]}))
|
||||||
|
const plugins = {lines:{enabled:enabled.has("lines")}, traffic:{enabled:enabled.has("traffic")}, pagespeed:{enabled:enabled.has("pagespeed")}}
|
||||||
if (core.getInput("pagespeed_token")) {
|
if (core.getInput("pagespeed_token")) {
|
||||||
plugins.pagespeed = {enabled:true, token:core.getInput("pagespeed_token")}
|
console.log(`Pagespeed token | provided`)
|
||||||
q.pagespeed = true
|
plugins.pagespeed.token = core.getInput("pagespeed_token")
|
||||||
}
|
}
|
||||||
|
const q = Object.fromEntries(Object.entries(plugins).filter(([key, plugin]) => plugin.enabled).map(([key]) => [key, true]))
|
||||||
|
|
||||||
//Render metrics
|
//Render metrics
|
||||||
const rendered = await metrics({login:user, q}, {template, style, query, graphql, plugins})
|
const rendered = await metrics({login:user, q}, {template, style, query, graphql, plugins})
|
||||||
@@ -9656,17 +9671,18 @@ __webpack_require__.r(__webpack_exports__);
|
|||||||
/* harmony export */ });
|
/* harmony export */ });
|
||||||
/* harmony import */ var image_to_base64__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7192);
|
/* harmony import */ var image_to_base64__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7192);
|
||||||
/* harmony import */ var image_to_base64__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(image_to_base64__WEBPACK_IMPORTED_MODULE_0__);
|
/* harmony import */ var image_to_base64__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(image_to_base64__WEBPACK_IMPORTED_MODULE_0__);
|
||||||
/* harmony import */ var _plugins_index_mjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9859);
|
/* harmony import */ var _plugins_index_mjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5820);
|
||||||
//Imports
|
//Imports
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Setup
|
//Setup
|
||||||
async function metrics({login, q}, {template, style, query, graphql, plugins}) {
|
async function metrics({login, q}, {template, style, query, graphql, rest, plugins}) {
|
||||||
//Compute rendering
|
//Compute rendering
|
||||||
try {
|
try {
|
||||||
|
|
||||||
//Query data from GitHub API
|
//Query data from GitHub API
|
||||||
|
console.debug(`metrics/metrics/${login} > query`)
|
||||||
const data = await graphql(query
|
const data = await graphql(query
|
||||||
.replace(/[$]login/, `"${login}"`)
|
.replace(/[$]login/, `"${login}"`)
|
||||||
.replace(/[$]calendar.to/, `"${(new Date()).toISOString()}"`)
|
.replace(/[$]calendar.to/, `"${(new Date()).toISOString()}"`)
|
||||||
@@ -9682,6 +9698,8 @@ __webpack_require__.r(__webpack_exports__);
|
|||||||
//Plugins
|
//Plugins
|
||||||
if (data.user.websiteUrl)
|
if (data.user.websiteUrl)
|
||||||
_plugins_index_mjs__WEBPACK_IMPORTED_MODULE_1__/* .default.pagespeed */ .Z.pagespeed({url:data.user.websiteUrl, computed, pending, q}, plugins.pagespeed)
|
_plugins_index_mjs__WEBPACK_IMPORTED_MODULE_1__/* .default.pagespeed */ .Z.pagespeed({url:data.user.websiteUrl, computed, pending, q}, plugins.pagespeed)
|
||||||
|
_plugins_index_mjs__WEBPACK_IMPORTED_MODULE_1__/* .default.lines */ .Z.lines({login, repositories:data.user.repositories.nodes.map(({name}) => name), rest, computed, pending, q}, plugins.lines)
|
||||||
|
_plugins_index_mjs__WEBPACK_IMPORTED_MODULE_1__/* .default.traffic */ .Z.traffic({login, repositories:data.user.repositories.nodes.map(({name}) => name), rest, computed, pending, q}, plugins.traffic)
|
||||||
|
|
||||||
//Iterate through user's repositories
|
//Iterate through user's repositories
|
||||||
for (const repository of data.user.repositories.nodes) {
|
for (const repository of data.user.repositories.nodes) {
|
||||||
@@ -9728,6 +9746,7 @@ __webpack_require__.r(__webpack_exports__);
|
|||||||
await Promise.all(pending)
|
await Promise.all(pending)
|
||||||
|
|
||||||
//Eval rendering and return
|
//Eval rendering and return
|
||||||
|
console.debug(`metrics/metrics/${login} > computed`)
|
||||||
return eval(`\`${template}\``)
|
return eval(`\`${template}\``)
|
||||||
}
|
}
|
||||||
//Internal error
|
//Internal error
|
||||||
@@ -9736,7 +9755,7 @@ __webpack_require__.r(__webpack_exports__);
|
|||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 9859:
|
/***/ 5820:
|
||||||
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
@@ -9746,6 +9765,51 @@ __webpack_require__.d(__webpack_exports__, {
|
|||||||
"Z": () => /* default */ E_Users_lecoq_Documents_GitHub_gitstats_src_plugins_index
|
"Z": () => /* default */ E_Users_lecoq_Documents_GitHub_gitstats_src_plugins_index
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// CONCATENATED MODULE: E:\Users\lecoq\Documents\GitHub\gitstats\src\plugins\lines\index.mjs
|
||||||
|
//Formatter
|
||||||
|
function format(n) {
|
||||||
|
for (const {u, v} of [{u:"b", v:10**9}, {u:"m", v:10**6}, {u:"k", v:10**3}])
|
||||||
|
if (n/v >= 1)
|
||||||
|
return `${(n/v).toFixed(2).substr(0, 4).replace(/[.]0*$/, "")}${u}`
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
//Setup
|
||||||
|
/* harmony default export */ function E_Users_lecoq_Documents_GitHub_gitstats_src_plugins_lines_index({login, repositories = [], rest, computed, pending, q}, {enabled = false} = {}) {
|
||||||
|
//Check if plugin is enabled and requirements are met
|
||||||
|
if (!enabled)
|
||||||
|
return computed.plugins.lines = null
|
||||||
|
if (!q.lines)
|
||||||
|
return computed.plugins.lines = null
|
||||||
|
console.debug(`metrics/plugins/lines/${login} > started`)
|
||||||
|
|
||||||
|
//Plugin execution
|
||||||
|
pending.push(new Promise(async solve => {
|
||||||
|
//Get contributors stats from repositories
|
||||||
|
const lines = {added:0, deleted:0}
|
||||||
|
const response = await Promise.all(repositories.map(async repo => await rest.repos.getContributorsStats({owner:login, repo})))
|
||||||
|
//Compute changed lines
|
||||||
|
response.map(({data:repository}) => {
|
||||||
|
//Check if data are available
|
||||||
|
if (!repository)
|
||||||
|
return
|
||||||
|
//Extract author
|
||||||
|
const [contributor] = repository.filter(({author}) => author.login === login)
|
||||||
|
//Compute editions
|
||||||
|
if (contributor)
|
||||||
|
contributor.weeks.forEach(({a, d}) => (lines.added += a, lines.deleted += d))
|
||||||
|
})
|
||||||
|
//Format values
|
||||||
|
lines.added = format(lines.added)
|
||||||
|
lines.deleted = format(lines.deleted)
|
||||||
|
//Save results
|
||||||
|
computed.plugins = {lines}
|
||||||
|
console.debug(`metrics/plugins/lines/${login} > ${JSON.stringify(computed.plugins.lines)}`)
|
||||||
|
solve()
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// EXTERNAL MODULE: E:\Users\lecoq\Documents\GitHub\gitstats\node_modules\axios\index.js
|
// EXTERNAL MODULE: E:\Users\lecoq\Documents\GitHub\gitstats\node_modules\axios\index.js
|
||||||
var E_Users_lecoq_Documents_GitHub_gitstats_node_modules_axios_index = __webpack_require__(2390);
|
var E_Users_lecoq_Documents_GitHub_gitstats_node_modules_axios_index = __webpack_require__(2390);
|
||||||
var E_Users_lecoq_Documents_GitHub_gitstats_node_modules_axios_index_default = /*#__PURE__*/__webpack_require__.n(E_Users_lecoq_Documents_GitHub_gitstats_node_modules_axios_index);
|
var E_Users_lecoq_Documents_GitHub_gitstats_node_modules_axios_index_default = /*#__PURE__*/__webpack_require__.n(E_Users_lecoq_Documents_GitHub_gitstats_node_modules_axios_index);
|
||||||
@@ -9755,14 +9819,17 @@ var E_Users_lecoq_Documents_GitHub_gitstats_node_modules_axios_index_default = /
|
|||||||
|
|
||||||
|
|
||||||
//Setup
|
//Setup
|
||||||
/* harmony default export */ function E_Users_lecoq_Documents_GitHub_gitstats_src_plugins_pagespeed_index({url, computed, pending, q}, {enabled = false, token = null} = {}) {
|
/* harmony default export */ function E_Users_lecoq_Documents_GitHub_gitstats_src_plugins_pagespeed_index({login, url, computed, pending, q}, {enabled = false, token = null} = {}) {
|
||||||
//Check if plugin is enabled and requirements are met
|
//Check if plugin is enabled and requirements are met
|
||||||
if (!enabled)
|
if (!enabled)
|
||||||
return computed.plugins.pagespeed = null
|
return computed.plugins.pagespeed = null
|
||||||
|
if (!token)
|
||||||
|
return computed.plugins.pagespeed = null
|
||||||
if (!url)
|
if (!url)
|
||||||
return computed.plugins.pagespeed = null
|
return computed.plugins.pagespeed = null
|
||||||
if (!q.pagespeed)
|
if (!q.pagespeed)
|
||||||
return computed.plugins.pagespeed = null
|
return computed.plugins.pagespeed = null
|
||||||
|
console.debug(`metrics/plugins/pagespeed/${login} > started`)
|
||||||
|
|
||||||
//Plugin execution
|
//Plugin execution
|
||||||
pending.push(new Promise(async solve => {
|
pending.push(new Promise(async solve => {
|
||||||
@@ -9777,6 +9844,41 @@ var E_Users_lecoq_Documents_GitHub_gitstats_node_modules_axios_index_default = /
|
|||||||
}))
|
}))
|
||||||
//Save results
|
//Save results
|
||||||
computed.plugins.pagespeed = {url, scores:[scores.get("performance"), scores.get("accessibility"), scores.get("best-practices"), scores.get("seo")]}
|
computed.plugins.pagespeed = {url, scores:[scores.get("performance"), scores.get("accessibility"), scores.get("best-practices"), scores.get("seo")]}
|
||||||
|
console.debug(`metrics/plugins/pagespeed/${login} > ${JSON.stringify(computed.plugins.pagespeed)}`)
|
||||||
|
solve()
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
// CONCATENATED MODULE: E:\Users\lecoq\Documents\GitHub\gitstats\src\plugins\traffic\index.mjs
|
||||||
|
//Formatter
|
||||||
|
function E_Users_lecoq_Documents_GitHub_gitstats_src_plugins_traffic_index_format(n) {
|
||||||
|
for (const {u, v} of [{u:"b", v:10**9}, {u:"m", v:10**6}, {u:"k", v:10**3}])
|
||||||
|
if (n/v >= 1)
|
||||||
|
return `${(n/v).toFixed(2).substr(0, 4).replace(/[.]0*$/, "")}${u}`
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
//Setup
|
||||||
|
/* harmony default export */ function E_Users_lecoq_Documents_GitHub_gitstats_src_plugins_traffic_index({login, repositories = [], rest, computed, pending, q}, {enabled = false} = {}) {
|
||||||
|
//Check if plugin is enabled and requirements are met
|
||||||
|
if (!enabled)
|
||||||
|
return computed.plugins.traffic = null
|
||||||
|
if (!q.traffic)
|
||||||
|
return computed.plugins.traffic = null
|
||||||
|
console.debug(`metrics/plugins/traffic/${login} > started`)
|
||||||
|
|
||||||
|
//Plugin execution
|
||||||
|
pending.push(new Promise(async solve => {
|
||||||
|
//Get views stats from repositories
|
||||||
|
const views = {count:0, uniques:0}
|
||||||
|
const response = await Promise.all(repositories.map(async repo => await rest.repos.getViews({owner:login, repo})))
|
||||||
|
//Compute views
|
||||||
|
response.filter(({data}) => data).map(({data:{count, uniques}}) => (views.count += count, views.uniques += uniques))
|
||||||
|
//Format values
|
||||||
|
views.count = E_Users_lecoq_Documents_GitHub_gitstats_src_plugins_traffic_index_format(views.count)
|
||||||
|
views.uniques = E_Users_lecoq_Documents_GitHub_gitstats_src_plugins_traffic_index_format(views.uniques)
|
||||||
|
//Save results
|
||||||
|
computed.plugins.traffic = {views}
|
||||||
|
console.debug(`metrics/plugins/traffic/${login} > ${JSON.stringify(computed.plugins.traffic)}`)
|
||||||
solve()
|
solve()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@@ -9784,9 +9886,13 @@ var E_Users_lecoq_Documents_GitHub_gitstats_node_modules_axios_index_default = /
|
|||||||
//Imports
|
//Imports
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Exports
|
//Exports
|
||||||
/* harmony default export */ const E_Users_lecoq_Documents_GitHub_gitstats_src_plugins_index = ({
|
/* harmony default export */ const E_Users_lecoq_Documents_GitHub_gitstats_src_plugins_index = ({
|
||||||
pagespeed: E_Users_lecoq_Documents_GitHub_gitstats_src_plugins_pagespeed_index
|
lines: E_Users_lecoq_Documents_GitHub_gitstats_src_plugins_lines_index,
|
||||||
|
pagespeed: E_Users_lecoq_Documents_GitHub_gitstats_src_plugins_pagespeed_index,
|
||||||
|
traffic: E_Users_lecoq_Documents_GitHub_gitstats_src_plugins_traffic_index,
|
||||||
});
|
});
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|||||||
@@ -30,11 +30,13 @@
|
|||||||
const rest = github.getOctokit(token)
|
const rest = github.getOctokit(token)
|
||||||
|
|
||||||
//Additional plugins
|
//Additional plugins
|
||||||
const plugins = {}, q = {}
|
const enabled = new Set(core.getInput("plugins", {default:[]}))
|
||||||
|
const plugins = {lines:{enabled:enabled.has("lines")}, traffic:{enabled:enabled.has("traffic")}, pagespeed:{enabled:enabled.has("pagespeed")}}
|
||||||
if (core.getInput("pagespeed_token")) {
|
if (core.getInput("pagespeed_token")) {
|
||||||
plugins.pagespeed = {enabled:true, token:core.getInput("pagespeed_token")}
|
console.log(`Pagespeed token | provided`)
|
||||||
q.pagespeed = true
|
plugins.pagespeed.token = core.getInput("pagespeed_token")
|
||||||
}
|
}
|
||||||
|
const q = Object.fromEntries(Object.entries(plugins).filter(([key, plugin]) => plugin.enabled).map(([key]) => [key, true]))
|
||||||
|
|
||||||
//Render metrics
|
//Render metrics
|
||||||
const rendered = await metrics({login:user, q}, {template, style, query, graphql, plugins})
|
const rendered = await metrics({login:user, q}, {template, style, query, graphql, plugins})
|
||||||
|
|||||||
35
package-lock.json
generated
35
package-lock.json
generated
@@ -77,6 +77,11 @@
|
|||||||
"@octokit/types": "^5.3.0"
|
"@octokit/types": "^5.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@octokit/plugin-request-log": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-ywoxP68aOT3zHCLgWZgwUJatiENeHE7xJzYjfz8WI0goynp96wETBF+d95b8g/uL4QmS6owPVlaxiz3wyMAzcw=="
|
||||||
|
},
|
||||||
"@octokit/plugin-rest-endpoint-methods": {
|
"@octokit/plugin-rest-endpoint-methods": {
|
||||||
"version": "4.1.4",
|
"version": "4.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.1.4.tgz",
|
||||||
@@ -111,6 +116,36 @@
|
|||||||
"once": "^1.4.0"
|
"once": "^1.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@octokit/rest": {
|
||||||
|
"version": "18.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.0.6.tgz",
|
||||||
|
"integrity": "sha512-ES4lZBKPJMX/yUoQjAZiyFjei9pJ4lTTfb9k7OtYoUzKPDLl/M8jiHqt6qeSauyU4eZGLw0sgP1WiQl9FYeM5w==",
|
||||||
|
"requires": {
|
||||||
|
"@octokit/core": "^3.0.0",
|
||||||
|
"@octokit/plugin-paginate-rest": "^2.2.0",
|
||||||
|
"@octokit/plugin-request-log": "^1.0.0",
|
||||||
|
"@octokit/plugin-rest-endpoint-methods": "4.2.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/plugin-rest-endpoint-methods": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-1/qn1q1C1hGz6W/iEDm9DoyNoG/xdFDt78E3eZ5hHeUfJTLJgyAMdj9chL/cNBHjcjd+FH5aO1x0VCqR2RE0mw==",
|
||||||
|
"requires": {
|
||||||
|
"@octokit/types": "^5.5.0",
|
||||||
|
"deprecation": "^2.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@octokit/types": {
|
||||||
|
"version": "5.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-5.5.0.tgz",
|
||||||
|
"integrity": "sha512-UZ1pErDue6bZNjYOotCNveTXArOMZQFG6hKJfOnGnulVCMcVVi7YIIuuR4WfBhjo7zgpmzn/BkPDnUXtNx+PcQ==",
|
||||||
|
"requires": {
|
||||||
|
"@types/node": ">= 8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@octokit/types": {
|
"@octokit/types": {
|
||||||
"version": "5.4.1",
|
"version": "5.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-5.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-5.4.1.tgz",
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
"@actions/core": "^1.2.5",
|
"@actions/core": "^1.2.5",
|
||||||
"@actions/github": "^4.0.0",
|
"@actions/github": "^4.0.0",
|
||||||
"@octokit/graphql": "^4.5.4",
|
"@octokit/graphql": "^4.5.4",
|
||||||
|
"@octokit/rest": "^18.0.6",
|
||||||
"axios": "^0.20.0",
|
"axios": "^0.20.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-rate-limit": "^5.1.3",
|
"express-rate-limit": "^5.1.3",
|
||||||
|
|||||||
@@ -6,10 +6,17 @@
|
|||||||
"ratelimiter":null, "//":"Rate limiter (see express-rate-limit documentation for options)",
|
"ratelimiter":null, "//":"Rate limiter (see express-rate-limit documentation for options)",
|
||||||
"port":3000, "//":"Listening port",
|
"port":3000, "//":"Listening port",
|
||||||
"debug":false, "//":"Debug mode",
|
"debug":false, "//":"Debug mode",
|
||||||
|
|
||||||
"plugins":{ "//":"Additional plugins (optional)",
|
"plugins":{ "//":"Additional plugins (optional)",
|
||||||
"pagespeed":{ "//":"Pagespeed configuration",
|
"pagespeed":{ "//":"Pagespeed plugin",
|
||||||
"enabled":false, "//":"Enable or disable Pagespeed metrics",
|
"enabled":false, "//":"Enable or disable Pagespeed metrics",
|
||||||
"token":"******", "//":"Pagespeed token"
|
"token":"******", "//":"Pagespeed token"
|
||||||
|
},
|
||||||
|
"traffic":{ "//":"Traffic plugin (GitHub API token must be RW for this to work)",
|
||||||
|
"enabled":true, "//":"Enable or disable repositories total page views is last two weeks"
|
||||||
|
},
|
||||||
|
"lines":{ "//":"Lines plugin",
|
||||||
|
"enabled":true, "//":"Enable or disabled repositories total lines added/removed"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
21
src/app.mjs
21
src/app.mjs
@@ -3,6 +3,7 @@
|
|||||||
import fs from "fs"
|
import fs from "fs"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import octokit from "@octokit/graphql"
|
import octokit from "@octokit/graphql"
|
||||||
|
import OctokitRest from "@octokit/rest"
|
||||||
import cache from "memory-cache"
|
import cache from "memory-cache"
|
||||||
import ratelimit from "express-rate-limit"
|
import ratelimit from "express-rate-limit"
|
||||||
import metrics from "./metrics.mjs"
|
import metrics from "./metrics.mjs"
|
||||||
@@ -19,10 +20,11 @@
|
|||||||
const settings = JSON.parse((await fs.promises.readFile(path.join("settings.json"))).toString())
|
const settings = JSON.parse((await fs.promises.readFile(path.join("settings.json"))).toString())
|
||||||
const {token, maxusers = 0, restricted = [], debug = false, cached = 30*60*1000, port = 3000, ratelimiter = null, plugins = null} = settings
|
const {token, maxusers = 0, restricted = [], debug = false, cached = 30*60*1000, port = 3000, ratelimiter = null, plugins = null} = settings
|
||||||
if (debug)
|
if (debug)
|
||||||
console.log(settings)
|
console.debug(settings)
|
||||||
//Load svg template, style and query
|
//Load svg template, style and query
|
||||||
let [template, style, query] = await load()
|
let [template, style, query] = await load()
|
||||||
const graphql = octokit.graphql.defaults({headers:{authorization: `token ${token}`}})
|
const graphql = octokit.graphql.defaults({headers:{authorization: `token ${token}`}})
|
||||||
|
const rest = new OctokitRest.Octokit({auth:token})
|
||||||
|
|
||||||
//Setup server
|
//Setup server
|
||||||
const app = express()
|
const app = express()
|
||||||
@@ -51,8 +53,10 @@
|
|||||||
|
|
||||||
//Request params
|
//Request params
|
||||||
const {login} = req.params
|
const {login} = req.params
|
||||||
if ((restricted.length)&&(!restricted.includes(login)))
|
if ((restricted.length)&&(!restricted.includes(login))) {
|
||||||
|
console.debug(`metrics/app/${login} > 403 (not in whitelisted users)`)
|
||||||
return res.sendStatus(403)
|
return res.sendStatus(403)
|
||||||
|
}
|
||||||
|
|
||||||
//Read cached data if possible
|
//Read cached data if possible
|
||||||
if ((!debug)&&(cached)&&(cache.get(login))) {
|
if ((!debug)&&(cached)&&(cache.get(login))) {
|
||||||
@@ -61,15 +65,17 @@
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
//Maximum simultaneous users
|
//Maximum simultaneous users
|
||||||
if ((maxusers)&&(cache.size()+1 > maxusers))
|
if ((maxusers)&&(cache.size()+1 > maxusers)) {
|
||||||
|
console.debug(`metrics/app/${login} > 503 (maximum users reached)`)
|
||||||
return res.sendStatus(503)
|
return res.sendStatus(503)
|
||||||
|
}
|
||||||
|
|
||||||
//Compute rendering
|
//Compute rendering
|
||||||
try {
|
try {
|
||||||
//Render
|
//Render
|
||||||
if (debug)
|
if (debug)
|
||||||
[template, style, query] = await load()
|
[template, style, query] = await load()
|
||||||
const rendered = await metrics({login, q:req.query}, {template, style, query, graphql, plugins})
|
const rendered = await metrics({login, q:req.query}, {template, style, query, graphql, rest, plugins})
|
||||||
//Cache
|
//Cache
|
||||||
if ((!debug)&&(cached))
|
if ((!debug)&&(cached))
|
||||||
cache.put(login, rendered, cached)
|
cache.put(login, rendered, cached)
|
||||||
@@ -80,8 +86,10 @@
|
|||||||
//Internal error
|
//Internal error
|
||||||
catch (error) {
|
catch (error) {
|
||||||
//Not found user
|
//Not found user
|
||||||
if ((error instanceof Error)&&(/^user not found$/.test(error.message)))
|
if ((error instanceof Error)&&(/^user not found$/.test(error.message))) {
|
||||||
|
console.debug(`metrics/app/${login} > 404 (user not found)`)
|
||||||
return res.sendStatus(404)
|
return res.sendStatus(404)
|
||||||
|
}
|
||||||
//General error
|
//General error
|
||||||
console.error(error)
|
console.error(error)
|
||||||
res.sendStatus(500)
|
res.sendStatus(500)
|
||||||
@@ -95,6 +103,7 @@
|
|||||||
`Restricted to users | ${restricted.size ? [...restricted].join(", ") : "(unrestricted)"}`,
|
`Restricted to users | ${restricted.size ? [...restricted].join(", ") : "(unrestricted)"}`,
|
||||||
`Cached time | ${cached} seconds`,
|
`Cached time | ${cached} seconds`,
|
||||||
`Rate limiter | ${ratelimiter ? JSON.stringify(ratelimiter) : "(enabled)"}`,
|
`Rate limiter | ${ratelimiter ? JSON.stringify(ratelimiter) : "(enabled)"}`,
|
||||||
`Max simultaneous users | ${maxusers ? `${maxusers} users` : "(unrestricted)"}`
|
`Max simultaneous users | ${maxusers ? `${maxusers} users` : "(unrestricted)"}`,
|
||||||
|
`Plugins enabled | ${Object.entries(plugins).filter(([key, plugin]) => plugin.enabled).map(([key]) => key).join(", ")}`
|
||||||
].join("\n")))
|
].join("\n")))
|
||||||
}
|
}
|
||||||
@@ -3,11 +3,12 @@
|
|||||||
import Plugins from "./plugins/index.mjs"
|
import Plugins from "./plugins/index.mjs"
|
||||||
|
|
||||||
//Setup
|
//Setup
|
||||||
export default async function metrics({login, q}, {template, style, query, graphql, plugins}) {
|
export default async function metrics({login, q}, {template, style, query, graphql, rest, plugins}) {
|
||||||
//Compute rendering
|
//Compute rendering
|
||||||
try {
|
try {
|
||||||
|
|
||||||
//Query data from GitHub API
|
//Query data from GitHub API
|
||||||
|
console.debug(`metrics/metrics/${login} > query`)
|
||||||
const data = await graphql(query
|
const data = await graphql(query
|
||||||
.replace(/[$]login/, `"${login}"`)
|
.replace(/[$]login/, `"${login}"`)
|
||||||
.replace(/[$]calendar.to/, `"${(new Date()).toISOString()}"`)
|
.replace(/[$]calendar.to/, `"${(new Date()).toISOString()}"`)
|
||||||
@@ -23,6 +24,8 @@
|
|||||||
//Plugins
|
//Plugins
|
||||||
if (data.user.websiteUrl)
|
if (data.user.websiteUrl)
|
||||||
Plugins.pagespeed({url:data.user.websiteUrl, computed, pending, q}, plugins.pagespeed)
|
Plugins.pagespeed({url:data.user.websiteUrl, computed, pending, q}, plugins.pagespeed)
|
||||||
|
Plugins.lines({login, repositories:data.user.repositories.nodes.map(({name}) => name), rest, computed, pending, q}, plugins.lines)
|
||||||
|
Plugins.traffic({login, repositories:data.user.repositories.nodes.map(({name}) => name), rest, computed, pending, q}, plugins.traffic)
|
||||||
|
|
||||||
//Iterate through user's repositories
|
//Iterate through user's repositories
|
||||||
for (const repository of data.user.repositories.nodes) {
|
for (const repository of data.user.repositories.nodes) {
|
||||||
@@ -69,6 +72,7 @@
|
|||||||
await Promise.all(pending)
|
await Promise.all(pending)
|
||||||
|
|
||||||
//Eval rendering and return
|
//Eval rendering and return
|
||||||
|
console.debug(`metrics/metrics/${login} > computed`)
|
||||||
return eval(`\`${template}\``)
|
return eval(`\`${template}\``)
|
||||||
}
|
}
|
||||||
//Internal error
|
//Internal error
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
//Imports
|
//Imports
|
||||||
|
import lines from "./lines/index.mjs"
|
||||||
import pagespeed from "./pagespeed/index.mjs"
|
import pagespeed from "./pagespeed/index.mjs"
|
||||||
|
import traffic from "./traffic/index.mjs"
|
||||||
|
|
||||||
//Exports
|
//Exports
|
||||||
export default {
|
export default {
|
||||||
pagespeed
|
lines,
|
||||||
|
pagespeed,
|
||||||
|
traffic,
|
||||||
}
|
}
|
||||||
@@ -1 +1,43 @@
|
|||||||
//Placeholder for https://docs.github.com/en/rest/reference/repos#get-all-contributor-commit-activity
|
//Formatter
|
||||||
|
function format(n) {
|
||||||
|
for (const {u, v} of [{u:"b", v:10**9}, {u:"m", v:10**6}, {u:"k", v:10**3}])
|
||||||
|
if (n/v >= 1)
|
||||||
|
return `${(n/v).toFixed(2).substr(0, 4).replace(/[.]0*$/, "")}${u}`
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
//Setup
|
||||||
|
export default function ({login, repositories = [], rest, computed, pending, q}, {enabled = false} = {}) {
|
||||||
|
//Check if plugin is enabled and requirements are met
|
||||||
|
if (!enabled)
|
||||||
|
return computed.plugins.lines = null
|
||||||
|
if (!q.lines)
|
||||||
|
return computed.plugins.lines = null
|
||||||
|
console.debug(`metrics/plugins/lines/${login} > started`)
|
||||||
|
|
||||||
|
//Plugin execution
|
||||||
|
pending.push(new Promise(async solve => {
|
||||||
|
//Get contributors stats from repositories
|
||||||
|
const lines = {added:0, deleted:0}
|
||||||
|
const response = await Promise.all(repositories.map(async repo => await rest.repos.getContributorsStats({owner:login, repo})))
|
||||||
|
//Compute changed lines
|
||||||
|
response.map(({data:repository}) => {
|
||||||
|
//Check if data are available
|
||||||
|
if (!repository)
|
||||||
|
return
|
||||||
|
//Extract author
|
||||||
|
const [contributor] = repository.filter(({author}) => author.login === login)
|
||||||
|
//Compute editions
|
||||||
|
if (contributor)
|
||||||
|
contributor.weeks.forEach(({a, d}) => (lines.added += a, lines.deleted += d))
|
||||||
|
})
|
||||||
|
//Format values
|
||||||
|
lines.added = format(lines.added)
|
||||||
|
lines.deleted = format(lines.deleted)
|
||||||
|
//Save results
|
||||||
|
computed.plugins = {lines}
|
||||||
|
console.debug(`metrics/plugins/lines/${login} > ${JSON.stringify(computed.plugins.lines)}`)
|
||||||
|
solve()
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,17 @@
|
|||||||
import axios from "axios"
|
import axios from "axios"
|
||||||
|
|
||||||
//Setup
|
//Setup
|
||||||
export default function ({url, computed, pending, q}, {enabled = false, token = null} = {}) {
|
export default function ({login, url, computed, pending, q}, {enabled = false, token = null} = {}) {
|
||||||
//Check if plugin is enabled and requirements are met
|
//Check if plugin is enabled and requirements are met
|
||||||
if (!enabled)
|
if (!enabled)
|
||||||
return computed.plugins.pagespeed = null
|
return computed.plugins.pagespeed = null
|
||||||
|
if (!token)
|
||||||
|
return computed.plugins.pagespeed = null
|
||||||
if (!url)
|
if (!url)
|
||||||
return computed.plugins.pagespeed = null
|
return computed.plugins.pagespeed = null
|
||||||
if (!q.pagespeed)
|
if (!q.pagespeed)
|
||||||
return computed.plugins.pagespeed = null
|
return computed.plugins.pagespeed = null
|
||||||
|
console.debug(`metrics/plugins/pagespeed/${login} > started`)
|
||||||
|
|
||||||
//Plugin execution
|
//Plugin execution
|
||||||
pending.push(new Promise(async solve => {
|
pending.push(new Promise(async solve => {
|
||||||
@@ -24,6 +27,7 @@
|
|||||||
}))
|
}))
|
||||||
//Save results
|
//Save results
|
||||||
computed.plugins.pagespeed = {url, scores:[scores.get("performance"), scores.get("accessibility"), scores.get("best-practices"), scores.get("seo")]}
|
computed.plugins.pagespeed = {url, scores:[scores.get("performance"), scores.get("accessibility"), scores.get("best-practices"), scores.get("seo")]}
|
||||||
|
console.debug(`metrics/plugins/pagespeed/${login} > ${JSON.stringify(computed.plugins.pagespeed)}`)
|
||||||
solve()
|
solve()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@@ -1 +1,33 @@
|
|||||||
//Placeholder for https://docs.github.com/en/rest/reference/repos#get-page-views
|
//Formatter
|
||||||
|
function format(n) {
|
||||||
|
for (const {u, v} of [{u:"b", v:10**9}, {u:"m", v:10**6}, {u:"k", v:10**3}])
|
||||||
|
if (n/v >= 1)
|
||||||
|
return `${(n/v).toFixed(2).substr(0, 4).replace(/[.]0*$/, "")}${u}`
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
//Setup
|
||||||
|
export default function ({login, repositories = [], rest, computed, pending, q}, {enabled = false} = {}) {
|
||||||
|
//Check if plugin is enabled and requirements are met
|
||||||
|
if (!enabled)
|
||||||
|
return computed.plugins.traffic = null
|
||||||
|
if (!q.traffic)
|
||||||
|
return computed.plugins.traffic = null
|
||||||
|
console.debug(`metrics/plugins/traffic/${login} > started`)
|
||||||
|
|
||||||
|
//Plugin execution
|
||||||
|
pending.push(new Promise(async solve => {
|
||||||
|
//Get views stats from repositories
|
||||||
|
const views = {count:0, uniques:0}
|
||||||
|
const response = await Promise.all(repositories.map(async repo => await rest.repos.getViews({owner:login, repo})))
|
||||||
|
//Compute views
|
||||||
|
response.filter(({data}) => data).map(({data:{count, uniques}}) => (views.count += count, views.uniques += uniques))
|
||||||
|
//Format values
|
||||||
|
views.count = format(views.count)
|
||||||
|
views.uniques = format(views.uniques)
|
||||||
|
//Save results
|
||||||
|
computed.plugins.traffic = {views}
|
||||||
|
console.debug(`metrics/plugins/traffic/${login} > ${JSON.stringify(computed.plugins.traffic)}`)
|
||||||
|
solve()
|
||||||
|
}))
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ query Metrics {
|
|||||||
repositories(last: 100, isFork: false, ownerAffiliations: OWNER) {
|
repositories(last: 100, isFork: false, ownerAffiliations: OWNER) {
|
||||||
totalCount
|
totalCount
|
||||||
nodes {
|
nodes {
|
||||||
|
name
|
||||||
watchers {
|
watchers {
|
||||||
totalCount
|
totalCount
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,6 +110,12 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M8.878.392a1.75 1.75 0 00-1.756 0l-5.25 3.045A1.75 1.75 0 001 4.951v6.098c0 .624.332 1.2.872 1.514l5.25 3.045a1.75 1.75 0 001.756 0l5.25-3.045c.54-.313.872-.89.872-1.514V4.951c0-.624-.332-1.2-.872-1.514L8.878.392zM7.875 1.69a.25.25 0 01.25 0l4.63 2.685L8 7.133 3.245 4.375l4.63-2.685zM2.5 5.677v5.372c0 .09.047.171.125.216l4.625 2.683V8.432L2.5 5.677zm6.25 8.271l4.625-2.683a.25.25 0 00.125-.216V5.677L8.75 8.432v5.516z"></path></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M8.878.392a1.75 1.75 0 00-1.756 0l-5.25 3.045A1.75 1.75 0 001 4.951v6.098c0 .624.332 1.2.872 1.514l5.25 3.045a1.75 1.75 0 001.756 0l5.25-3.045c.54-.313.872-.89.872-1.514V4.951c0-.624-.332-1.2-.872-1.514L8.878.392zM7.875 1.69a.25.25 0 01.25 0l4.63 2.685L8 7.133 3.245 4.375l4.63-2.685zM2.5 5.677v5.372c0 .09.047.171.125.216l4.625 2.683V8.432L2.5 5.677zm6.25 8.271l4.625-2.683a.25.25 0 00.125-.216V5.677L8.75 8.432v5.516z"></path></svg>
|
||||||
${data.user.packages.totalCount} Package${data.user.packages.totalCount > 1 ? "s" : ""}
|
${data.user.packages.totalCount} Package${data.user.packages.totalCount > 1 ? "s" : ""}
|
||||||
</div>
|
</div>
|
||||||
|
${computed.plugins.lines ? `
|
||||||
|
<div class="field">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M4.72 3.22a.75.75 0 011.06 1.06L2.06 8l3.72 3.72a.75.75 0 11-1.06 1.06L.47 8.53a.75.75 0 010-1.06l4.25-4.25zm6.56 0a.75.75 0 10-1.06 1.06L13.94 8l-3.72 3.72a.75.75 0 101.06 1.06l4.25-4.25a.75.75 0 000-1.06l-4.25-4.25z"></path></svg>
|
||||||
|
${computed.plugins.lines.added} added, ${computed.plugins.lines.deleted} removed
|
||||||
|
</div>` : ""
|
||||||
|
}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
@@ -121,6 +127,12 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M1.679 7.932c.412-.621 1.242-1.75 2.366-2.717C5.175 4.242 6.527 3.5 8 3.5c1.473 0 2.824.742 3.955 1.715 1.124.967 1.954 2.096 2.366 2.717a.119.119 0 010 .136c-.412.621-1.242 1.75-2.366 2.717C10.825 11.758 9.473 12.5 8 12.5c-1.473 0-2.824-.742-3.955-1.715C2.92 9.818 2.09 8.69 1.679 8.068a.119.119 0 010-.136zM8 2c-1.981 0-3.67.992-4.933 2.078C1.797 5.169.88 6.423.43 7.1a1.619 1.619 0 000 1.798c.45.678 1.367 1.932 2.637 3.024C4.329 13.008 6.019 14 8 14c1.981 0 3.67-.992 4.933-2.078 1.27-1.091 2.187-2.345 2.637-3.023a1.619 1.619 0 000-1.798c-.45-.678-1.367-1.932-2.637-3.023C11.671 2.992 9.981 2 8 2zm0 8a2 2 0 100-4 2 2 0 000 4z"></path></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M1.679 7.932c.412-.621 1.242-1.75 2.366-2.717C5.175 4.242 6.527 3.5 8 3.5c1.473 0 2.824.742 3.955 1.715 1.124.967 1.954 2.096 2.366 2.717a.119.119 0 010 .136c-.412.621-1.242 1.75-2.366 2.717C10.825 11.758 9.473 12.5 8 12.5c-1.473 0-2.824-.742-3.955-1.715C2.92 9.818 2.09 8.69 1.679 8.068a.119.119 0 010-.136zM8 2c-1.981 0-3.67.992-4.933 2.078C1.797 5.169.88 6.423.43 7.1a1.619 1.619 0 000 1.798c.45.678 1.367 1.932 2.637 3.024C4.329 13.008 6.019 14 8 14c1.981 0 3.67-.992 4.933-2.078 1.27-1.091 2.187-2.345 2.637-3.023a1.619 1.619 0 000-1.798c-.45-.678-1.367-1.932-2.637-3.023C11.671 2.992 9.981 2 8 2zm0 8a2 2 0 100-4 2 2 0 000 4z"></path></svg>
|
||||||
${data.computed.repositories.watchers} Watcher${data.computed.repositories.watchers > 1 ? "s" : ""}
|
${data.computed.repositories.watchers} Watcher${data.computed.repositories.watchers > 1 ? "s" : ""}
|
||||||
</div>
|
</div>
|
||||||
|
${computed.plugins.traffic ? `
|
||||||
|
<div class="field">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M0 1.75A.75.75 0 01.75 1h4.253c1.227 0 2.317.59 3 1.501A3.744 3.744 0 0111.006 1h4.245a.75.75 0 01.75.75v10.5a.75.75 0 01-.75.75h-4.507a2.25 2.25 0 00-1.591.659l-.622.621a.75.75 0 01-1.06 0l-.622-.621A2.25 2.25 0 005.258 13H.75a.75.75 0 01-.75-.75V1.75zm8.755 3a2.25 2.25 0 012.25-2.25H14.5v9h-3.757c-.71 0-1.4.201-1.992.572l.004-7.322zm-1.504 7.324l.004-5.073-.002-2.253A2.25 2.25 0 005.003 2.5H1.5v9h3.757a3.75 3.75 0 011.994.574z"></path></svg>
|
||||||
|
${computed.plugins.traffic.views.count} views in last two weeks
|
||||||
|
</div>` : ""
|
||||||
|
}
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 22 KiB |
Reference in New Issue
Block a user