Skip to content

Commit

Permalink
Fix update-schema build script
Browse files Browse the repository at this point in the history
Signed-off-by: Neal Granger <[email protected]>
  • Loading branch information
10xjs committed Apr 9, 2019
1 parent 6bfee96 commit 07cdcda
Show file tree
Hide file tree
Showing 10 changed files with 370 additions and 32 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
/build
/stats.json
/dashboard.tgz
/.schema

# misc
.DS_Store
Expand Down
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"spec": "node scripts test.js --env=jsdom",
"start": "NODE_ENV=development yarn build:vendor && NODE_ENV=development yarn dev-server",
"test": "yarn check-version && yarn build && yarn lint && yarn spec --coverage",
"fetch-schema": "node scripts fetch-schema",
"update-schema": "node scripts update-schema",
"upload-artifacts": "node scripts upload-artifacts"
},
Expand All @@ -60,6 +61,8 @@
"@babel/preset-react": "^7.0.0",
"@material-ui/core": "^3.0.0",
"@material-ui/icons": "^3.0.0",
"@octokit/plugin-throttling": "^2.4.0",
"@octokit/rest": "^16.23.2",
"acorn": "^6.1.1",
"acorn-dynamic-import": "^4.0.0",
"add-asset-html-webpack-plugin": "^3.1.3",
Expand Down Expand Up @@ -203,5 +206,6 @@
"graphql-config/**/graphql": "0.13.0",
"graphql-import/**/graphql": "0.13.0",
"js-yaml": "^3.13.0"
}
},
"graphQLSchemaRef": "5a9e138d"
}
134 changes: 134 additions & 0 deletions scripts/fetch-schema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import fs from "fs";
import https from "https";
import path from "path";

import fsPromise from "./fsPromise";
import api from "./githubApi";

import pkg from "../package.json";

const MAX_PARALLEL_REQUESTS = 5;

const schemaDir = path.resolve(".schema");
const lockFilePath = path.join(schemaDir, "lock.json");

const readLockFile = () =>
fsPromise.readFile(lockFilePath, "utf-8").then(
contents => JSON.parse(contents),
error => {
if (error.code === "ENOENT") {
return [];
}
throw error;
},
);

const updateLockFile = contents =>
fsPromise.writeFile(lockFilePath, JSON.stringify(contents, null, 2), "utf-8");

const fetchSchemaContents = (ref = "master") => {
console.log(`fetching graphql schema from sensu-go/${ref}`);
return api.repos
.getContents({
owner: "sensu",
repo: "sensu-go",
path: "backend/apid/graphql/schema",
ref,
})
.then(result => result.data.filter(item => /\.graphql$/.test(item.name)));
};

const fetch = (url, filePath) =>
new Promise((resolve, reject) => {
const done = (error, ...args) => {
if (error) {
reject(error);
} else {
resolve(args);
}
};

const fileStream = fs.createWriteStream(filePath);

const request = https.get(url, response => {
response.pipe(fileStream);
fileStream.on("finish", () => {
fileStream.close(done);
});
});

request.on("error", done);
});

const lockFilePromise = readLockFile();

const exists = filePath =>
fsPromise.stat(filePath).then(
() => true,
error => {
if (error.code === "ENOENT") {
return false;
}
throw error;
},
);

const updateLocal = remoteItem => {
const filePath = path.join(schemaDir, remoteItem.name);

return lockFilePromise
.then(localContents =>
localContents.find(
localItem =>
localItem.name === remoteItem.name &&
localItem.sha === remoteItem.sha,
),
)
.then(currentItem => !!currentItem && exists(filePath))
.then(localFileExists => {
if (!localFileExists) {
console.log("updating local", filePath);
return fetch(remoteItem.download_url, filePath);
}
return Promise.resolve();
});
};

const mapPromiseParallel = (items, max, callback) =>
new Promise((resolve, reject) => {
const remaining = [...items];
const result = [];

let count = 0;

const run = () => {
if (remaining.length === 0 && count === 0) {
resolve(result);
}

if (remaining.length && count < max) {
count += 1;
callback(remaining.pop()).then(() => {
count -= 1;
run();
}, reject);
run();
}
};

run();
});

