-
Notifications
You must be signed in to change notification settings - Fork 17
feat: add plugin to fetch terasology engine info from github #197
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0bc8cb0
02c8058
87fc1c5
10fb48c
6fa5d10
1992ea9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| # source-terasology-engine | ||
|
|
||
| Custom [Gatsby Source Plugin](https://www.gatsbyjs.com/docs/how-to/plugins-and-themes/creating-a-source-plugin/) to fetch enriched information for the [Terasology Engine](https://github.com/MovingBlocks/Terasology) from GitHub. | ||
|
|
||
| ## Install | ||
|
|
||
| This is a local plugin that is automatically loaded from the `plugins/` folder. | ||
|
|
||
| ## Configuration | ||
|
|
||
| ```js | ||
| // in gatsby-config.js | ||
| module.exports = { | ||
| plugins: [ | ||
| //... | ||
| { | ||
| resolve: "source-terasology-engine", | ||
| options: { | ||
| accessToken: `<your GitHub access token>` | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| ``` | ||
|
|
||
| Use [Environment Variables](https://www.gatsbyjs.com/docs/how-to/local-development/environment-variables/) to avoid exposing secrets. | ||
|
|
||
| ## Usage | ||
|
|
||
| ```graphql | ||
| query Engine { | ||
| allTerasologyEngine { | ||
| issues{ | ||
| nodes { | ||
| id | ||
| title | ||
| author { | ||
| login | ||
| } | ||
| labels { | ||
| nodes { | ||
| name | ||
| } | ||
| } | ||
| updatedAt | ||
| url | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| const { graphql } = require("@octokit/graphql"); | ||
| const { DateTime } = require("luxon"); | ||
| const fs = require("fs"); | ||
|
|
||
| const PLUGIN_NAME = "source-terasology-engine"; | ||
|
|
||
| const query = ` | ||
| query Engine { | ||
| organization(login: "MovingBlocks") { | ||
| repository(name: "Terasology") { | ||
| issues(first: 10, filterBy: {labels: "Good First Issue", states: OPEN}, orderBy: {field: UPDATED_AT, direction: DESC}) { | ||
| nodes { | ||
| id | ||
| title | ||
| author { | ||
| login | ||
| } | ||
| labels(first: 10) { | ||
| nodes { | ||
| name | ||
| } | ||
| } | ||
| updatedAt | ||
| url | ||
| } | ||
|
Comment on lines
+12
to
+25
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is (naturally) the same structure as we use for fetching issues for modules. We could use GraphQL Fragments to make sure they always have the same structure. Which makes me wonder whether this should actually be a separate plugin, or whether we just merge it with the other one for simplicity (and easier sharing of code and query fragments....)
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's consider doing that in a follow-up PR 👍 |
||
| } | ||
| } | ||
| } | ||
| } | ||
| `; | ||
|
|
||
| exports.onPreInit = ({ reporter }) => | ||
| reporter.verbose("Loaded source-terasology-engine"); | ||
|
|
||
| exports.sourceNodes = async ( | ||
| { | ||
| actions: { createNode }, | ||
| createContentDigest, | ||
| createNodeId, | ||
| reporter, | ||
| cache, | ||
| }, | ||
| { accessToken } | ||
| ) => { | ||
| const gql = graphql.defaults({ | ||
| headers: { | ||
| authorization: `token ${accessToken}`, | ||
| }, | ||
| }); | ||
|
|
||
| const lastFetchedKey = "terasology-engine-last-fetched"; | ||
| const dataKey = "terasology-engine-data"; | ||
|
Comment on lines
+51
to
+52
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the caches are scoped for the plugins individually, so prefixing is not strictly required. This applies to the other plugin as well, so that's rather a note to self here...
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. guess if we plan to merge the plugins anyway, we can make use of the prefix for scoping then, so keeping it for now. |
||
|
|
||
| const now = DateTime.utc(); | ||
| const lastFetched = DateTime.fromISO(await cache.get(lastFetchedKey), { | ||
| zone: "utc", | ||
| }); | ||
|
|
||
| let engine = {}; | ||
|
|
||
| // Temporary hack to avoid fetching data from GitHub during local testing. | ||
| // Un-/comment as needed after changing the query. | ||
| if (fs.existsSync(`${__dirname}/data.json`)) { | ||
| // engine = JSON.parse(fs.readFileSync(`${__dirname}/data.json`)); | ||
| } | ||
|
|
||
| if (lastFetched.plus({ hours: 12 }) > now) { | ||
| reporter.info( | ||
| `[${PLUGIN_NAME}] Loading Terasology engine info from cache ...` | ||
| ); | ||
| engine = JSON.parse(await cache.get(dataKey)); | ||
| } else { | ||
| reporter.info( | ||
| `[${PLUGIN_NAME}] Fetching Terasology engine info from GitHub ...` | ||
| ); | ||
|
|
||
| const { organization } = await gql(query); | ||
| engine = organization.repository; | ||
|
|
||
| await cache.set(dataKey, JSON.stringify(engine)); | ||
| await cache.set(lastFetchedKey, now.toISO()); | ||
|
|
||
| fs.writeFileSync(`${__dirname}/data.json`, JSON.stringify(engine, null, 2)); | ||
| } | ||
|
|
||
| reporter.success(`[${PLUGIN_NAME}] Loaded Terasology engine info.`); | ||
|
|
||
| const node = { | ||
| id: createNodeId(`TerasologyEngine`), | ||
| issues: engine.issues, | ||
| parent: "__SOURCE__", | ||
| children: [], | ||
| internal: { | ||
| type: "TerasologyEngine", | ||
| }, | ||
| }; | ||
|
|
||
| node.internal.contentDigest = createContentDigest(node); | ||
|
|
||
| createNode(node); | ||
|
|
||
| reporter.success(`[${PLUGIN_NAME}] Created node for Terasology engine.`); | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| // noop |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| { | ||
| "name": "source-terasology-engine", | ||
| "version": "0.0.1", | ||
| "private": true, | ||
| "description": "A Gatsby source plugin to fetch Terasology engine information.", | ||
| "main": "index.js", | ||
| "scripts": { | ||
| "test": "echo \"Error: no test specified\" && exit 1", | ||
| "build": "echo \"No build script setup\"" | ||
| }, | ||
| "keywords": [ | ||
| "gatsby", | ||
| "gatsby-plugin" | ||
| ], | ||
| "author": "The Terasology Foundation <terasology@gmail.com>", | ||
| "dependencies": { | ||
| "@octokit/graphql": "^5.0.4", | ||
| "gatsby-source-filesystem": "^5.3.1", | ||
| "luxon": "^3.2.0" | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we only fetching the first ten issues here? This seems to be quite a few, and even if we fetch more we can still decide to only display a few on the page...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's change this to fetching all of them with respective pagination in a follow-up PR