From 0c70a25288dbc0b5afc2d24f2eb5bb3074ccfd3e Mon Sep 17 00:00:00 2001 From: lowlighter <22963968+lowlighter@users.noreply.github.com> Date: Tue, 18 Jan 2022 19:56:56 -0500 Subject: [PATCH] docs(plugins/community): finish writing (closes #778) --- .../partials/templated/plugins.community.md | 167 +++++++++++++++--- source/plugins/community/README.md | 167 +++++++++++++++--- 2 files changed, 282 insertions(+), 52 deletions(-) diff --git a/.github/readme/partials/templated/plugins.community.md b/.github/readme/partials/templated/plugins.community.md index 03b76b5a..cca86aa2 100644 --- a/.github/readme/partials/templated/plugins.community.md +++ b/.github/readme/partials/templated/plugins.community.md @@ -35,7 +35,7 @@ Please respect the following guidelines: - A plugin should be independant and should not rely on other plugins - [🧱 core](/source/plugins/core/README.md) and [đŸ—ƒī¸ base](/source/plugins/base/README.md) output can be reused though -- A plugin should never edit its original arguments, as the object is shared amongst other plugins and would create unattended side effects +- A plugin should never edit its original arguments, as it is shared amongst other plugins and would create unattended side effects - Use `imports.metadata.plugins.{plugin-name}.inputs()` to automatically typecheck and default user inputs through defined `metadata.yml` - Plugin options should respect the "lexical field" of existing option to keep consistency - Plugin errors should be handled gracefully by partials with error message @@ -46,6 +46,8 @@ Please respect the following guidelines: - Pass `{prefixed: true}` to wrap automatically command with [WSL](https://docs.microsoft.com/windows/wsl/about) on Windows - It is required to work on Linux Ubuntu (as the GitHub action run on it) +> 💡 While the following guide intend to explain the creation process of new plugin, it may also be a good idea to see what existing plugins looks like and see if you want to embark on the adventure! + ### đŸ’Ŧ Quick-start To create a new plugin, clone and setup this repository first: @@ -82,6 +84,8 @@ category: community description: Short description examples: default: https://via.placeholder.com/468x60?text=No%20preview%20available +authors: + - octocat supports: - user - organization @@ -101,6 +105,8 @@ inputs: `name`, `description`, `scopes`, `examples` are used to auto-generate documentation in the `README.md`. For community plugins, `examples` should be set with auto-generated examples of your own profile. +`authors` should contain your GitHub username + `category` should be set to `community`. Because of GitHub Actions original limitations, only strings, numbers and boolean were actually supported by `action.yml`. *metrics* implemented its own `inputs` validator to circumvent this. It should be pretty simple to use. @@ -192,7 +198,54 @@ console.assert(limit === true) ### đŸ’Ŧ Filling `index.mjs` -> 🚧 Will be available at a later date +Plugins use [JavaScript modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules). + +The default exported module of `index.mjs` will be auto-loaded when *metrics* start. + +Below is a breakdown of basic `index.mjs` content +```js +export default async function( + //Shared inputs + { + login, //GitHub username + q, //Raw user inputs (dot notation without plugin_ prefix, don't use it directly) + imports, //Various utilitaires (axios, puppeteer, fs, etc., see /source/app/metrics/utils.mjs) + data, //Raw data from core/base plugin + computed, //Computed data from core/base plugin + rest, //Rest authenticated GitHub octokit + graphql, //Graph QL authenticated GitHub octokit + queries, //Autoloaded queries from ./queries + account, //Account type ("user" or "organization") + }, + //Settings and tokens + { + enabled = false + } = {}) { + //Plugin execution + try { + //Check if plugin is enabled and requirements are met + if ((!enabled)||(!q.my_plugin)) + return null + + //Automatically validate user inputs + //An error will be thrown if `account` type is not supported + //Inputs will have correct typing from `metadata.yml` and unset or invalid options will be set to default + let {option} = imports.metadata.plugins.my_plugin.inputs({data, account, q}) + + //Automatically template query from /source/plugins/myplugin/queries/myquery.graph ql + const {[account]:stuff} = await graphql(queries.myplugin.myquery({login, account, option})) + + //Results + return {stuff} + } + //Handle errors + catch (error) { + throw {error:{message:"An error occured", instance:error}} + } +} +``` + +> âš ī¸ Remember, a plugin should never edit its original arguments, as it is shared amongst other plugins and would create unattended side effects ### đŸ’Ŧ Creating partials @@ -215,6 +268,40 @@ Partials should have the match the same name as plugin handles, as they're used [EJS](https://github.com/mde/ejs) framework is used to template content through templating tags (`<% %>`). +### đŸ’Ŧ Filling `README.md` + +`README.md` is used as documentation. + +Most of it will is auto-generated by `metadata.yml` and `examples.yml` content, so usually it is not required to manually edit it. + +The default content looks like below: +```markdown +<Įƒ--header--> +<Įƒ--/header--> + +## âžĄī¸ Available options + +<Įƒ--options--> +<Įƒ--/options--> + +## â„šī¸ Examples workflows + +<Įƒ--examples--> +<Įƒ--/examples--> +``` + +- `<Įƒ--header-->` will be replaced by an auto-generated header containing plugin name, supported features and output examples based on `metadata.yml` +- `<Įƒ--options-->` will be replaced by an auto-generated table containing all referenced option from `metadata.yml` +- `<Įƒ--examples-->` will be replaced by workflows from `examples.yml` + +> âš ī¸ Do not replace these auto-generated placeholder yet! They will be built by the ci workflow and will help making your pull request easier to read + +When a plugin requires a token, please add a `## đŸ—ī¸ Obtaining a {service} token` section after the available options section. + +Complex features may also be documented in additional sections after available options section options if required. + +Try to respect current format of `README.md` from other plugins and use a neutral and impersonal writing style if possible. + ### đŸ’Ŧ Filling `examples.yml` Workflow examples from `examples.yml` are used as unit testing and to auto-generate documentation in the `README.md`. @@ -244,34 +331,62 @@ It uses the same syntax as GitHub action and looks like below: `prod` should keep `skip: true` as you should use your own render outputs as examples. -### đŸ’Ŧ Filling `README.md` +### đŸ’Ŧ Testing locally and creating mocked data -`README.md` is used as documentation. +The easiest way to test a new plugin is to setup a web instance locally ([see documentation](.github/readme/partials/documentation/setup/local.md)). -Most of it will is auto-generated by `metadata.yml` and `examples.yml` content, so usually it is not required to manually edit it. - -The default content looks like below: -```markdown -<Įƒ--header--> -<Įƒ--/header--> - -## âžĄī¸ Available options - -<Įƒ--options--> -<Įƒ--/options--> - -## â„šī¸ Examples workflows - -<Įƒ--examples--> -<Įƒ--/examples--> +Once server is started, open a browser and try to generate an output with your new plugin enabled and check if it works as expected: +``` +http://localhost:3000/username?base=0&my-plugin=1 ``` -- `<Įƒ--header-->` will be replaced by an auto-generated header containing plugin name, supported features and output examples based on `metadata.yml` -- `<Įƒ--options-->` will be replaced by an auto-generated table containing all referenced option from `metadata.yml` -- `<Įƒ--examples-->` will be replaced by workflows from `examples.yml` +> 💡 You may need to configure your server first by editing `settings.json`. Ensure that: +> - `token` is correctly set when working with GitHub APIs +> - `plugins.default` is set to `true` as plugins are disabled by default +> - or enable your plugins by manually in `plugins`.`my-plugin`.`enabled` +> - `debug` is set to `true` for more verbose output -When a plugin requires a token, please add a `## đŸ—ī¸ Obtaining a {service} token` section after the available options section. +When your plugin is finalized, you may need to create mocked data if it either uses GitHub APIs or any external service. -Complex features may also be documented in additional sections after available options section options if required. +They must be created in `tests/mocks/api`: +- use `github` directory for all related GitHub APIs data +- use `axios` directory for all external service that you call using `imports.axios` + +> 💡 Files from these directories are auto-loaded, so it is just required to create them with faked data. + +Finally [/source/app/web/statics/app.placeholder.js](/source/app/web/statics/app.placeholder.js) to add mocked placeholder data to make users using the shared instance able to preview a render locally without any server computation. + +### đŸ’Ŧ Submitting a pull request + +If you made it until there, congratulations đŸĨŗ! + +You're almost done, review the following checklist before submitting a pull request: +- [x] I have correctly filled `metadata.yml` + - [x] `name` is set with an unused emoji and plugin name + - [x] `category` is set to `community` + - [x] `examples` contains links towards a rendered output hosted by you + - [x] `authors` contains my GitHub username + - [x] `supports` list which account type are supported + - [x] `scopes` are correctly listed with their associated names on GitHub (leave an empty array if not applicable) + - [x] `inputs` are correctly filled +- [x] I have implemented my plugin + - [x] `index.mjs` respects the plugins guidelines +- [x] I have tested my plugin locally + - [x] `tests/mocks` ... have been created + - [x] `app.placeholder.js` has been updated for preview from web instances + - [x] `examples.yml` contains workflows examples (at least one is required) + - [x] `skip: true` has been set for `prod` attribute in each test + - [x] `npm run linter` yields no errors +- [x] I have documented my plugin + - [x] `README.md` eventually describes complex setup or options (if applicable) +- [x] I am ready! + - [x] Checkout any generated files (in fact, don't run `npm run build`) + - [x] Commit and push your changes (commits are squashed, no need to rebase) + - [x] Open a new [pull request](https://github.com/lowlighter/metrics/pulls) + - [x] Post a screenshot or a render in the pull request so it can be previewed + +> 💡 A pull request **will need** to have passing builds and an example screenshot if you want to get it merged. +> Maintainers may request changes in some cases + +> 🎊 Thanks a lot for your contribution! -Try to respect current format of `README.md` from other plugins and use a neutral and impersonal writing style if possible. diff --git a/source/plugins/community/README.md b/source/plugins/community/README.md index 879c2a62..a454cf7f 100644 --- a/source/plugins/community/README.md +++ b/source/plugins/community/README.md @@ -44,7 +44,7 @@ Please respect the following guidelines: - A plugin should be independant and should not rely on other plugins - [🧱 core](/source/plugins/core/README.md) and [đŸ—ƒī¸ base](/source/plugins/base/README.md) output can be reused though -- A plugin should never edit its original arguments, as the object is shared amongst other plugins and would create unattended side effects +- A plugin should never edit its original arguments, as it is shared amongst other plugins and would create unattended side effects - Use `imports.metadata.plugins.{plugin-name}.inputs()` to automatically typecheck and default user inputs through defined `metadata.yml` - Plugin options should respect the "lexical field" of existing option to keep consistency - Plugin errors should be handled gracefully by partials with error message @@ -55,6 +55,8 @@ Please respect the following guidelines: - Pass `{prefixed: true}` to wrap automatically command with [WSL](https://docs.microsoft.com/windows/wsl/about) on Windows - It is required to work on Linux Ubuntu (as the GitHub action run on it) +> 💡 While the following guide intend to explain the creation process of new plugin, it may also be a good idea to see what existing plugins looks like and see if you want to embark on the adventure! + ### đŸ’Ŧ Quick-start To create a new plugin, clone and setup this repository first: @@ -91,6 +93,8 @@ category: community description: Short description examples: default: https://via.placeholder.com/468x60?text=No%20preview%20available +authors: + - octocat supports: - user - organization @@ -110,6 +114,8 @@ inputs: `name`, `description`, `scopes`, `examples` are used to auto-generate documentation in the `README.md`. For community plugins, `examples` should be set with auto-generated examples of your own profile. +`authors` should contain your GitHub username + `category` should be set to `community`. Because of GitHub Actions original limitations, only strings, numbers and boolean were actually supported by `action.yml`. *metrics* implemented its own `inputs` validator to circumvent this. It should be pretty simple to use. @@ -201,7 +207,54 @@ console.assert(limit === true) ### đŸ’Ŧ Filling `index.mjs` -> 🚧 Will be available at a later date +Plugins use [JavaScript modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules). + +The default exported module of `index.mjs` will be auto-loaded when *metrics* start. + +Below is a breakdown of basic `index.mjs` content +```js +export default async function( + //Shared inputs + { + login, //GitHub username + q, //Raw user inputs (dot notation without plugin_ prefix, don't use it directly) + imports, //Various utilitaires (axios, puppeteer, fs, etc., see /source/app/metrics/utils.mjs) + data, //Raw data from core/base plugin + computed, //Computed data from core/base plugin + rest, //Rest authenticated GitHub octokit + graphql, //Graph QL authenticated GitHub octokit + queries, //Autoloaded queries from ./queries + account, //Account type ("user" or "organization") + }, + //Settings and tokens + { + enabled = false + } = {}) { + //Plugin execution + try { + //Check if plugin is enabled and requirements are met + if ((!enabled)||(!q.my_plugin)) + return null + + //Automatically validate user inputs + //An error will be thrown if `account` type is not supported + //Inputs will have correct typing from `metadata.yml` and unset or invalid options will be set to default + let {option} = imports.metadata.plugins.my_plugin.inputs({data, account, q}) + + //Automatically template query from /source/plugins/myplugin/queries/myquery.graph ql + const {[account]:stuff} = await graphql(queries.myplugin.myquery({login, account, option})) + + //Results + return {stuff} + } + //Handle errors + catch (error) { + throw {error:{message:"An error occured", instance:error}} + } +} +``` + +> âš ī¸ Remember, a plugin should never edit its original arguments, as it is shared amongst other plugins and would create unattended side effects ### đŸ’Ŧ Creating partials @@ -224,6 +277,40 @@ Partials should have the match the same name as plugin handles, as they're used [EJS](https://github.com/mde/ejs) framework is used to template content through templating tags (``). +### đŸ’Ŧ Filling `README.md` + +`README.md` is used as documentation. + +Most of it will is auto-generated by `metadata.yml` and `examples.yml` content, so usually it is not required to manually edit it. + +The default content looks like below: +```markdown +<Įƒ--header--> +<Įƒ--/header--> + +## âžĄī¸ Available options + +<Įƒ--options--> +<Įƒ--/options--> + +## â„šī¸ Examples workflows + +<Įƒ--examples--> +<Įƒ--/examples--> +``` + +- `<Įƒ--header-->` will be replaced by an auto-generated header containing plugin name, supported features and output examples based on `metadata.yml` +- `<Įƒ--options-->` will be replaced by an auto-generated table containing all referenced option from `metadata.yml` +- `<Įƒ--examples-->` will be replaced by workflows from `examples.yml` + +> âš ī¸ Do not replace these auto-generated placeholder yet! They will be built by the ci workflow and will help making your pull request easier to read + +When a plugin requires a token, please add a `## đŸ—ī¸ Obtaining a {service} token` section after the available options section. + +Complex features may also be documented in additional sections after available options section options if required. + +Try to respect current format of `README.md` from other plugins and use a neutral and impersonal writing style if possible. + ### đŸ’Ŧ Filling `examples.yml` Workflow examples from `examples.yml` are used as unit testing and to auto-generate documentation in the `README.md`. @@ -253,34 +340,62 @@ It uses the same syntax as GitHub action and looks like below: `prod` should keep `skip: true` as you should use your own render outputs as examples. -### đŸ’Ŧ Filling `README.md` +### đŸ’Ŧ Testing locally and creating mocked data -`README.md` is used as documentation. +The easiest way to test a new plugin is to setup a web instance locally ([see documentation](.github/readme/partials/documentation/setup/local.md)). -Most of it will is auto-generated by `metadata.yml` and `examples.yml` content, so usually it is not required to manually edit it. - -The default content looks like below: -```markdown -<Įƒ--header--> -<Įƒ--/header--> - -## âžĄī¸ Available options - -<Įƒ--options--> -<Įƒ--/options--> - -## â„šī¸ Examples workflows - -<Įƒ--examples--> -<Įƒ--/examples--> +Once server is started, open a browser and try to generate an output with your new plugin enabled and check if it works as expected: +``` +http://localhost:3000/username?base=0&my-plugin=1 ``` -- `<Įƒ--header-->` will be replaced by an auto-generated header containing plugin name, supported features and output examples based on `metadata.yml` -- `<Įƒ--options-->` will be replaced by an auto-generated table containing all referenced option from `metadata.yml` -- `<Įƒ--examples-->` will be replaced by workflows from `examples.yml` +> 💡 You may need to configure your server first by editing `settings.json`. Ensure that: +> - `token` is correctly set when working with GitHub APIs +> - `plugins.default` is set to `true` as plugins are disabled by default +> - or enable your plugins by manually in `plugins`.`my-plugin`.`enabled` +> - `debug` is set to `true` for more verbose output -When a plugin requires a token, please add a `## đŸ—ī¸ Obtaining a {service} token` section after the available options section. +When your plugin is finalized, you may need to create mocked data if it either uses GitHub APIs or any external service. -Complex features may also be documented in additional sections after available options section options if required. +They must be created in `tests/mocks/api`: +- use `github` directory for all related GitHub APIs data +- use `axios` directory for all external service that you call using `imports.axios` + +> 💡 Files from these directories are auto-loaded, so it is just required to create them with faked data. + +Finally [/source/app/web/statics/app.placeholder.js](/source/app/web/statics/app.placeholder.js) to add mocked placeholder data to make users using the shared instance able to preview a render locally without any server computation. + +### đŸ’Ŧ Submitting a pull request + +If you made it until there, congratulations đŸĨŗ! + +You're almost done, review the following checklist before submitting a pull request: +- [x] I have correctly filled `metadata.yml` + - [x] `name` is set with an unused emoji and plugin name + - [x] `category` is set to `community` + - [x] `examples` contains links towards a rendered output hosted by you + - [x] `authors` contains my GitHub username + - [x] `supports` list which account type are supported + - [x] `scopes` are correctly listed with their associated names on GitHub (leave an empty array if not applicable) + - [x] `inputs` are correctly filled +- [x] I have implemented my plugin + - [x] `index.mjs` respects the plugins guidelines +- [x] I have tested my plugin locally + - [x] `tests/mocks` ... have been created + - [x] `app.placeholder.js` has been updated for preview from web instances + - [x] `examples.yml` contains workflows examples (at least one is required) + - [x] `skip: true` has been set for `prod` attribute in each test + - [x] `npm run linter` yields no errors +- [x] I have documented my plugin + - [x] `README.md` eventually describes complex setup or options (if applicable) +- [x] I am ready! + - [x] Checkout any generated files (in fact, don't run `npm run build`) + - [x] Commit and push your changes (commits are squashed, no need to rebase) + - [x] Open a new [pull request](https://github.com/lowlighter/metrics/pulls) + - [x] Post a screenshot or a render in the pull request so it can be previewed + +> 💡 A pull request **will need** to have passing builds and an example screenshot if you want to get it merged. +> Maintainers may request changes in some cases + +> 🎊 Thanks a lot for your contribution! -Try to respect current format of `README.md` from other plugins and use a neutral and impersonal writing style if possible.