Configure fe2 to load from instances (#1856)
This modifies the frontend2 so that we can load real data from cli2 instances, including: - the root `sourcecred.json` config - files inside the `config/` directory - files inside the `output/` directory This works both for the dev server and the compiled output. In the case of the dev server, it's now necessary to provide the path to the cli2 instance you're developing against. You can pass this via the `--instance` argument, as in `yarn start2 --instance=/path/`, or via the `$SOURCECRED_DEV_INSTANCE` environment variable (recommended). If neither is provided, or if that path doesn't look like a valid instance, an error is thrown. In the case of the built output, given a valid sc2 instance, you can set it up via the following: ``` cp -r build2/favicon.png build2/index.html build2/static $INSTANCE ``` Then spin up a simple http server in the $INSTANCE. You can look at console messages in the frontend to verify that the instance is working (note it expects to see a discourse config file, not a GitHub config file as was used in some previous examples). Test plan: Setup an example Discourse instance, and then turn on the server via `yarn start2 --instance=PATH`, `SOURCECRED_DEV_INSTANCE=path yarn start2`, and by manually copying in the built outputs using the instructions above. In each case, you can load the homepage and check the console to see that assets loaded successfully.
This commit is contained in:
parent
cb637dbaa4
commit
e6a3d776ab
|
@ -6,8 +6,8 @@ import type {
|
|||
$Response as ExpressResponse,
|
||||
} from "express";
|
||||
*/
|
||||
const os = require("os");
|
||||
const path = require("path");
|
||||
const fs = require("fs-extra");
|
||||
const webpack = require("webpack");
|
||||
const RemoveBuildDirectoryPlugin = require("./RemoveBuildDirectoryPlugin");
|
||||
const CopyPlugin = require("copy-webpack-plugin");
|
||||
|
@ -40,18 +40,55 @@ async function makeConfig(
|
|||
devServer: {
|
||||
inline: false,
|
||||
before: (app /*: ExpressApp */) => {
|
||||
const apiRoot = "/api/v1/data";
|
||||
let developmentInstancePath /*: ?string */ =
|
||||
process.env["SOURCECRED_DEV_INSTANCE"];
|
||||
const lastArg = process.argv[process.argv.length - 1];
|
||||
if (lastArg.startsWith("--instance")) {
|
||||
const pieces = lastArg.split("=");
|
||||
developmentInstancePath = pieces[1];
|
||||
}
|
||||
if (developmentInstancePath == null) {
|
||||
throw new Error(
|
||||
"Please provide a SourceCred cli2 instance, via $SOURCECRED_DEV_INSTANCE, or --instance=PATH"
|
||||
);
|
||||
}
|
||||
const configPath = path.join(
|
||||
developmentInstancePath,
|
||||
"sourcecred.json"
|
||||
);
|
||||
if (!fs.existsSync(configPath)) {
|
||||
// Sanity check; we won't try to verify that the right output files are there, since it may change and the
|
||||
// frontend should have helpful error messages in that case. But if there's no sourcecred.json file, then
|
||||
// it's likely the developer has made a mistake and would find a quick failure helpful.
|
||||
throw new Error(
|
||||
`Provided instance directory ${developmentInstancePath} doesn't have a sourcecred.json file`
|
||||
);
|
||||
}
|
||||
|
||||
const configContents = fs.readFileSync(configPath);
|
||||
const serveConfig = (_unused_req, res /*: ExpressResponse */) => {
|
||||
res.status(200).send(configContents);
|
||||
};
|
||||
const rejectCache = (_unused_req, res /*: ExpressResponse */) => {
|
||||
res.status(400).send("Bad Request: Cache unavailable at runtime\n");
|
||||
};
|
||||
app.get(`${apiRoot}/cache`, rejectCache);
|
||||
app.get(`${apiRoot}/cache/*`, rejectCache);
|
||||
|
||||
app.get("/sourcecred.json", serveConfig);
|
||||
app.get(`/cache`, rejectCache);
|
||||
app.get(`/cache/*`, rejectCache);
|
||||
|
||||
// It's important that we individually whitelist directories (and the
|
||||
// sourcecred.json file) rather than indiscriminately serving from
|
||||
// root, because there might be a "permanent" frontend installed in
|
||||
// that instance, and we don't want to accidentally load the existing
|
||||
// frontend instead of our development copy.
|
||||
app.use(
|
||||
apiRoot,
|
||||
express.static(
|
||||
process.env.SOURCECRED_DIRECTORY ||
|
||||
path.join(os.tmpdir(), "sourcecred")
|
||||
)
|
||||
"/output/",
|
||||
express.static(path.join(developmentInstancePath, "output"))
|
||||
);
|
||||
app.use(
|
||||
"/config/",
|
||||
express.static(path.join(developmentInstancePath, "config"))
|
||||
);
|
||||
},
|
||||
},
|
||||
|
|
|
@ -5,7 +5,23 @@ import React from "react";
|
|||
import type {Assets} from "../webutil/assets";
|
||||
import {StyleSheet, css} from "aphrodite/no-important";
|
||||
|
||||
async function loadAndReport(assets, path) {
|
||||
const url = assets.resolve(path);
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
console.error(path, response);
|
||||
}
|
||||
const json = await response.json();
|
||||
console.log(path, json);
|
||||
}
|
||||
|
||||
export default class HomePage extends React.Component<{|+assets: Assets|}> {
|
||||
async componentDidMount() {
|
||||
loadAndReport(this.props.assets, "sourcecred.json");
|
||||
loadAndReport(this.props.assets, "output/credResult.json");
|
||||
loadAndReport(this.props.assets, "config/sourcecred/discourse/config.json");
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className={css(styles.container)}>
|
||||
|
|
Loading…
Reference in New Issue