fsPromise
.mkdir(schemaDir)
.catch(error => {
if (error.code !== "EEXIST") {
throw error;
}
})
.then(() => fetchSchemaContents(pkg.graphQLSchemaRef))
.then(remoteContents =>
mapPromiseParallel(remoteContents, MAX_PARALLEL_REQUESTS, updateLocal)
.then(() => remoteContents.map(({ name, sha }) => ({ name, sha })))
.then(items => updateLockFile(items)),
);
18 changes: 18 additions & 0 deletions scripts/fsPromise.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import fs from "fs";

const callback = (resolve, reject) => (error, ...args) => {
if (error) {
reject(error);
} else {
resolve(args);
}
};

export default Object.keys(fs).reduce((result, key) => {
// eslint-disable-next-line no-param-reassign
result[key] = (...args) =>
new Promise((resolve, reject) => {
fs[key](...args, callback(resolve, reject));
});
return result;
}, {});
28 changes: 28 additions & 0 deletions scripts/githubApi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import OctokitRest from "@octokit/rest";
import OctokitPluginThrottling from "@octokit/plugin-throttling";

OctokitRest.plugin(OctokitPluginThrottling);

export default new OctokitRest({
throttle: {
onRateLimit: (retryAfter, options) => {
console.warn(
`Request quota exhausted for request ${options.method} ${options.url}`,
);

if (options.request.retryCount === 0) {
// only retries once
console.log(`Retrying after ${retryAfter} seconds!`);
return true;
}

return false;
},
onAbuseLimit: (retryAfter, options) => {
// does not retry, only logs a warning
console.warn(
`Abuse detected for request ${options.method} ${options.url}`,
);
},
},
});
2 changes: 1 addition & 1 deletion scripts/update-schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { writeFileSync, readFileSync } from "fs";
import { printSchema, buildASTSchema, extendSchema, parse } from "graphql";
import chalk from "chalk";

const serverSchemaPath = resolve("../backend/apid/graphql/schema/*.graphql");
const serverSchemaPath = resolve(".schema/*.graphql");
const clientSchemaPath = resolve("src/schema/client.graphql");
const combinedFilePath = resolve("src/schema/combined.graphql");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,7 @@ class ClearSilencedEntriesDialog extends React.PureComponent {
id
deleted @client
name
creator {
username
}
creator
}

${SilenceExpiration.fragments.silence}
Expand Down Expand Up @@ -111,7 +109,7 @@ class ClearSilencedEntriesDialog extends React.PureComponent {
</TableOverflowCell>
<TableCell>
<ResourceDetails
title={<Maybe value={silence.creator}>{u => u.username}</Maybe>}
title={<Maybe value={silence.creator} fallback="Unspecified" />}
/>
</TableCell>
</TableSelectableRow>
Expand Down
30 changes: 15 additions & 15 deletions src/app/component/partial/SilencesList/SilencesListItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,7 @@ class SilencesListItem extends React.Component {
name
begin
reason
creator {
username
}
creator
}

${SilenceExpiration.fragments.silence}
Expand Down Expand Up @@ -118,18 +116,20 @@ class SilencesListItem extends React.Component {
}}
>
<Maybe value={silence.creator}>
<Chip
avatar={
<Avatar>
<FaceIcon />
</Avatar>
}
label={silence.creator.username}
style={{
// TODO: ideally have Chip scale to current fontSize(?)
transform: "scale(0.87)",
}}
/>
{creator => (
<Chip
avatar={
<Avatar>
<FaceIcon />
</Avatar>
}
label={creator}
style={{
// TODO: ideally have Chip scale to current fontSize(?)
transform: "scale(0.87)",
}}
/>
)}
</Maybe>
</TableCell>
</Hidden>
Expand Down
28 changes: 27 additions & 1 deletion src/schema/combined.graphql

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 07cdcda

Please sign in to comment.