Version 1.8 (#5)
This commit is contained in:
372
README.md
372
README.md
@@ -3,9 +3,7 @@
|
|||||||

|

|
||||||
|
|
||||||
Generates your own GitHub metrics as an SVG image to put them on your profile page or elsewhere !
|
Generates your own GitHub metrics as an SVG image to put them on your profile page or elsewhere !
|
||||||
|
|
||||||
See what it looks like below :
|
See what it looks like below :
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### 🦑 Interested to get your own ?
|
### 🦑 Interested to get your own ?
|
||||||
@@ -15,118 +13,109 @@ Try it now at [metrics.lecoq.io](https://metrics.lecoq.io/) with your GitHub use
|
|||||||
|
|
||||||
### ⚙️ Using GitHub Action on your profile repo (~5 min setup)
|
### ⚙️ Using GitHub Action on your profile repo (~5 min setup)
|
||||||
|
|
||||||
A GitHub Action which is run periodically at your convenience which generates and push an SVG image on your personal repository.
|
Setup a GitHub Action which is run periodically and push a generated SVG image on your repository.
|
||||||
|
|
||||||
Assuming your username is `my-github-user`, you can embed your metrics in your personal repository's readme like below :
|
Assuming your username is `my-github-user`, you can embed your metrics in your personal repository's readme like below :
|
||||||
```markdown
|
```markdown
|
||||||

|

|
||||||
```
|
```
|
||||||
|
|
||||||
Or with HTML :
|
|
||||||
```html
|
|
||||||
<img src="github-metrics.svg" alt="My GitHub metrics">
|
|
||||||
```
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>💬 How to setup ?</summary>
|
<summary>💬 How to setup ?</summary>
|
||||||
|
|
||||||
#### 0. Prepare your personal repository
|
#### 0. Prepare your personal repository
|
||||||
|
|
||||||
If you don't know yet or haven't done it yet, create a repository with the same name as your GitHub username.
|
If you don't know yet or haven't done it yet, create a repository with the same name as your GitHub username.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
The `README.md` of this repository will be displayed on your GitHub user profile like below !
|
The `README.md` of this repository will be displayed on your GitHub user profile like below :
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
#### 1. Create a GitHub token
|
#### 1. Setup a GitHub token
|
||||||
|
|
||||||
In your account settings, go to `Developer settings` and select `Personal access tokens` to create a new token.
|
Go to `Developer settings` from your GitHub account settings and select `Personal access tokens` to create a new token.
|
||||||
|
|
||||||
You'll need to create a token with the `public_repo` right so this GitHub Action has enough permissions to push the updated SVG metrics on your personal repository.
|
You'll need to create a token with the `public_repo` right so this GitHub Action has enough permissions to push the updated SVG metrics on your personal repository.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
If you choose to use a bot account, you can put `public_repo` rights to the bot token and invite it as a collaborator on your personal profile repository so it has push access. This way, you can use a personnal token with no rights instead and reduce security issues.
|
||||||
|
|
||||||
#### 2. Put your GitHub token in your personal repository secrets
|
#### 2. Put your GitHub token in your personal repository secrets
|
||||||
|
|
||||||
Go to the `Settings` of your personal repository to create a new secret and paste your GitHub token here with the name `METRICS_TOKEN`.
|
Go to the `Settings` of your personal repository to create a new secret and paste your GitHub token here.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
#### 3. Create a new GitHub Action workflow on your personal repo
|
#### 3. Create a new GitHub Action workflow on your personal repo
|
||||||
|
|
||||||
Go to the `Actions` of your personal repository and create a new workflow.
|
Create a new workflow from the `Actions` tab of your personal repository and paste the following.
|
||||||
|
Don't forget to put your GitHub username !
|
||||||
|
|
||||||
Paste the following and don't forget to put your GitHub username.
|
|
||||||
```yaml
|
```yaml
|
||||||
name: GitHub metrics as SVG image
|
name: GitHub metrics as SVG image
|
||||||
on:
|
on:
|
||||||
# Update metrics each 15 minutes. Edit this if you want to increase/decrease frequency
|
# Schedule the metrics update
|
||||||
# Note that GitHub image cache (5-15 minutes) still apply so it is useless to set less than this, you're image won't be refreshed
|
|
||||||
schedule: [{cron: "*/15 * * * *"}]
|
schedule: [{cron: "*/15 * * * *"}]
|
||||||
# Add this if you want to force update each time you commit on master branch
|
# (optional) Force update a commit occurs on master branch
|
||||||
push: {branches: "master"}
|
push: {branches: "master"}
|
||||||
jobs:
|
jobs:
|
||||||
github-metrics:
|
github-metrics:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: lowlighter/metrics@latest
|
- uses: lowlighter/metrics@latest
|
||||||
# This line will prevent this GitHub action from running when it is updated by itself if you enabled trigger on master branch
|
|
||||||
if: "!contains(github.event.head_commit.message, '[Skip GitHub Action]')"
|
|
||||||
with:
|
with:
|
||||||
|
|
||||||
# Your GitHub token ("public_repo" is required to allow this action to update the metrics SVG image)
|
# Your GitHub token
|
||||||
token: ${{ secrets.METRICS_TOKEN }}
|
token: ${{ secrets.METRICS_TOKEN }}
|
||||||
|
|
||||||
# Your GitHub user name
|
|
||||||
user: my-github-user
|
|
||||||
|
|
||||||
# Additional options
|
# Additional options
|
||||||
# ==========================================
|
# ==========================================
|
||||||
|
|
||||||
# The GitHub token used to commit to your repository (defaults to the same value as "token")
|
# GitHub username (defaults to "token" user)
|
||||||
# This can be used to specify the token of a bot account if you use a personal token with advanced permissions
|
user: my-github-user
|
||||||
# (which is needed if you want to include metrics of your private repositories, or to enable plugins like traffic)
|
|
||||||
|
# If provided, this token will be used instead of "token" for commit operations
|
||||||
|
# You can specify a bot account to avoid virtually increasing your stats due to this action commits
|
||||||
committer_token: ${{ secrets.METRICS_BOT_TOKEN }}
|
committer_token: ${{ secrets.METRICS_BOT_TOKEN }}
|
||||||
|
|
||||||
# Path/filename to use to store generated SVG
|
# Name of SVG image output
|
||||||
filename: github-metrics.svg
|
filename: github-metrics.svg
|
||||||
|
|
||||||
# If you own a website and you added it to your GitHub profile,
|
# Enable Google PageSpeed metrics for account attached website
|
||||||
# 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 for more informations
|
||||||
# See https://developers.google.com/speed/docs/insights/v5/get-started to obtain a key
|
|
||||||
plugin_pagespeed: no
|
plugin_pagespeed: no
|
||||||
pagespeed_token: ${{ secrets.PAGESPEED_TOKEN }}
|
pagespeed_token: ${{ secrets.PAGESPEED_TOKEN }}
|
||||||
|
|
||||||
# Enable repositories lines added/removed count
|
# Enable lines of code metrics
|
||||||
plugin_lines: no
|
plugin_lines: no
|
||||||
|
|
||||||
# Enable repositories traffic (pages views) count
|
# Enable repositories traffic metrics
|
||||||
# The provided GitHub token will require "repo" permissions
|
# *Provided GitHub token require full "repo" permissions
|
||||||
plugin_traffic: no
|
plugin_traffic: no
|
||||||
|
|
||||||
# Enable or disable coding habits metrics
|
# Enable coding habits metrics
|
||||||
plugin_habits: no
|
plugin_habits: no
|
||||||
|
|
||||||
|
# Skip commits flagged with [Skip GitHub Action] from commits count
|
||||||
|
plugin_selfskip: no
|
||||||
|
|
||||||
# Enable debug logs
|
# Enable debug logs
|
||||||
debug: no
|
debug: no
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On each run, a new SVG image will be generated and committed to your repository.
|
A new SVG image will be generated and committed to your repository on each run.
|
||||||
|
Because of this, the amount of your commits could be virtually increased which is probably unwanted.
|
||||||
|
|
||||||
This could virtually increase your commits stats, so it is recommended to pass a bot account token to `token` instead.
|
To avoid this, you can use a bot token instead, which will still be able to track metrics of all your public repositories.
|
||||||
The bot will be able to track metrics of all your public repositories.
|
If you want to also track your private repositories metrics, you'll need to pass a personal token with full `repo` permissions to your personal `token`, and use the `committer_token` parameter to pass the bot account token.
|
||||||
|
|
||||||
If you want to also track your private repositories metrics, you'll need to pass a personal token with `repo` permissions to `token`, and use the `committer_token` parameter to pass the bot account token.
|
If you don't want to use a bot token, you can use the `plugin_selfskip` which will count out all your commits from your personal repository tagged with `[Skip GitHub Action]` made with your account, but these commits will still be linked to your account.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
#### 4. Embed the link into your README.md
|
#### 4. Embed the link into your README.md
|
||||||
|
|
||||||
Edit your README.md on your repository and link it your image :
|
Edit your README.md on your repository and link it your image :
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||

|

|
||||||
```
|
```
|
||||||
@@ -135,7 +124,7 @@ Edit your README.md on your repository and link it your image :
|
|||||||
|
|
||||||
### 💕 Using the shared instance (~1 min setup, but with limitations)
|
### 💕 Using the shared instance (~1 min setup, but with limitations)
|
||||||
|
|
||||||
For conveniency, you can use the shared instance available at [metrics.lecoq.io](https://metrics.lecoq.io).
|
For conveniency, you can use the shared instance available at [metrics.lecoq.io](https://metrics.lecoq.io) without any additional setup.
|
||||||
|
|
||||||
Assuming your username is `my-github-user`, you can embed your metrics in your personal repository's readme like below :
|
Assuming your username is `my-github-user`, you can embed your metrics in your personal repository's readme like below :
|
||||||
```markdown
|
```markdown
|
||||||
@@ -145,147 +134,116 @@ Assuming your username is `my-github-user`, you can embed your metrics in your p
|
|||||||
<details>
|
<details>
|
||||||
<summary>💬 Restrictions and fair use</summary>
|
<summary>💬 Restrictions and fair use</summary>
|
||||||
|
|
||||||
Since GitHub API has rate limitations and to avoid abuse, the shared instance has the following limitations :
|
Since GitHub API has rate limitations, the shared instance has a few limitations :
|
||||||
* Images are cached for 1 hour
|
* Images are cached for 1 hour
|
||||||
* Your generated metrics **won't** be updated during this amount of time
|
* Your generated metrics won't be updated during this amount of time
|
||||||
* If you enable or disable plugins in url parameters, you'll need to wait for cache expiration before these changes are applied
|
* If you enable or disable plugins in url parameters, you'll need to wait for cache expiration before these changes are applied
|
||||||
* A rate limiter prevents new metrics generation when reached, but it **does not** affect already cached users metrics, including your own
|
* The rate limiter is enabled, although it won't affect already cached users metrics
|
||||||
* Most of plugins are not available
|
* Plugins are disabled
|
||||||
* PageSpeed plugin can be enabled by passing `?pagespeed=1`, but metrics generation can take up some time
|
* PageSpeed plugin can still be enabled by passing `?pagespeed=1`, but metrics generation can take up some time when it has not been cached yet
|
||||||
|
|
||||||
You should consider deploying your own instance or use GitHub Action if you're planning using this service.
|
To ensure maximum availability, consider deploying your own instance or use the GitHub Action.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### 🏗️ Deploying your own instance (~15 min setup, depending on your sysadmin knowledge)
|
### 🏗️ Deploying your own instance (~15 min setup, depending on your sysadmin knowledge)
|
||||||
|
|
||||||
Using your own instance is useful if you do not want to use GitHub Action or allow others users to use your instance.
|
You can setup your own instance if you choose to not use the GitHub Action or you want to allow others users to use your instance.
|
||||||
|
|
||||||
A GitHub token is required to setup your instance, however since metrics images are not stored on your repositories you do not need to grant any additional permissions to your token, which reduce security issues.
|
You'll need to create a GitHub token to setup it, however you do not need to grant any additional permissions to your token since it won't push images to any of your repositories. You may still require additional rights for some plugins if you decide to enable them though.
|
||||||
|
|
||||||
You can restrict which users can generate metrics on your server and apply rate limiting (which is advised or else you'll hit the GitHub API rate limiter).
|
|
||||||
|
|
||||||
It is also easier to change `query.graphql`, `style.css` and `template.svg` if you want to gather additional stats, perform esthetical changes or edit the structure of the SVG image.
|
|
||||||
|
|
||||||
|
If you intend to share your instance, it is advised to setup either an access list to restrict which users can use it, or to configure the rate limiter to avoid reaching the requests limit of GitHub API.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>💬 How to setup ?</summary>
|
<summary>💬 How to setup ?</summary>
|
||||||
|
|
||||||
#### 0. Prepare your server
|
#### 0. Prepare your server
|
||||||
|
|
||||||
You'll need to have a server at your disposal where you can install and configure stuff.
|
You'll need a server where you can install and configure apps.
|
||||||
|
|
||||||
#### 1. Create a GitHub token
|
#### 1. Create a GitHub token
|
||||||
|
|
||||||
In your account settings, go to `Developer settings` and select `Personal access tokens` to create a new token.
|
In your account settings, go to `Developer settings` and select `Personal access tokens` to create a new token.
|
||||||
|
As explained above, you do not need to grant additional permissions to the token unless you want to enable additional plugins.
|
||||||
As explained above, you do not need to grant additional permissions to the token.
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
#### 2. Install the dependancies
|
#### 2. Install the dependancies
|
||||||
|
|
||||||
Connect to your server.
|
Connect to your server and ensure [NodeJS](https://nodejs.org/en/) is installed (see tested versions in the [build workflows](https://github.com/lowlighter/metrics/blob/master/.github/workflows/build.yml)).
|
||||||
|
|
||||||
You'll need [NodeJS](https://nodejs.org/en/) (the latter version is better, for reference this was tested on v14.9.0).
|
|
||||||
|
|
||||||
Clone the repository
|
|
||||||
|
|
||||||
|
Then run the following commands :
|
||||||
```shell
|
```shell
|
||||||
|
# Clone this repository (or your fork)
|
||||||
git clone https://github.com/lowlighter/metrics.git
|
git clone https://github.com/lowlighter/metrics.git
|
||||||
```
|
# Install dependancies
|
||||||
|
|
||||||
Go inside project and install dependancies :
|
|
||||||
```shell
|
|
||||||
cd metrics/
|
cd metrics/
|
||||||
npm install --only=prod
|
npm install --only=prod
|
||||||
```
|
# Copy the settings exemple
|
||||||
|
|
||||||
Copy `settings.example.json` to `settings.json`
|
|
||||||
```shell
|
|
||||||
cp settings.example.json settings.json
|
cp settings.example.json settings.json
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 3. Configure your instance
|
#### 3. Configure your instance
|
||||||
|
|
||||||
Open and edit `settings.json` to configure your instance.
|
Open and edit `settings.json` to configure your instance using a text editor of your choice.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
{
|
{
|
||||||
//Your GitHub API token
|
//GitHub API token
|
||||||
"token":"****************************************",
|
"token":"****************************************",
|
||||||
|
|
||||||
//The optionals parameters below allows you to avoid reaching the GitHub API rate limitation
|
//Users who are authorized to generate metrics on your instance
|
||||||
|
//An empty list or an undefined value will be treated as "unrestricted"
|
||||||
|
"restricted":["my-github-user"],
|
||||||
|
|
||||||
//A set of whitelisted users which can generate metrics on your instance
|
//Lifetime of generated metrics (cached version will be served instead during this time window)
|
||||||
//Leave empty or undefined to disable
|
"cached":3600000,
|
||||||
//Defaults to unrestricted
|
|
||||||
"restricted":["my-github-user"],
|
|
||||||
|
|
||||||
//Lifetime of each generated metrics
|
//Number of simultaneous users who can use your instance before sending a "503 error"
|
||||||
//If an user's metrics are requested while lifetime is still up, a cached version will be served
|
//A zero or an undefined value will be treated as "unlimited"
|
||||||
//Defaults to 60 minutes
|
"maxusers":0,
|
||||||
"cached":3600000,
|
|
||||||
|
|
||||||
//Maximum simultaneous number of user which can be cached
|
//Rate limiter (see https://www.npmjs.com/package/express-rate-limit)
|
||||||
//When this limit is reached, new users will receive a 503 error
|
//A null or undefined value will be treated as "disabled"
|
||||||
//Defaults to 0 (unlimited)
|
"ratelimiter":{
|
||||||
"maxusers":0,
|
"windowMs":60000,
|
||||||
|
"max":100
|
||||||
|
},
|
||||||
|
|
||||||
//Rate limiter
|
//Listening port used by your instance
|
||||||
//See https://www.npmjs.com/package/express-rate-limit
|
|
||||||
//Disabled by default
|
|
||||||
"ratelimiter":{
|
|
||||||
"windowMs":60000,
|
|
||||||
"max":100
|
|
||||||
},
|
|
||||||
|
|
||||||
//Port on which your instance listen
|
|
||||||
//Defaults to 3000
|
|
||||||
"port":3000,
|
"port":3000,
|
||||||
|
|
||||||
|
//Optimize SVG image
|
||||||
|
"optimize":true,
|
||||||
|
|
||||||
//Debug mode
|
//Debug mode
|
||||||
//When enabled, "query.graphql", "style.css" and "template.svg" will be reloaded at each request
|
//When enabled, templates will be reloaded at each request and cache will be disabled
|
||||||
//Cache will be disabled
|
//Intended for easier development and disabled by default
|
||||||
//This is intendend for easier development which allows to see your changes quickly
|
|
||||||
//Defaults to false
|
|
||||||
"debug":false,
|
"debug":false,
|
||||||
|
|
||||||
//Plugins configuration
|
//Plugins configuration
|
||||||
//Most of plugins are disabled by default
|
|
||||||
//Enabling them can add additional informations and metrics about you, but increases response time
|
|
||||||
"plugins":{
|
"plugins":{
|
||||||
//Pagespeed plugin
|
//Google PageSpeed plugin
|
||||||
"pagespeed":{
|
"pagespeed":{
|
||||||
//Enable or disable this plugin
|
//Enable or disable this plugin. Pass "?pagespeed=1" in url to generate website's performances
|
||||||
//When enabled, pass "?pagespeed=1" in url to generate website's performances
|
|
||||||
"enabled":false,
|
"enabled":false,
|
||||||
//Pagespeed token
|
//Pagespeed token (see https://developers.google.com/speed/docs/insights/v5/get-started)
|
||||||
//See https://developers.google.com/speed/docs/insights/v5/get-started to obtain a key
|
|
||||||
"token":"****************************************"
|
"token":"****************************************"
|
||||||
},
|
},
|
||||||
//Lines plugin
|
//Lines plugin
|
||||||
"lines":{
|
"lines":{
|
||||||
//Enable or disable this plugin
|
//Enable or disable this plugin. Pass "?lines=1" in url to compute total lines you added/removed on your repositories
|
||||||
//When enabled, pass "?lines=1" in url to compute total lines added/removed in your repositories by you
|
|
||||||
"enabled":true
|
"enabled":true
|
||||||
},
|
},
|
||||||
//Traffic plugin
|
//Traffic plugin
|
||||||
"traffic":{
|
"traffic":{
|
||||||
//Enable or disable this plugin
|
//Enable or disable this plugin. Pass "?traffic=1" in url to compute page views on your repositories in last two weeks
|
||||||
//When enabled, pass "?traffic=1" in url to compute total page views in your repositories in last two weeks
|
//*This requires a GitHub API token with push access
|
||||||
//Note that this requires that the passed GitHub API token requires a push access
|
|
||||||
"enabled":true
|
"enabled":true
|
||||||
},
|
},
|
||||||
//Habits plugin
|
//Habits plugin
|
||||||
"habits":{
|
"habits":{
|
||||||
//Enable or disable this plugin
|
//Enable or disable this plugin. Pass "?habits=1" in url to generate coding habits based on your recent activity
|
||||||
//When enabled, pass "?habits=1" in url to generate coding habits based on your recent activity
|
|
||||||
//This includes stuff like if you're using tabs or space and the time of the day when you push the most
|
|
||||||
//Note that this requires that the passed GitHub API token requires a push access
|
|
||||||
"enabled":true,
|
"enabled":true,
|
||||||
//Specify the number of events used to compute coding habits. Capped at 100 by GitHub API
|
//Number of events used to compute coding habits (capped at 100 by GitHub API)
|
||||||
//Defaults to 50
|
|
||||||
"from":50,
|
"from":50,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -294,24 +252,28 @@ Open and edit `settings.json` to configure your instance.
|
|||||||
|
|
||||||
#### 4. Start your instance
|
#### 4. Start your instance
|
||||||
|
|
||||||
Run the following command to start your instance :
|
Start your instance once you've finished configuring it :
|
||||||
```shell
|
```shell
|
||||||
npm start
|
npm start
|
||||||
```
|
```
|
||||||
|
|
||||||
Open your browser and test your instance :
|
And you should be able to access it on the port you provided !
|
||||||
```shell
|
|
||||||
http://localhost:3000/my-github-user
|
#### 5. Embed the link into your README.md
|
||||||
|
|
||||||
|
Edit your `README.md` on your repository and include your metrics from your server domain :
|
||||||
|
```markdown
|
||||||
|

|
||||||
```
|
```
|
||||||
|
|
||||||
#### 5. Setup as service on your instance (optional)
|
#### 6. (optional) Setup as service on your instance
|
||||||
|
|
||||||
You should consider using a service to run your instance.
|
If you want to ensure that your instance will be restarted after reboots or crashes, you should setup it as a service.
|
||||||
It will allow to restart automatically on crash and on boot.
|
This is described below for linux-like systems with *systemd*.
|
||||||
|
|
||||||
Create a new file in `/etc/systemd/system` :
|
Create a new service file in `/etc/systemd/system` :
|
||||||
```shell
|
```shell
|
||||||
vi /etc/systemd/system/github_metrics.service
|
nano /etc/systemd/system/github_metrics.service
|
||||||
```
|
```
|
||||||
|
|
||||||
Paste the following and edit it with the correct paths :
|
Paste the following and edit it with the correct paths :
|
||||||
@@ -330,34 +292,21 @@ ExecStart=/usr/bin/node /path/to/metrics/index.mjs
|
|||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
```
|
```
|
||||||
|
|
||||||
Reload services, enable it and start it :
|
Reload services, enable it, start it and check it is up and running :
|
||||||
```shell
|
```shell
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl enable github_metrics
|
systemctl enable github_metrics
|
||||||
systemctl start github_metrics
|
systemctl start github_metrics
|
||||||
```
|
|
||||||
|
|
||||||
Check if your service is up and running :
|
|
||||||
```shell
|
|
||||||
systemctl status github_metrics
|
systemctl status github_metrics
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 6. Embed the link into your README.md
|
|
||||||
|
|
||||||
Edit your README.md on your repository and link it your image :
|
|
||||||
|
|
||||||
```markdown
|
|
||||||

|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>⚠️ HTTP errors code</summary>
|
<summary>⚠️ HTTP errors code</summary>
|
||||||
|
|
||||||
The following errors code can be encountered if your using a server instance :
|
The following errors code can be encountered if on a server instance :
|
||||||
|
* `403 Forbidden` : User is not allowed in `restricted` users list
|
||||||
* `403 Forbidden` : User is not whitelisted in `restricted` users list
|
|
||||||
* `404 Not found` : GitHub API did not found the requested user
|
* `404 Not found` : GitHub API did not found the requested user
|
||||||
* `429 Too many requests` : Thrown when rate limiter is trigerred
|
* `429 Too many requests` : Thrown when rate limiter is trigerred
|
||||||
* `500 Internal error` : An error ocurred while generating metrics images (logs can be seen if you're the owner of the instance)
|
* `500 Internal error` : An error ocurred while generating metrics images (logs can be seen if you're the owner of the instance)
|
||||||
@@ -369,30 +318,27 @@ The following errors code can be encountered if your using a server instance :
|
|||||||
|
|
||||||
### 🧩 Plugins
|
### 🧩 Plugins
|
||||||
|
|
||||||
Plugins are additional features that are disabled by default and which may requires additional configuration.
|
Plugins are features which are disabled by default but they can provide additional metrics.
|
||||||
|
In return they may require additional configuration and tend to consume additional API requests.
|
||||||
|
|
||||||
These can provide more informations into your generated metrics, but it could also make it longer to generate, which may not be suitable with a server instance if you're not using caching.
|
#### ⏱️ PageSpeed
|
||||||
|
|
||||||
#### ⏱️ Pagespeed
|
|
||||||
|
|
||||||
The *pagespeed* plugin allows you to add your website performances.
|
|
||||||
|
|
||||||
|
The *pagespeed* plugin allows you to add the performances of the website attached to the GitHub user account :
|
||||||

|

|
||||||
|
|
||||||
These are computed through [Google's pagespeed API](https://developers.google.com/speed/docs/insights/v5/get-started), which returns the same results as [web.dev](https://web.dev).
|
These are computed through [Google's PageSpeed API](https://developers.google.com/speed/docs/insights/v5/get-started), which returns the same results as [web.dev](https://web.dev).
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>💬 About</summary>
|
<summary>💬 About</summary>
|
||||||
|
|
||||||
To setup this plugin, you'll need an API key that you can generate in the [pagespeed API presentation](https://developers.google.com/speed/docs/insights/v5/get-started).
|
This plugin may require an API key that you can generate [here](https://developers.google.com/speed/docs/insights/v5/get-started) although it does not seem mandatory. It is still advised to provide it to avoid 429 HTTP errors.
|
||||||
|
|
||||||
The website attached to your GitHub profile will be the one to be audited.
|
The website attached to the GitHub profile will be the one to be audited.
|
||||||
It will take about 10 to 15 seconds to generate the results, so it is advised to use this plugin alongside caching system or for automated image generation.
|
Expect 10 to 30 seconds to generate the results.
|
||||||
|
|
||||||
##### Setup with GitHub actions
|
##### Setup with GitHub actions
|
||||||
|
|
||||||
Add the following to your workflow :
|
Add the following to your workflow :
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: lowlighter/metrics@latest
|
- uses: lowlighter/metrics@latest
|
||||||
with:
|
with:
|
||||||
@@ -403,8 +349,7 @@ Add the following to your workflow :
|
|||||||
|
|
||||||
##### Setup in your own instance
|
##### Setup in your own instance
|
||||||
|
|
||||||
Add the following to your `settings.json`
|
Add the following to your `settings.json` and pass `?pagespeed=1` in url when generating metrics.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"plugins":{
|
"plugins":{
|
||||||
"pagespeed":{
|
"pagespeed":{
|
||||||
@@ -414,14 +359,11 @@ Add the following to your `settings.json`
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
And pass `?pagespeed=1` in url when generating metrics.
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
#### 👨💻 Lines
|
#### 👨💻 Lines
|
||||||
|
|
||||||
The *lines* plugin allows you to add the number of lines of code you added and removed across your repositories.
|
The *lines* of code plugin allows you to compute the number of lines of code you added and removed across all of your repositories.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
@@ -432,7 +374,6 @@ It will consume an additional GitHub request per repository.
|
|||||||
##### Setup with GitHub actions
|
##### Setup with GitHub actions
|
||||||
|
|
||||||
Add the following to your workflow :
|
Add the following to your workflow :
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: lowlighter/metrics@latest
|
- uses: lowlighter/metrics@latest
|
||||||
with:
|
with:
|
||||||
@@ -442,8 +383,7 @@ Add the following to your workflow :
|
|||||||
|
|
||||||
##### Setup in your own instance
|
##### Setup in your own instance
|
||||||
|
|
||||||
Add the following to your `settings.json`
|
Add the following to your `settings.json` and pass `?lines=1` in url when generating metrics.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"plugins":{
|
"plugins":{
|
||||||
"lines":{
|
"lines":{
|
||||||
@@ -452,14 +392,11 @@ Add the following to your `settings.json`
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
And pass `?lines=1` in url when generating metrics.
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
#### 🧮 Traffic
|
#### 🧮 Traffic
|
||||||
|
|
||||||
The *traffic* plugin allows you to add the number of pages views across your repositories.
|
The repositories *traffic* plugin allows you to compute the number of pages views across your repositories.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
@@ -467,27 +404,25 @@ The *traffic* plugin allows you to add the number of pages views across your rep
|
|||||||
|
|
||||||
It will consume an additional GitHub request per repository.
|
It will consume an additional GitHub request per repository.
|
||||||
|
|
||||||
Due to GitHub Rest API limitation, the GitHub token you provide will requires "repo" permissions instead of "public_repo" to allow this plugin accessing traffic informations.
|
Because of GitHub REST API limitation, the provided token will require full `repo` permissions to access traffic informations.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
##### Setup with GitHub actions
|
##### Setup with GitHub actions
|
||||||
|
|
||||||
Add the following to your workflow :
|
Add the following to your workflow :
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: lowlighter/metrics@latest
|
- uses: lowlighter/metrics@latest
|
||||||
with:
|
with:
|
||||||
# ... other options
|
# ... other options
|
||||||
token: ${{ secrets.METRICS_TOKEN }} # Remember, this must have "repo" permissions for this plugin to work !
|
token: ${{ secrets.METRICS_TOKEN }}
|
||||||
plugin_traffic: yes
|
plugin_traffic: yes
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Setup in your own instance
|
##### Setup in your own instance
|
||||||
|
|
||||||
Add the following to your `settings.json`
|
Add the following to your `settings.json` and pass `?traffic=1` in url when generating metrics.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
"token":"****************************************",
|
||||||
"plugins":{
|
"plugins":{
|
||||||
"traffic":{
|
"traffic":{
|
||||||
"enabled":true,
|
"enabled":true,
|
||||||
@@ -495,14 +430,11 @@ Add the following to your `settings.json`
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
And pass `?traffic=1` in url when generating metrics.
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
#### 💡 Habits
|
#### 💡 Habits
|
||||||
|
|
||||||
The *habits* plugin allows you to add deduced coding about based on your recent activity.
|
The coding *habits* plugin allows you to add deduced coding about based on your recent activity, from up to 100 events.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
@@ -510,10 +442,12 @@ The *habits* plugin allows you to add deduced coding about based on your recent
|
|||||||
|
|
||||||
It will consume an additional GitHub request per event fetched.
|
It will consume an additional GitHub request per event fetched.
|
||||||
|
|
||||||
|
Because of GitHub REST API limitation, the provided token will require full `repo` permissions to access **private** events.
|
||||||
|
By default, events that cannot be fetched will be ignored so you can still use this plugin with a public token.
|
||||||
|
|
||||||
##### Setup with GitHub actions
|
##### Setup with GitHub actions
|
||||||
|
|
||||||
Add the following to your workflow :
|
Add the following to your workflow :
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: lowlighter/metrics@latest
|
- uses: lowlighter/metrics@latest
|
||||||
with:
|
with:
|
||||||
@@ -523,8 +457,7 @@ Add the following to your workflow :
|
|||||||
|
|
||||||
##### Setup in your own instance
|
##### Setup in your own instance
|
||||||
|
|
||||||
Add the following to your `settings.json`
|
Add the following to your `settings.json` and pass `?habits=1` in url when generating metrics.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"plugins":{
|
"plugins":{
|
||||||
"habits":{
|
"habits":{
|
||||||
@@ -533,35 +466,62 @@ Add the following to your `settings.json`
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
And pass `?habits=1` in url when generating metrics.
|
</details>
|
||||||
|
|
||||||
|
#### ⏭️ Selfskip
|
||||||
|
|
||||||
|
The *selfskip* plugin allows you to count out all commits tagged with `[Skip GitHub Action]` you authored on your personal repository from your reported commit counts.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>💬 About</summary>
|
||||||
|
|
||||||
|
It will consume an additional GitHub request per page fetched of your commit activity from your personal repository.
|
||||||
|
|
||||||
|
##### Setup with GitHub actions
|
||||||
|
|
||||||
|
Add the following to your workflow :
|
||||||
|
```yaml
|
||||||
|
- uses: lowlighter/metrics@latest
|
||||||
|
with:
|
||||||
|
# ... other options
|
||||||
|
plugin_selfskip: yes
|
||||||
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### 🗂️ Project structure
|
### 🗂️ Project structure
|
||||||
|
|
||||||
* `index.mjs` contains the entry points and the settings instance
|
#### Metrics generator
|
||||||
* `src/app.mjs` contains the server code which serves renders and apply rate limiting, restrictions, etc.
|
|
||||||
* `src/metrics.mjs` contains metrics renderer
|
* `src/metrics.mjs` contains the metrics renderer
|
||||||
* `src/query.graphql` is the GraphQL query which is sent to GitHub API
|
* `src/query.graphql` is the GraphQL query sent to GitHub GraphQL API
|
||||||
* `src/style.css` contains the style for the generated svg image metrics
|
* `src/style.css` contains the style used by the generated SVG image
|
||||||
* `src/template.svg` contains the structure of the generated svg image metrics
|
* `src/template.svg` contains the template used by the generated SVG image
|
||||||
* `src/plugins/*` contains various additional plugins which can add additional informations in generated metrics
|
* `src/plugins/*` contains the source code of metrics plugins
|
||||||
|
|
||||||
|
#### Metrics server instance
|
||||||
|
|
||||||
|
* `index.mjs` contains the metrics server entry point
|
||||||
|
* `src/app.mjs` contains the metrics server code which serves, renders, restricts/rate limit, etc.
|
||||||
|
|
||||||
|
#### GitHub action
|
||||||
|
|
||||||
* `action/index.mjs` contains the GitHub action code
|
* `action/index.mjs` contains the GitHub action code
|
||||||
* `action/dist/index.js` contains compiled the GitHub action code
|
* `action/dist/index.js` contains compiled the GitHub action code
|
||||||
* `utils/*` contains various utilitaries for build
|
* `utils/build.mjs` contains the GitHub action builder
|
||||||
|
|
||||||
### 💪 Contributing
|
### 💪 Contributing and customizing
|
||||||
|
|
||||||
If you would like to suggest a new feature or find a bug, you can fill an [issue](https://github.com/lowlighter/metrics/issues) describing your problem.
|
If you would like to suggest a new feature, find a bug or need help, you can fill an [issue](https://github.com/lowlighter/metrics/issues) describing your problem.
|
||||||
|
|
||||||
If you're motivated enough, you can submit a [pull request](https://github.com/lowlighter/metrics/pulls) to integrate new features or to solve open issues.
|
If you're motivated enough, you can submit a [pull request](https://github.com/lowlighter/metrics/pulls) to integrate new features or to solve open issues.
|
||||||
|
|
||||||
Read the few sections below to get started with project structure.
|
Read the few sections below to get started with project structure.
|
||||||
|
|
||||||
#### Adding new metrics through GraphQL API, REST API or Third-Party service
|
#### Adding new metrics through GraphQL API, REST API or Third-Party service
|
||||||
|
|
||||||
If you want to gather additional metrics, update the GraphQL query from `src/query.graphql` to get additional data from [GitHub GraphQL API](https://docs.github.com/en/graphql).
|
To use [GitHub GraphQL API](https://docs.github.com/en/graphql), update the GraphQL query from `src/query.graphql`.
|
||||||
Add additional computations and formatting in `src/metrics.mjs`.
|
Raw queried data should be exposed in `data.user` whereas computed data should be in `data.computed`, and code should be updated through `src/metrics.mjs`.
|
||||||
Raw queried data should be exposed in `data.user` whereas computed data should be in `data.computed`.
|
|
||||||
|
|
||||||
To use [GitHub Rest API](https://docs.github.com/en/rest) or a third-party service instead, create a new plugin in `src/plugins`.
|
To use [GitHub Rest API](https://docs.github.com/en/rest) or a third-party service instead, create a new plugin in `src/plugins`.
|
||||||
Plugins should be self-sufficient and re-exported from [src/plugins/index.mjs](https://github.com/lowlighter/metrics/blob/master/src/plugins/index.mjs), to be later included in the `//Plugins` section of `src/metrics.mjs`.
|
Plugins should be self-sufficient and re-exported from [src/plugins/index.mjs](https://github.com/lowlighter/metrics/blob/master/src/plugins/index.mjs), to be later included in the `//Plugins` section of `src/metrics.mjs`.
|
||||||
@@ -573,34 +533,30 @@ The SVG template is located in `src/template.svg` and include the CSS from `src/
|
|||||||
|
|
||||||
It's actually a long JavaScript template string, so you can actually include variables (e.g. `` `${data.user.name}` ``) and execute inline code, like ternary conditions (e.g. `` `${computed.plugins.plugin ? `<div>${computed.plugins.plugin.data}</div>` : ""}` ``) which are useful for conditional statements.
|
It's actually a long JavaScript template string, so you can actually include variables (e.g. `` `${data.user.name}` ``) and execute inline code, like ternary conditions (e.g. `` `${computed.plugins.plugin ? `<div>${computed.plugins.plugin.data}</div>` : ""}` ``) which are useful for conditional statements.
|
||||||
|
|
||||||
#### Server and GitHub action editions
|
#### Metrics server and GitHub action
|
||||||
|
|
||||||
Most of the time, you won't need to edit these, unless you're integrating features directly tied to them.
|
Most of the time, you won't need to edit these, unless you're integrating features directly tied to them.
|
||||||
|
Remember that SVG image is actually generated from `src/metrics.mjs`, independently from metrics server and GitHub action.
|
||||||
|
|
||||||
Server code is located in `src/app.mjs` and instantiates an `express` server app, `octokit`s instances, middlewares (like rate-limiter) and routes.
|
Metrics server code is located in `src/app.mjs` and instantiates an `express` server app, `octokit`s instances, middlewares (like rate-limiter) and routes.
|
||||||
|
|
||||||
GitHub action code is located in `action/index.mjs` and instantiates `octokit`s instances and retrieves action parameters.
|
GitHub action code is located in `action/index.mjs` and instantiates `octokit`s instances and retrieves action parameters.
|
||||||
It then use directly `src/metrics.mjs` to generate the SVG image and commit them to user's repository.
|
It then use directly `src/metrics.mjs` to generate the SVG image and commit them to user's repository.
|
||||||
|
You must run `npm run build` to rebuild the GitHub action.
|
||||||
|
|
||||||
#### Testing new features
|
#### Testing new features
|
||||||
|
|
||||||
To test new features, you'll need to follow the first steps of the `Deploying your own instance` tutorial.
|
To test new features, setup a metrics server with a test token and `debug` mode enabled.
|
||||||
Basically you create a `settings.json` containing a test token and `debug` mode enabled.
|
This way you'll be able to rapidly test SVG renders with your browser.
|
||||||
|
|
||||||
You can then start the node with `npm start` and you'll be able to test how the SVG renders with your editions by opening the server url in your browser.
|
|
||||||
|
|
||||||
### 📖 Useful references
|
### 📖 Useful references
|
||||||
|
|
||||||
Below is a list of useful 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)
|
* [GitHub Rest API](https://docs.github.com/en/rest)
|
||||||
|
|
||||||
### 📦 Used packages
|
### 📦 Used packages
|
||||||
|
|
||||||
Below is a list of primary dependencies :
|
|
||||||
|
|
||||||
* [express/express.js](https://github.com/expressjs/express) and [expressjs/compression](https://github.com/expressjs/compression)
|
* [express/express.js](https://github.com/expressjs/express) and [expressjs/compression](https://github.com/expressjs/compression)
|
||||||
* To serve, compute and render a GitHub user's metrics
|
* To serve, compute and render a GitHub user's metrics
|
||||||
* [nfriedly/express-rate-limit](https://github.com/nfriedly/express-rate-limit)
|
* [nfriedly/express-rate-limit](https://github.com/nfriedly/express-rate-limit)
|
||||||
@@ -623,8 +579,6 @@ See [GitHub Logos and Usage](https://github.com/logos) for more information.
|
|||||||
|
|
||||||
### ✨ Inspirations
|
### ✨ Inspirations
|
||||||
|
|
||||||
This project was inspired by the following projects :
|
|
||||||
|
|
||||||
* [anuraghazra/github-readme-stats](https://github.com/anuraghazra/github-readme-stats)
|
* [anuraghazra/github-readme-stats](https://github.com/anuraghazra/github-readme-stats)
|
||||||
* [jstrieb/github-stats](https://github.com/jstrieb/github-stats)
|
* [jstrieb/github-stats](https://github.com/jstrieb/github-stats)
|
||||||
* [ankurparihar/readme-pagespeed-insights](https://github.com/ankurparihar/readme-pagespeed-insights)
|
* [ankurparihar/readme-pagespeed-insights](https://github.com/ankurparihar/readme-pagespeed-insights)
|
||||||
|
|||||||
29
action.yml
29
action.yml
@@ -6,28 +6,41 @@ branding:
|
|||||||
color: gray-dark
|
color: gray-dark
|
||||||
inputs:
|
inputs:
|
||||||
token:
|
token:
|
||||||
description: GitHub Personal Token (require "public_repo" permissions)
|
description: GitHub Personal Token
|
||||||
required: true
|
required: true
|
||||||
committer_token:
|
committer_token:
|
||||||
description: If provided, this token will be used instead of "token" for commit operations. You can specify a bot account to avoid virtually increasing your stats due to this action commits.
|
description: If provided, this token will be used instead of "token" for commit operations (you can specify a bot account to avoid virtually increasing your stats due to this action commits)
|
||||||
|
default: ""
|
||||||
user:
|
user:
|
||||||
description: Target GitHub username
|
description: GitHub username
|
||||||
required: true
|
default: ""
|
||||||
filename:
|
filename:
|
||||||
description: Name of SVG image output
|
description: Name of SVG image output
|
||||||
default: github-metrics.svg
|
default: github-metrics.svg
|
||||||
|
optimize:
|
||||||
|
description: Optimize SVG image
|
||||||
|
default: yes
|
||||||
plugin_pagespeed:
|
plugin_pagespeed:
|
||||||
description: Enable Pagespeed metrics for user's website (requires "pagespeed_token" to be provided)
|
description: Enable Google PageSpeed metrics for account attached website
|
||||||
|
default: no
|
||||||
pagespeed_token:
|
pagespeed_token:
|
||||||
description: Pagespeed Personal Token (optional, see https://developers.google.com/speed/docs/insights/v5/get-started for more information)
|
description: Google Pagespeed Personal Token (*see https://developers.google.com/speed/docs/insights/v5/get-started for more informations)
|
||||||
|
default: ""
|
||||||
plugin_lines:
|
plugin_lines:
|
||||||
description: Enable repositories lines metrics
|
description: Enable lines of code metrics
|
||||||
|
default: no
|
||||||
plugin_traffic:
|
plugin_traffic:
|
||||||
description: Enable repositories traffic metrics (due to GitHub API limitations, "token" must have "repo" permissions)
|
description: Enable repositories traffic metrics (*provided GitHub token require full "repo" permissions)
|
||||||
|
default: no
|
||||||
plugin_habits:
|
plugin_habits:
|
||||||
description: Enable coding habits metrics
|
description: Enable coding habits metrics
|
||||||
|
default: no
|
||||||
|
plugin_selfskip:
|
||||||
|
description: Skip commits flagged with [Skip GitHub Action] from commits count
|
||||||
|
default: no
|
||||||
debug:
|
debug:
|
||||||
description: Enable debug logs
|
description: Enable debug logs
|
||||||
|
default: no
|
||||||
runs:
|
runs:
|
||||||
using: node12
|
using: node12
|
||||||
main: action/dist/index.js
|
main: action/dist/index.js
|
||||||
10
action/dist/index.js
vendored
10
action/dist/index.js
vendored
File diff suppressed because one or more lines are too long
100
action/index.mjs
100
action/index.mjs
@@ -4,10 +4,13 @@
|
|||||||
import * as _octokit from "@octokit/graphql"
|
import * as _octokit from "@octokit/graphql"
|
||||||
import * as _core from "@actions/core"
|
import * as _core from "@actions/core"
|
||||||
import * as _github from "@actions/github"
|
import * as _github from "@actions/github"
|
||||||
|
import * as _axios from "axios"
|
||||||
|
|
||||||
;((async function () {
|
;((async function () {
|
||||||
//Hack because ES modules are not correctly transpiled with ncc
|
//Hack because ES modules are not correctly transpiled with ncc
|
||||||
const [core, github, octokit, metrics] = [_core, _github, _octokit, _metrics].map(m => (m && m.default) ? m.default : m)
|
const [core, github, octokit, axios, metrics] = [_core, _github, _octokit, _axios, _metrics].map(m => (m && m.default) ? m.default : m)
|
||||||
|
//Yaml boolean converter
|
||||||
|
const bool = (value, defaulted = false) => typeof value === "string" ? /^(?:[Tt]rue|[Oo]n|[Yy]es)$/.test(value) : defaulted
|
||||||
//Runner
|
//Runner
|
||||||
try {
|
try {
|
||||||
//Initialization
|
//Initialization
|
||||||
@@ -16,68 +19,99 @@
|
|||||||
console.log(`Version | <#version>`)
|
console.log(`Version | <#version>`)
|
||||||
process.on("unhandledRejection", error => { throw error })
|
process.on("unhandledRejection", error => { throw error })
|
||||||
|
|
||||||
|
//Skip process if needed
|
||||||
|
if ((github.eventName === "push")&&(github.context.payload)&&(github.context.payload.head_commit)) {
|
||||||
|
if (/\[Skip GitHub Action\]/.test(github.context.payload.head_commit.message)) {
|
||||||
|
console.log(`Skipped because [Skip GitHub Action] is in commit message`)
|
||||||
|
process.exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Load svg template, style and query
|
//Load svg template, style and query
|
||||||
const template = `<#include template.svg>`, style = `<#include style.css>`, query = `<#include query.graphql>`
|
const template = `<#include template.svg>`, style = `<#include style.css>`, query = `<#include query.graphql>`
|
||||||
console.log(`Templates | loaded`)
|
console.log(`Templates | loaded`)
|
||||||
|
|
||||||
//Initialization
|
//Token for data gathering
|
||||||
const [token, user, filename, debug] = [core.getInput("token"), core.getInput("user"), core.getInput("filename", {default:"github-metrics.svg"}), core.getInput("debug", {default:false})]
|
const token = core.getInput("token") || github.token
|
||||||
const committer = core.getInput("committer_token", {default:null}) || token
|
|
||||||
const output = path.join(filename)
|
|
||||||
console.log(`GitHub user | ${user}`)
|
|
||||||
console.log(`Output file | ${output}`)
|
|
||||||
console.log(`Github token | ${token ? "provided" : "missing"}`)
|
console.log(`Github token | ${token ? "provided" : "missing"}`)
|
||||||
if (!token)
|
if (!token)
|
||||||
throw new Error("You must provide a valid GitHub token")
|
throw new Error("You must provide a valid GitHub token")
|
||||||
const graphql = octokit.graphql.defaults({headers:{authorization: `token ${token}`}})
|
const graphql = octokit.graphql.defaults({headers:{authorization: `token ${token}`}})
|
||||||
|
console.log(`Github GraphQL API | ok`)
|
||||||
const rest = github.getOctokit(token)
|
const rest = github.getOctokit(token)
|
||||||
|
console.log(`Github REST API | ok`)
|
||||||
|
|
||||||
|
//SVG output
|
||||||
|
const filename = core.getInput("filename") || "github-metrics.svg"
|
||||||
|
const output = path.join(filename)
|
||||||
|
console.log(`SVG output file | ${output}`)
|
||||||
|
|
||||||
|
//SVG optimization
|
||||||
|
const optimize = bool(core.getInput("optimize"), true)
|
||||||
|
console.log(`SVG optimization | ${optimize}`)
|
||||||
|
|
||||||
|
//GitHub user
|
||||||
|
const user = core.getInput("user") || (await rest.users.getAuthenticated()).data.login
|
||||||
|
console.log(`GitHub user | ${user}`)
|
||||||
|
|
||||||
//Debug mode
|
//Debug mode
|
||||||
|
const debug = bool(core.getInput("debug"))
|
||||||
if (!debug)
|
if (!debug)
|
||||||
console.debug = () => null
|
console.debug = () => null
|
||||||
console.log(`Debug mode | ${debug ? "enabled" : "disabled"}`)
|
console.log(`Debug mode | ${debug}`)
|
||||||
|
|
||||||
//Additional plugins
|
//Additional plugins
|
||||||
const plugins = {
|
const plugins = {
|
||||||
lines:{enabled:core.getInput("plugin_lines", {default:false})},
|
lines:{enabled:bool(core.getInput("plugin_lines"))},
|
||||||
traffic:{enabled:core.getInput("plugin_traffic", {default:false})},
|
traffic:{enabled:bool(core.getInput("plugin_traffic"))},
|
||||||
pagespeed:{enabled:core.getInput("plugin_pagespeed", {default:false})},
|
pagespeed:{enabled:bool(core.getInput("plugin_pagespeed"))},
|
||||||
habits:{enabled:core.getInput("plugin_habits", {default:false})},
|
habits:{enabled:bool(core.getInput("plugin_habits"))},
|
||||||
}
|
selfskip:{enabled:bool(core.getInput("plugin_selfskip"))},
|
||||||
if (core.getInput("pagespeed_token")) {
|
|
||||||
console.log(`Pagespeed token | provided`)
|
|
||||||
plugins.pagespeed.token = core.getInput("pagespeed_token")
|
|
||||||
}
|
}
|
||||||
const q = Object.fromEntries(Object.entries(plugins).filter(([key, plugin]) => plugin.enabled).map(([key]) => [key, true]))
|
const q = Object.fromEntries(Object.entries(plugins).filter(([key, plugin]) => plugin.enabled).map(([key]) => [key, true]))
|
||||||
console.log(`Plugins enabled | ${Object.entries(plugins).filter(([key, plugin]) => plugin.enabled).map(([key]) => key).join(", ")}`)
|
console.log(`Plugins enabled | ${Object.entries(plugins).filter(([key, plugin]) => plugin.enabled).map(([key]) => key).join(", ")}`)
|
||||||
|
if (plugins.pagespeed.enabled) {
|
||||||
|
plugins.pagespeed.token = core.getInput("pagespeed_token")
|
||||||
|
console.log(`Pagespeed token | ${plugins.pagespeed.token ? "provided" : "missing"}`)
|
||||||
|
}
|
||||||
|
|
||||||
//Render metrics
|
//Render metrics
|
||||||
const rendered = await metrics({login:user, q}, {template, style, query, graphql, rest, plugins})
|
const rendered = await metrics({login:user, q}, {template, style, query, graphql, rest, plugins, optimize})
|
||||||
console.log(`Render | complete`)
|
console.log(`Render | complete`)
|
||||||
|
|
||||||
//Commit to repository
|
//Commit to repository
|
||||||
{
|
{
|
||||||
const rest = github.getOctokit(committer)
|
//Committer token
|
||||||
console.log(`Committer | ${(await rest.users.getAuthenticated()).data.login}`)
|
const token = core.getInput("committer_token") || core.getInput("token")
|
||||||
let sha = undefined
|
console.log(`Committer token | ${token ? "provided" : "missing"}`)
|
||||||
try {
|
if (!token)
|
||||||
const {data} = await rest.repos.getContent({
|
throw new Error("You must provide a valid GitHub token")
|
||||||
owner:user,
|
const rest = github.getOctokit(token)
|
||||||
repo:user,
|
console.log(`Committer REST API | ok`)
|
||||||
path:filename,
|
console.log(`Committer | ${(await rest.users.getAuthenticated()).data.login}`)
|
||||||
|
//Retrieve previous render SHA to be able to update file content through API
|
||||||
|
let sha = undefined
|
||||||
|
try {
|
||||||
|
const {data} = await rest.repos.getContent({
|
||||||
|
owner:user,
|
||||||
|
repo:user,
|
||||||
|
path:filename,
|
||||||
|
})
|
||||||
|
sha = data.sha
|
||||||
|
} catch (error) { }
|
||||||
|
console.log(`Previous render sha | ${sha || "none"}`)
|
||||||
|
//Update file content through API
|
||||||
|
await rest.repos.createOrUpdateFileContents({
|
||||||
|
owner:user, repo:user, path:filename, sha, message:`Update ${filename} - [Skip GitHub Action]`,
|
||||||
|
content:Buffer.from(rendered).toString("base64"),
|
||||||
})
|
})
|
||||||
sha = data.sha
|
console.log(`Commit to repo | ok`)
|
||||||
} catch (error) { }
|
|
||||||
console.log(`Previous render sha | ${sha || "none"}`)
|
|
||||||
await rest.repos.createOrUpdateFileContents({
|
|
||||||
owner:user, repo:user, path:filename, sha, message:`Update ${filename} - [Skip GitHub Action]`,
|
|
||||||
content:Buffer.from(rendered).toString("base64"),
|
|
||||||
})
|
|
||||||
console.log(`Commit to repo | ok`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Success
|
//Success
|
||||||
console.log(`Success !`)
|
console.log(`Success !`)
|
||||||
|
process.exit(0)
|
||||||
|
|
||||||
//Errors
|
//Errors
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "metrics",
|
"name": "metrics",
|
||||||
"version": "1.7.0",
|
"version": "1.8.0",
|
||||||
"description": "Generate an user's GitHub metrics as SVG image format to embed somewhere else",
|
"description": "Generate an user's GitHub metrics as SVG image format to embed somewhere else",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -5,11 +5,12 @@
|
|||||||
"maxusers":0, "//":"Maximum number of users, 0 for unlimited",
|
"maxusers":0, "//":"Maximum number of users, 0 for unlimited",
|
||||||
"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",
|
||||||
|
"optimize":true, "//":"Optimize SVG image",
|
||||||
"debug":false, "//":"Debug mode",
|
"debug":false, "//":"Debug mode",
|
||||||
|
|
||||||
"plugins":{ "//":"Additional plugins (optional)",
|
"plugins":{ "//":"Additional plugins (optional)",
|
||||||
"pagespeed":{ "//":"Pagespeed plugin",
|
"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)",
|
"traffic":{ "//":"Traffic plugin (GitHub API token must be RW for this to work)",
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
//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, rest, plugins})
|
const rendered = await metrics({login, q:req.query}, {template, style, query, graphql, rest, plugins, optimize:settings.optimize})
|
||||||
//Cache
|
//Cache
|
||||||
if ((!debug)&&(cached))
|
if ((!debug)&&(cached))
|
||||||
cache.put(login, rendered, cached)
|
cache.put(login, rendered, cached)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
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, rest, plugins}) {
|
export default async function metrics({login, q}, {template, style, query, graphql, rest, plugins, selfless = true, optimize = true}) {
|
||||||
//Compute rendering
|
//Compute rendering
|
||||||
try {
|
try {
|
||||||
|
|
||||||
@@ -29,6 +29,7 @@
|
|||||||
Plugins.lines({login, repositories:data.user.repositories.nodes.map(({name}) => name), rest, computed, pending, q}, plugins.lines)
|
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)
|
Plugins.traffic({login, repositories:data.user.repositories.nodes.map(({name}) => name), rest, computed, pending, q}, plugins.traffic)
|
||||||
Plugins.habits({login, rest, computed, pending, q}, plugins.habits)
|
Plugins.habits({login, rest, computed, pending, q}, plugins.habits)
|
||||||
|
Plugins.selfskip({login, rest, computed, pending, q}, plugins.selfskip)
|
||||||
|
|
||||||
//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) {
|
||||||
@@ -82,16 +83,18 @@
|
|||||||
|
|
||||||
//Eval rendering
|
//Eval rendering
|
||||||
console.debug(`metrics/metrics/${login} > computed`)
|
console.debug(`metrics/metrics/${login} > computed`)
|
||||||
const templated = eval(`\`${template}\``)
|
let rendered = eval(`\`${template}\``)
|
||||||
console.debug(`metrics/metrics/${login} > templated`)
|
console.debug(`metrics/metrics/${login} > templated`)
|
||||||
|
|
||||||
//Optimize rendering
|
//Optimize rendering
|
||||||
const svgo = new SVGO({full:true, plugins:[{cleanupAttrs:true}, {inlineStyles:false}]})
|
if (optimize) {
|
||||||
const {data:optimized} = await svgo.optimize(templated)
|
const svgo = new SVGO({full:true, plugins:[{cleanupAttrs:true}, {inlineStyles:false}]})
|
||||||
console.debug(`metrics/metrics/${login} > optimized`)
|
const {data:optimized} = await svgo.optimize(rendered)
|
||||||
|
console.debug(`metrics/metrics/${login} > optimized`)
|
||||||
|
rendered = optimized
|
||||||
|
}
|
||||||
|
|
||||||
//Result
|
//Result
|
||||||
const rendered = optimized
|
|
||||||
return rendered
|
return rendered
|
||||||
}
|
}
|
||||||
//Internal error
|
//Internal error
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import habits from "./habits/index.mjs"
|
import habits from "./habits/index.mjs"
|
||||||
import lines from "./lines/index.mjs"
|
import lines from "./lines/index.mjs"
|
||||||
import pagespeed from "./pagespeed/index.mjs"
|
import pagespeed from "./pagespeed/index.mjs"
|
||||||
|
import selfskip from "./selfskip/index.mjs"
|
||||||
import traffic from "./traffic/index.mjs"
|
import traffic from "./traffic/index.mjs"
|
||||||
|
|
||||||
//Exports
|
//Exports
|
||||||
@@ -9,5 +10,6 @@
|
|||||||
habits,
|
habits,
|
||||||
lines,
|
lines,
|
||||||
pagespeed,
|
pagespeed,
|
||||||
|
selfskip,
|
||||||
traffic,
|
traffic,
|
||||||
}
|
}
|
||||||
@@ -6,8 +6,6 @@
|
|||||||
//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)
|
||||||
|
|||||||
33
src/plugins/selfskip/index.mjs
Normal file
33
src/plugins/selfskip/index.mjs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
//Setup
|
||||||
|
export default function ({login, rest, computed, pending, q}, {enabled = false} = {}) {
|
||||||
|
//Check if plugin is enabled and requirements are met
|
||||||
|
if (!enabled)
|
||||||
|
return computed.plugins.selfskip = null
|
||||||
|
if (!q.selfskip)
|
||||||
|
return computed.plugins.selfskip = null
|
||||||
|
console.debug(`metrics/plugins/selfskip/${login} > started`)
|
||||||
|
|
||||||
|
//Plugin execution
|
||||||
|
pending.push(new Promise(async solve => {
|
||||||
|
try {
|
||||||
|
//Search for auto-generated commits
|
||||||
|
let commits = 0
|
||||||
|
for (let page = 0;;page++) {
|
||||||
|
const {data} = await rest.repos.listCommits({owner:login, repo:login, author:login, per_page:100, page})
|
||||||
|
commits += data.filter(({commit}) => /\[Skip GitHub Action\]/.test(commit.message)).length
|
||||||
|
if (!data.length)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
//Save results
|
||||||
|
computed.plugins.selfskip = {commits}
|
||||||
|
console.debug(`metrics/plugins/selfskip/${login} > ${JSON.stringify(computed.plugins.selfskip)}`)
|
||||||
|
solve()
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
//Generic error
|
||||||
|
computed.plugins.selfskip = {error:`An error occured`}
|
||||||
|
console.debug(error)
|
||||||
|
solve()
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
</h2>
|
</h2>
|
||||||
<div class="field">
|
<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="M10.5 7.75a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0zm1.43.75a4.002 4.002 0 01-7.86 0H.75a.75.75 0 110-1.5h3.32a4.001 4.001 0 017.86 0h3.32a.75.75 0 110 1.5h-3.32z"></path></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M10.5 7.75a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0zm1.43.75a4.002 4.002 0 01-7.86 0H.75a.75.75 0 110-1.5h3.32a4.001 4.001 0 017.86 0h3.32a.75.75 0 110 1.5h-3.32z"></path></svg>
|
||||||
${data.computed.commits} Commit${data.computed.commits > 1 ? "s" : ""}
|
${data.computed.commits - (computed.plugins.selfskip ? computed.plugins.selfskip.commits||0 : 0)} Commit${data.computed.commits - (computed.plugins.selfskip ? computed.plugins.selfskip.commits||0 : 0) > 1 ? "s" : ""}
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<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="M2.5 1.75a.25.25 0 01.25-.25h8.5a.25.25 0 01.25.25v7.736a.75.75 0 101.5 0V1.75A1.75 1.75 0 0011.25 0h-8.5A1.75 1.75 0 001 1.75v11.5c0 .966.784 1.75 1.75 1.75h3.17a.75.75 0 000-1.5H2.75a.25.25 0 01-.25-.25V1.75zM4.75 4a.75.75 0 000 1.5h4.5a.75.75 0 000-1.5h-4.5zM4 7.75A.75.75 0 014.75 7h2a.75.75 0 010 1.5h-2A.75.75 0 014 7.75zm11.774 3.537a.75.75 0 00-1.048-1.074L10.7 14.145 9.281 12.72a.75.75 0 00-1.062 1.058l1.943 1.95a.75.75 0 001.055.008l4.557-4.45z"></path></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M2.5 1.75a.25.25 0 01.25-.25h8.5a.25.25 0 01.25.25v7.736a.75.75 0 101.5 0V1.75A1.75 1.75 0 0011.25 0h-8.5A1.75 1.75 0 001 1.75v11.5c0 .966.784 1.75 1.75 1.75h3.17a.75.75 0 000-1.5H2.75a.25.25 0 01-.25-.25V1.75zM4.75 4a.75.75 0 000 1.5h4.5a.75.75 0 000-1.5h-4.5zM4 7.75A.75.75 0 014.75 7h2a.75.75 0 010 1.5h-2A.75.75 0 014 7.75zm11.774 3.537a.75.75 0 00-1.048-1.074L10.7 14.145 9.281 12.72a.75.75 0 00-1.062 1.058l1.943 1.95a.75.75 0 001.055.008l4.557-4.45z"></path></svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
@@ -2,15 +2,20 @@
|
|||||||
import path from "path"
|
import path from "path"
|
||||||
import fs from "fs"
|
import fs from "fs"
|
||||||
import metrics from "../src/metrics.mjs"
|
import metrics from "../src/metrics.mjs"
|
||||||
|
import build from "../utils/build.mjs"
|
||||||
import octokit from "@octokit/graphql"
|
import octokit from "@octokit/graphql"
|
||||||
import OctokitRest from "@octokit/rest"
|
import OctokitRest from "@octokit/rest"
|
||||||
import libxmljs from "libxmljs"
|
import libxmljs from "libxmljs"
|
||||||
|
import url from "url"
|
||||||
|
|
||||||
|
//Dirname
|
||||||
|
const __dirname = path.join(path.dirname(url.fileURLToPath(import.meta.url)), "..", "action")
|
||||||
|
|
||||||
//Die on unhandled rejections
|
//Die on unhandled rejections
|
||||||
process.on("unhandledRejection", error => { throw error })
|
process.on("unhandledRejection", error => { throw error })
|
||||||
|
|
||||||
//Load GitHub handlers
|
//Load GitHub handlers
|
||||||
const token = process.argv.slice(2)[0] ?? ""
|
const token = process.argv.slice(2)[0] ?? "73a71c11ec07d9b114f5e2af26a3cdde1c6fe65a"
|
||||||
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})
|
const rest = new OctokitRest.Octokit({auth:token})
|
||||||
|
|
||||||
@@ -25,4 +30,10 @@
|
|||||||
if (parsed.errors.length)
|
if (parsed.errors.length)
|
||||||
throw new Error(`Malformed SVG : \n${parsed.errors.join("\n")}`)
|
throw new Error(`Malformed SVG : \n${parsed.errors.join("\n")}`)
|
||||||
|
|
||||||
|
//Ensure that action has been rebuild
|
||||||
|
const action = `${await fs.promises.readFile(`${__dirname}/dist/index.js`)}`
|
||||||
|
const code = await build()
|
||||||
|
if (action !== code)
|
||||||
|
throw new Error(`GitHub Action has not been rebuild. Run "npm run build" to solve this issue`)
|
||||||
|
|
||||||
console.log("Test success !")
|
console.log("Test success !")
|
||||||
@@ -7,23 +7,33 @@
|
|||||||
//Dirname
|
//Dirname
|
||||||
const __dirname = path.join(path.dirname(url.fileURLToPath(import.meta.url)), "..", "action")
|
const __dirname = path.join(path.dirname(url.fileURLToPath(import.meta.url)), "..", "action")
|
||||||
|
|
||||||
//Build code
|
/** Build function */
|
||||||
let {code} = await ncc(`${__dirname}/index.mjs`, {
|
export default async function build() {
|
||||||
minify:true,
|
//Build code
|
||||||
sourceMap:false,
|
let {code} = await ncc(`${__dirname}/index.mjs`, {
|
||||||
sourceMapRegister:false,
|
minify:true,
|
||||||
})
|
sourceMap:false,
|
||||||
|
sourceMapRegister:false,
|
||||||
|
})
|
||||||
|
|
||||||
//Perform static includes
|
//Perform static includes
|
||||||
for (const match of [...code.match(/(?<=`)<#include (.+?)>(?=`)/g)]) {
|
for (const match of [...code.match(/(?<=`)<#include (.+?)>(?=`)/g)]) {
|
||||||
const file = match.match(/<#include (.+?)>/)[1]
|
const file = match.match(/<#include (.+?)>/)[1]
|
||||||
code = code.replace(`<#include ${file}>`, `${await fs.promises.readFile(path.join(__dirname, "..", "src", file))}`.replace(/([$`])/g, "\\$1"))
|
code = code.replace(`<#include ${file}>`, `${await fs.promises.readFile(path.join(__dirname, "..", "src", file))}`.replace(/([$`])/g, "\\$1"))
|
||||||
console.log(`Included ${file}`)
|
console.log(`Included ${file}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Perform version include
|
||||||
|
const version = JSON.parse(await fs.promises.readFile(path.join(__dirname, "..", "package.json"))).version
|
||||||
|
code = code.replace(`<#version>`, version)
|
||||||
|
|
||||||
|
//Code
|
||||||
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
//Perform version include
|
//Main
|
||||||
const version = JSON.parse(await fs.promises.readFile(path.join(__dirname, "..", "package.json"))).version
|
if (/build.mjs/.test(process.argv[1])) {
|
||||||
code = code.replace(`<#version>`, version)
|
//Save build
|
||||||
|
await fs.promises.writeFile(`${__dirname}/dist/index.js`, await build())
|
||||||
//Save build
|
console.log("Build successful !")
|
||||||
await fs.promises.writeFile(`${__dirname}/dist/index.js`, code)
|
}
|
||||||
Reference in New Issue
Block a user