2018-05-08 21:56:06 +00:00
|
|
|
|
// @flow
|
2018-08-16 20:38:13 +00:00
|
|
|
|
const {spawnSync, execFileSync} = require("child_process");
|
2018-02-18 16:13:29 +00:00
|
|
|
|
const fs = require("fs");
|
2018-08-16 20:38:13 +00:00
|
|
|
|
const stringify = require("json-stable-stringify");
|
2018-02-18 16:13:29 +00:00
|
|
|
|
const path = require("path");
|
2018-08-16 20:38:13 +00:00
|
|
|
|
|
2018-02-18 16:13:29 +00:00
|
|
|
|
const paths = require("./paths");
|
2018-02-17 21:28:47 +00:00
|
|
|
|
|
2018-11-01 17:19:51 +00:00
|
|
|
|
/*:: import type {GitState} from "../src/homepage/version"; */
|
2018-08-16 20:38:13 +00:00
|
|
|
|
|
2018-02-17 21:28:47 +00:00
|
|
|
|
// Make sure that including paths.js after env.js will read .env variables.
|
2018-02-18 16:13:29 +00:00
|
|
|
|
delete require.cache[require.resolve("./paths")];
|
2018-02-17 21:28:47 +00:00
|
|
|
|
|
|
|
|
|
const NODE_ENV = process.env.NODE_ENV;
|
|
|
|
|
if (!NODE_ENV) {
|
|
|
|
|
throw new Error(
|
2018-02-18 16:13:29 +00:00
|
|
|
|
"The NODE_ENV environment variable is required but was not specified."
|
2018-02-17 21:28:47 +00:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
|
|
|
|
|
var dotenvFiles = [
|
|
|
|
|
`${paths.dotenv}.${NODE_ENV}.local`,
|
|
|
|
|
`${paths.dotenv}.${NODE_ENV}`,
|
|
|
|
|
// Don't include `.env.local` for `test` environment
|
|
|
|
|
// since normally you expect tests to produce the same
|
|
|
|
|
// results for everyone
|
2018-05-08 21:56:06 +00:00
|
|
|
|
...(NODE_ENV !== "test" ? [`${paths.dotenv}.local`] : []),
|
2018-02-17 21:28:47 +00:00
|
|
|
|
paths.dotenv,
|
2018-05-08 21:56:06 +00:00
|
|
|
|
];
|
2018-02-17 21:28:47 +00:00
|
|
|
|
|
|
|
|
|
// Load environment variables from .env* files. Suppress warnings using silent
|
|
|
|
|
// if this file is missing. dotenv will never modify any environment variables
|
|
|
|
|
// that have already been set. Variable expansion is supported in .env files.
|
|
|
|
|
// https://github.com/motdotla/dotenv
|
|
|
|
|
// https://github.com/motdotla/dotenv-expand
|
2018-02-18 16:13:29 +00:00
|
|
|
|
dotenvFiles.forEach((dotenvFile) => {
|
2018-02-17 21:28:47 +00:00
|
|
|
|
if (fs.existsSync(dotenvFile)) {
|
2018-02-18 16:13:29 +00:00
|
|
|
|
require("dotenv-expand")(
|
|
|
|
|
require("dotenv").config({
|
2018-02-17 21:28:47 +00:00
|
|
|
|
path: dotenvFile,
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// We support resolving modules according to `NODE_PATH`.
|
|
|
|
|
// This lets you use absolute paths in imports inside large monorepos:
|
|
|
|
|
// https://github.com/facebookincubator/create-react-app/issues/253.
|
|
|
|
|
// It works similar to `NODE_PATH` in Node itself:
|
|
|
|
|
// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
|
|
|
|
|
// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.
|
|
|
|
|
// Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims.
|
|
|
|
|
// https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421
|
|
|
|
|
// We also resolve them to make sure all tools using them work consistently.
|
|
|
|
|
const appDirectory = fs.realpathSync(process.cwd());
|
2018-02-18 16:13:29 +00:00
|
|
|
|
process.env.NODE_PATH = (process.env.NODE_PATH || "")
|
2018-02-17 21:28:47 +00:00
|
|
|
|
.split(path.delimiter)
|
2018-02-18 16:13:29 +00:00
|
|
|
|
.filter((folder) => folder && !path.isAbsolute(folder))
|
|
|
|
|
.map((folder) => path.resolve(appDirectory, folder))
|
2018-02-17 21:28:47 +00:00
|
|
|
|
.join(path.delimiter);
|
|
|
|
|
|
2018-08-16 20:38:13 +00:00
|
|
|
|
// Get the state of the SourceCred Git repository. This requires that
|
|
|
|
|
// Git be installed. If this fails for you, please install Git.
|
|
|
|
|
//
|
|
|
|
|
// If the dependency on Git becomes a problem, we can consider making
|
|
|
|
|
// this optional. However, note that this computation is performed at
|
|
|
|
|
// build time, so end users of SourceCred as a library or application
|
|
|
|
|
// should not need this dependency.
|
|
|
|
|
function getGitState() /*: GitState */ {
|
|
|
|
|
const env = {
|
env: pass parent PATH to Git invocations (#900)
Summary:
Our environment-stripping logic used in `config/env.js` to read the
current Git state included stripping the `PATH` environment variable.
This had the effect that the system Git executable would always be used
in preference to a user-installed version.
Test Plan:
Run `/usr/bin/git --version`, and then install a different version of
Git. (For instance, check out an old tag, then `make && make install`
from the `git/git` repository.) Then, add
```js
console.log(execFileSync("git", ["--version"], {env}).toString());
```
to `getGitState` in `config/env.js`, and run
NODE_ENV=development node ./config/env.js
Note that this prints the version of the system Git before this change,
and the user Git after this change.
Alternately, local-install a version of Git earlier than 2.6.0, and note
that `yarn unit` now _fails_ because the `--date=format:…` syntax is not
known to such versions of Git. Prior to this commit, the tests would
pass as long as the system Git were more recent.
wchargin-branch: env-git-path
2018-10-02 00:52:56 +00:00
|
|
|
|
GIT_ATTR_NOSYSTEM: "1",
|
|
|
|
|
GIT_CONFIG_NOSYSTEM: "1",
|
2018-08-16 20:38:13 +00:00
|
|
|
|
LANG: "C",
|
|
|
|
|
LC_ALL: "C",
|
env: pass parent PATH to Git invocations (#900)
Summary:
Our environment-stripping logic used in `config/env.js` to read the
current Git state included stripping the `PATH` environment variable.
This had the effect that the system Git executable would always be used
in preference to a user-installed version.
Test Plan:
Run `/usr/bin/git --version`, and then install a different version of
Git. (For instance, check out an old tag, then `make && make install`
from the `git/git` repository.) Then, add
```js
console.log(execFileSync("git", ["--version"], {env}).toString());
```
to `getGitState` in `config/env.js`, and run
NODE_ENV=development node ./config/env.js
Note that this prints the version of the system Git before this change,
and the user Git after this change.
Alternately, local-install a version of Git earlier than 2.6.0, and note
that `yarn unit` now _fails_ because the `--date=format:…` syntax is not
known to such versions of Git. Prior to this commit, the tests would
pass as long as the system Git were more recent.
wchargin-branch: env-git-path
2018-10-02 00:52:56 +00:00
|
|
|
|
PATH: process.env.PATH,
|
2018-08-16 20:38:13 +00:00
|
|
|
|
TZ: "UTC",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const diffIndex = spawnSync(
|
|
|
|
|
"git",
|
|
|
|
|
["-C", __dirname, "diff-index", "--quiet", "HEAD", "--"],
|
|
|
|
|
{env}
|
|
|
|
|
);
|
|
|
|
|
const dirty = diffIndex.status !== 0;
|
|
|
|
|
if (diffIndex.status !== 0 && diffIndex.status !== 1) {
|
|
|
|
|
throw new Error(diffIndex.status + ": " + diffIndex.stderr.toString());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const commitHash = execFileSync(
|
|
|
|
|
"git",
|
|
|
|
|
["-C", __dirname, "rev-parse", "--short=12", "--verify", "HEAD"],
|
|
|
|
|
{env}
|
|
|
|
|
)
|
|
|
|
|
.toString()
|
|
|
|
|
.trim();
|
|
|
|
|
|
2018-10-02 01:07:52 +00:00
|
|
|
|
const iso8601Timestamp = execFileSync(
|
2018-08-16 20:38:13 +00:00
|
|
|
|
"git",
|
|
|
|
|
[
|
|
|
|
|
"-C",
|
|
|
|
|
__dirname,
|
|
|
|
|
"show",
|
|
|
|
|
"--no-patch",
|
|
|
|
|
"--format=%cd",
|
2018-10-02 01:07:52 +00:00
|
|
|
|
"--date=iso8601",
|
2018-08-16 20:38:13 +00:00
|
|
|
|
commitHash,
|
|
|
|
|
],
|
|
|
|
|
{env}
|
|
|
|
|
)
|
|
|
|
|
.toString()
|
|
|
|
|
.trim();
|
2018-10-02 01:07:52 +00:00
|
|
|
|
const commitDate = new Date(iso8601Timestamp);
|
|
|
|
|
function zeroPad(number /*: number */, length /*: number */) /*: string */ {
|
|
|
|
|
return String(number).padStart(length, "0");
|
|
|
|
|
}
|
|
|
|
|
const commitTimestamp = [
|
|
|
|
|
zeroPad(commitDate.getFullYear(), 4),
|
2018-10-31 00:24:39 +00:00
|
|
|
|
zeroPad(commitDate.getMonth() + 1, 2),
|
|
|
|
|
zeroPad(commitDate.getDate(), 2),
|
2018-10-02 01:07:52 +00:00
|
|
|
|
"-",
|
|
|
|
|
zeroPad(commitDate.getHours(), 2),
|
|
|
|
|
zeroPad(commitDate.getMinutes(), 2),
|
|
|
|
|
].join("");
|
2018-08-16 20:38:13 +00:00
|
|
|
|
|
|
|
|
|
return {commitHash, commitTimestamp, dirty};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const SOURCECRED_GIT_STATE = stringify(getGitState());
|
|
|
|
|
process.env.SOURCECRED_GIT_STATE = SOURCECRED_GIT_STATE;
|
|
|
|
|
|
2018-08-29 22:06:12 +00:00
|
|
|
|
const SOURCECRED_FEEDBACK_URL =
|
|
|
|
|
process.env.SOURCECRED_FEEDBACK_URL != null
|
|
|
|
|
? process.env.SOURCECRED_FEEDBACK_URL
|
|
|
|
|
: "https://discuss.sourcecred.io/c/cred-feedback/";
|
|
|
|
|
process.env.SOURCECRED_FEEDBACK_URL = SOURCECRED_FEEDBACK_URL;
|
|
|
|
|
|
2018-08-16 18:19:09 +00:00
|
|
|
|
function getClientEnvironment() {
|
2018-08-16 18:27:37 +00:00
|
|
|
|
const raw = {};
|
|
|
|
|
// Useful for determining whether we’re running in production mode.
|
|
|
|
|
// Most importantly, it switches React into the correct mode.
|
|
|
|
|
raw.NODE_ENV = process.env.NODE_ENV || "development";
|
2018-08-16 20:38:13 +00:00
|
|
|
|
// Used by `src/app/version.js`.
|
|
|
|
|
raw.SOURCECRED_GIT_STATE = SOURCECRED_GIT_STATE;
|
2018-08-29 22:06:12 +00:00
|
|
|
|
// Used by `src/app/credExplorer/App.js`.
|
|
|
|
|
raw.SOURCECRED_FEEDBACK_URL = SOURCECRED_FEEDBACK_URL;
|
2018-08-16 18:27:37 +00:00
|
|
|
|
|
|
|
|
|
// Stringify all values so we can feed into Webpack's DefinePlugin.
|
|
|
|
|
const stringified = {"process.env": {}};
|
2018-08-31 23:34:18 +00:00
|
|
|
|
const individuallyStringified = {};
|
2018-08-16 18:27:37 +00:00
|
|
|
|
for (const key of Object.keys(raw)) {
|
2018-08-31 23:34:18 +00:00
|
|
|
|
const value = JSON.stringify(raw[key]);
|
|
|
|
|
stringified["process.env"][key] = value;
|
|
|
|
|
individuallyStringified["process.env." + key] = value;
|
2018-08-16 18:27:37 +00:00
|
|
|
|
}
|
2018-02-17 21:28:47 +00:00
|
|
|
|
|
2018-08-31 23:34:18 +00:00
|
|
|
|
return {raw, stringified, individuallyStringified};
|
2018-02-17 21:28:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
module.exports = getClientEnvironment;
|