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,5 @@
# 📚 Documentation
<% for (const partial of ["compatibility", "templates", "plugins", "organizations", "contributing"]) { %>
<%- await include(`/partials/documentation/${partial}.md`) -%>
<% } %>

View File

@@ -0,0 +1,15 @@
### 🧰 Template/plugin compatibily matrix
<table>
<tr>
<th nowrap="nowrap">Template\Plugin</th><%# -%>
<% for (const [plugin, {icon}] of Object.entries(plugins).filter(([key, value]) => (value)&&(!["core"].includes(key)))) { %>
<th nowrap="nowrap" align="center"><%= icon %></th><% } %>
</tr><%# -%>
<% for (const [template, {name, readme}] of Object.entries(templates).filter(([key, value]) => (value)&&(!["community"].includes(key)))) { %>
<tr>
<th nowrap="nowrap"><%= name %></th><%# -%>
<% for (const [plugin] of Object.entries(plugins).filter(([key, value]) => (value)&&(!["core"].includes(key)))) { %>
<th nowrap="nowrap" align="center" data-plugin="<%= plugin %>"><%= readme.compatibility[plugin] ? "✔️" : "❌" %></th><% } %>
</tr><% } %>
</table>

View File

@@ -0,0 +1,9 @@
## 💪 Customizing and contributing
Metrics is built to be easily customizable.
Fork this repository, switch used action from `lowlighter/metrics@latest` to your fork and start coding!
To suggest a new feature, report a bug or ask for help, fill an [issue](https://github.com/lowlighter/metrics/issues) describing it.
If you want to contribute, submit a [pull request](https://github.com/lowlighter/metrics/pulls).
Be sure to read [CONTRIBUTING.md](CONTRIBUTING.md) for more information about this.

View File

@@ -0,0 +1,48 @@
### 🏦 Organizations metrics
While metrics targets mainly user accounts, it's possible to render metrics for organization accounts.
![Metrics (organization account)](https://github.com/lowlighter/lowlighter/blob/master/metrics.organization.svg)
<details>
<summary>💬 Metrics for organizations</summary>
Setup is the same as for user accounts, though you'll need to add `read:org` scope, **whether you're member of target organization or not**.
![Add read:org scope to personal token](.github/readme/imgs/setup_token_org_read_scope.png)
You'll also need to set `user` option with your organization name.
If you're encounting errors and your organization is using single sign-on, try to [authorize your personal token](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/authorizing-a-personal-access-token-for-use-with-saml-single-sign-on).
Most of plugins supported by user accounts will work with organization accounts, but note that rendering metrics for organizations consume way more APIs requests.
To support private repositories, add full `repo` scope to your personal token.
#### Example workflow
```yaml
- uses: lowlighter/metrics@latest
with:
# ... other options
token: ${{ secrets.METRICS_TOKEN }} # A personal token from an user account with read:org scope
committer_token: ${{ secrets.GITHUB_TOKEN }} # GitHub auto-generated token
user: organization-name # Organization name
```
</details>
<details>
<summary>💬 Organizations memberships for user accounts</summary>
Only public memberships can be displayed by metrics by default.
You can manage your membership visibility in the `People` tab of your organization:
![Publish organization membership](.github/readme/imgs/setup_public_membership_org.png)
For organization memberships, add `read:org` scope to your personal token.
![Add read:org scope to personal token](.github/readme/imgs/setup_token_org_read_scope.png)
</details>

View File

@@ -0,0 +1,7 @@
## 🧩 Plugins
Plugins are features which provide additional content and lets you customize your rendered metrics.
See their respective documentation for more informations about how to setup them:
<% for (const [plugin, {name}] of Object.entries(plugins).filter(([key, value]) => value)) { %>
* [<%= name %>](/source/plugins/<%= plugin %>/README.md)<%# -%>
<% } %>

View File

@@ -0,0 +1,7 @@
## 🖼️ Templates
Templates lets you change general appearance of rendered metrics.
See their respective documentation for more informations about how to setup them:
<% for (const [template, {name}] of Object.entries(templates).filter(([key, value]) => value)) { %>
* [<%= name %>](/source/templates/<%= template %>/README.md)<%# -%>
<% } %>

80
.github/readme/partials/introduction.md vendored Normal file
View File

@@ -0,0 +1,80 @@
Generate your metrics that you can embed everywhere, including your GitHub profile readme! It works for both user and organization accounts, and even for repositories!
<table>
<tr>
<th align="center">For user accounts</th>
<th align="center">For organization accounts</th>
</tr>
<tr>
<%- plugins.base.readme.demo?.replace(/<img src=/g, `<img alt="" width="400" src=`) %>
</tr>
</table>
<% {
let cell = 0
const elements = Object.entries(plugins).filter(([key, value]) => (value)&&(!["base", "core"].includes(key)))
if (elements.length%2)
elements.push(["", {}])
%>
<table>
<tr>
<th colspan="2" align="center">
<a href="source/plugins/README.md">🧩 <%= elements.length %> plugins</a>
</th>
</tr>
<% for (let i = 0; i < elements.length; i+=2) {
const cells = [["even", elements[i]], ["odd", elements[i+1]]]
for (const [cell, [plugin, {name, readme}]] of cells) {
if (cell === "even") {
-%>
<tr>
<% } %> <th><a href="source/plugins/<%= plugin %>/README.md"><%= name -%></a></th>
<% if (cell === "odd") {
-%> </tr>
<% }}
for (const [cell, [plugin, {name, readme}]] of cells) {
if (cell === "even") {
-%>
<tr>
<% } %> <%- readme.demo.replace(/<img src=/g, `<img alt="" width="400" src=`)?.split("\n")?.map((x, i) => i ? ` ${x}` : x)?.join("\n") %>
<% if (cell === "odd") {
-%> </tr>
<% }}} -%>
<tr>
<th colspan="2" align="center">
<a href="https://github.com/lowlighter/metrics/projects/1">More to come soon!</a>
</th>
</tr>
</table>
<% } %>
<% {
let cell = 0
const elements = Object.entries(templates).filter(([key, value]) => value)
if (elements.length%2)
elements.push(["", {}])
%>
<table>
<tr>
<th colspan="2" align="center">
<a href="source/templates/README.md">🖼️ <%= elements.length-1 %> templates</a>
</th>
</tr>
<% for (let i = 0; i < elements.length; i+=2) {
const cells = [["even", elements[i]], ["odd", elements[i+1]]]
for (const [cell, [template, {name, readme}]] of cells) {
if (cell === "even") {
-%>
<tr>
<% } %> <th><a href="source/templates/<%= template %>/README.md"><%= name -%></a></th>
<% if (cell === "odd") {
-%> </tr>
<% }}
for (const [cell, [template, {name, readme}]] of cells) {
if (cell === "even") {
-%>
<tr>
<% } %> <%- readme.demo.replace(/<img src=/g, `<img alt="" width="400" src=`)?.split("\n")?.map((x, i) => i ? ` ${x}` : x)?.join("\n") %>
<% if (cell === "odd") {
-%> </tr>
<% }}} -%>
</table>
<% } %>

6
.github/readme/partials/license.md vendored Normal file
View File

@@ -0,0 +1,6 @@
## 📜 License
```
MIT License
Copyright (c) 2020 lowlighter
```

15
.github/readme/partials/references.md vendored Normal file
View File

@@ -0,0 +1,15 @@
## 📖 Useful references
* [GitHub GraphQL API](https://docs.github.com/en/graphql)
* [GitHub GraphQL Explorer](https://docs.github.com/en/free-pro-team@latest/graphql/overview/explorer)
* [GitHub Rest API](https://docs.github.com/en/rest)
* [GitHub Octicons](https://github.com/primer/octicons)
* See [GitHub Logos and Usage](https://github.com/logos) for more information.
### ✨ Inspirations
* [anuraghazra/github-readme-stats](https://github.com/anuraghazra/github-readme-stats)
* [jstrieb/github-stats](https://github.com/jstrieb/github-stats)
* [ankurparihar/readme-pagespeed-insights](https://github.com/ankurparihar/readme-pagespeed-insights)
* [jasonlong/isometric-contributions](https://github.com/jasonlong/isometric-contributions)
* [jamesgeorge007/github-activity-readme](https://github.com/jamesgeorge007/github-activity-readme)

5
.github/readme/partials/setup.md vendored Normal file
View File

@@ -0,0 +1,5 @@
# 📜 How to use?
<% for (const partial of ["action", "shared", "web"]) { -%>
<%- await include(`/partials/setup/${partial}.md`) %>
<% } %>

113
.github/readme/partials/setup/action.md vendored Normal file
View File

@@ -0,0 +1,113 @@
## ⚙️ Using GitHub Action on your profile repository (~5 min setup)
Setup a GitHub Action which runs periodically and pushes your generated metrics image to your repository.
See all supported options in [action.yml](action.yml).
Assuming your username is `my-github-user`, you can then embed rendered metrics in your readme like below:
```markdown
<!-- If you're using "master" as default branch -->
![Metrics](https://github.com/my-github-user/my-github-user/blob/master/github-metrics.svg)
<!-- If you're using "main" as default branch -->
![Metrics](https://github.com/my-github-user/my-github-user/blob/main/github-metrics.svg)
```
<details>
<summary>💬 How to setup?</summary>
### 0. Setup your personal repository
Create a repository with the same name as your GitHub login (if it's not already done).
![Setup personal repository](.github/readme/imgs/setup_personal_repository.png)
Its `README.md` will be displayed on your user profile:
![GitHub Profile Example](.github/readme/imgs/example_github_profile.png)
### 1. Create a GitHub personal token
From the `Developer settings` of your account settings, select `Personal access tokens` to create a new token.
No additional scopes are needed for basic metrics, but you may have to grant additional scope depending on what features you're planning to use:
- `public_repo` scope for some plugins
- `read:org` scope for all organizations related metrics
- `repo` scope for all private repositories related metrics
![Setup a GitHub personal token](.github/readme/imgs/setup_personal_token.png)
A scope-less token can still display private contributions by enabling `Include private contributions on my profile` in your account settings:
![Enable "Include private contributions on my profile`"](.github/readme/imgs/setup_private_contributions.png)
If a plugin has not enough scopes to operate (and `plugins_errors_fatal` isn't enabled), it'll be reported in the rendering like below:
![Plugin error example](https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.error.svg)
### 2. Put your GitHub perosnal token in your repository secrets
Go to the `Settings` of your repository to create a new secret and paste your freshly generated GitHub token there.
![Setup a repository secret](.github/readme/imgs/setup_repository_secret.png)
### 3. Create a GitHub Action workflow in your repository
Create a new workflow from the `Actions` tab of your repository and paste the following:
```yaml
name: Metrics
on:
# Schedule updates (each hour)
schedule: [{cron: "0 * * * *"}]
# Lines below let you run workflow manually and on each commit (optional)
push: {branches: ["master", "main"]}
workflow_dispatch:
jobs:
github-metrics:
runs-on: ubuntu-latest
steps:
# See action.yml for all options
- uses: lowlighter/metrics@latest
with:
# Your GitHub token
token: ${{ secrets.METRICS_TOKEN }}
# GITHUB_TOKEN is a special auto-generated token restricted to current repository, which is used to push files in it
committer_token: ${{ secrets.GITHUB_TOKEN }}
```
See all supported options in [action.yml](action.yml).
Rendered metrics will be committed to your repository on each run.
![Action update example](.github/readme/imgs/example_action_update.png)
#### Choosing between `@latest`, `@master` or a fork
If you wish to use new features as they're being released, you can switch from `@latest` to `@master`.
As the latter is used as a development branch, jobs may fail from time to time (although we try to mitigate this).
When using a token with additional permissions, it is advised to fork this repository and use it instead to minimize security risks:
```yaml
- uses: my-github-username/metrics@master
```
In this case, please consider watching new releases to stay up-to-date and enjoy latest features!
`@latest` will be updated on each release soon after [Planned for next release](https://github.com/lowlighter/metrics/projects/1#column-12378679) is emptied. Metrics doesn't introduce breaking changes **from an user point of view** (i.e. your workflows will always be valid) so you can follow release cycles without worrying.
#### Examples workflows
Metrics displayed on this page are rendered from this [workflow](https://github.com/lowlighter/lowlighter/blob/master/.github/workflows/metrics.yml). You can check it for some code examples.
### 4. Embed link into your README.md
Update your README.md to embed your metrics:
```markdown
<!-- If you're using "master" as default branch -->
![Metrics](https://github.com/my-github-user/my-github-user/blob/master/github-metrics.svg)
<!-- If you're using "main" as default branch -->
![Metrics](https://github.com/my-github-user/my-github-user/blob/main/github-metrics.svg)
```
</details>

21
.github/readme/partials/setup/shared.md vendored Normal file
View File

@@ -0,0 +1,21 @@
## 💕 Using the shared instance (~1 min setup, but with limitations)
For convenience, you can use the shared instance available at [metrics.lecoq.io](https://metrics.lecoq.io) without any additional setup.
```markdown
![Metrics](https://metrics.lecoq.io/my-github-user)
```
This is mostly intended for previews, to enjoy all features consider using GitHub Action instead.
<details>
<summary>💬 Fair use</summary>
To ensure service availability, shared instance has a few limitations:
* Images are cached for 1 hour
* Rendered metrics **won't be updated** during this time window when queried
* You can manually update rendering againg your metrics on [metrics.lecoq.io](https://metrics.lecoq.io)
* There is a rate limiter enabled (it doesn't affect already cached metrics)
* Several plugins may not be available
</details>

140
.github/readme/partials/setup/web.md vendored Normal file
View File

@@ -0,0 +1,140 @@
## 🏗️ Deploying your own web instance (~15 min setup, depending on your sysadmin knowledge)
Setup a metrics instance on your server if you don't want to use GitHub Actions and [metrics.lecoq.io](https://metrics.lecoq.io).
See all supported options in [settings.example.json](settings.example.json).
Assuming your username is `my-github-user`, you can then embed rendered metrics in your readme like below:
```markdown
![Metrics](https://my-personal-domain.com/my-github-user)
```
<details>
<summary>💬 How to setup?</summary>
### 0. Prepare your server
You'll need a server with a recent version [NodeJS](https://nodejs.org) (see used version in [Dockerfile](Dockerfile#L1-L2)).
### 1. Create a GitHub personal token
From the `Developer settings` of your account settings, select `Personal access tokens` to create a new token.
No additional scopes are needed.
![Setup a GitHub personal token](.github/readme/imgs/setup_personal_token.png)
### 2. Install dependencies
Clone repository, install dependencies and copy configuration example to `settings.json`:
```shell
git clone https://github.com/lowlighter/metrics.git
cd metrics/
npm install --only=prod
cp settings.example.json settings.json
```
### 3. Configure your instance and start it
Edit `settings.json` to configure your instance.
```javascript
{
//GitHub API token
"token":"GITHUB_TOKEN",
//Other options...
}
```
See all supported options in [settings.example.json](settings.example.json).
If you plan to make your web instance public, it is advised to restrict its access thanks to rate limiter and access list.
Once you've finished configuring metrics, start your instance:
```shell
npm start
```
Access your server with provided port in `setting.json` from your browser to ensure everything is working.
### 4. Embed link into your README.md
Edit your repository readme and add your metrics image from your server domain:
```markdown
![Metrics](https://my-personal-domain.com/my-github-user)
```
### 6. (optional) Setup your instance as a service
To ensure that your instance will restart if it reboots or crashes, you should set it up as a service.
This is described below for Linux-like systems which support *systemd*.
Create a new service file `/etc/systemd/system/github_metrics.service` and paste the following after editing paths inside:
```ini
[Unit]
Description=Metrics
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
WorkingDirectory=/path/to/metrics
ExecStart=/usr/bin/node /path/to/metrics/index.mjs
[Install]
WantedBy=multi-user.target
```
Reload services, enable it, start it and check if it is up and running:
```shell
systemctl daemon-reload
systemctl enable github_metrics
systemctl start github_metrics
systemctl status github_metrics
```
</details>
<details>
<summary>⚠️ HTTP errors code</summary>
Following error codes may be encountered on web instance:
| Error code | Description |
| ------------------------- | -------------------------------------------------------------------------- |
| `400 Bad request` | Invalid query (e.g. unsupported template) |
| `403 Forbidden` | User not allowed in `restricted` users list |
| `404 Not found` | GitHub API did not found the requested user |
| `429 Too many requests` | Thrown when rate limiter is trigerred |
| `500 Internal error` | Server error while generating metrics images (check logs for more details) |
| `503 Service unavailable` | Maximum user capacity reached, only cached images can be accessed for now |
</details>
<details>
<summary>🔗 HTTP parameters</summary>
Most of options from [action.yml](action.yml) are actually supported by web instance, though syntax is slightly different.
All underscores (`_`) must be replaced by dots (`.`) and `plugin_` prefixes must be dropped.
For example, to configure pagespeed plugin you'd use the following:
```
https://my-personal-domain.com/my-github-user?pagespeed=1&pagespeed.detailed=1&pagespeed.url=https%3A%2F%2Fexample.com
```
Note that url parameters must be [encoded](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/encodeURIComponent).
As for `base` content, which is enabled by default, sections are available through "`base.<section>`".
For example, to display only `repositories` section, use:
```
https://my-personal-domain.com/my-github-user?base=0&base.repositories=1
```
</details>

5
.github/readme/partials/shared.md vendored Normal file
View File

@@ -0,0 +1,5 @@
## 🦑 Interested to get your own?
Try it now at [metrics.lecoq.io](https://metrics.lecoq.io/) with your GitHub username!
Some plugins are not are not available at [metrics.lecoq.io](https://metrics.lecoq.io/), for a fully-featured experience use it as a [GitHub Action](https://github.com/marketplace/actions/github-metrics-as-svg-image) instead!