diff --git a/.buildkite/eslint-formatter-buildkite.js b/.buildkite/eslint-formatter-buildkite.js
new file mode 100644
index 000000000..7acc52da9
--- /dev/null
+++ b/.buildkite/eslint-formatter-buildkite.js
@@ -0,0 +1,108 @@
+const spawnSync = require('child_process').spawnSync;
+const relative = require('path').relative;
+
+module.exports = function(results) {
+ const { warning, error } = results.reduce(
+ function(acc, file) {
+ if (file.errorCount > 0) {
+ acc.error.push(file);
+ }
+
+ if (file.warningCount > 0) {
+ acc.warning.push(file);
+ }
+
+ return acc;
+ },
+ {
+ warning: [],
+ error: []
+ }
+ );
+
+ if (error.length > 0) {
+ let errorOutput = `
+#### ESLint Errors
+
+${
+ error.map(function(file) {
+ return `
+${relative('.', file.filePath)}
+
+${
+ file.messages.map(function(message) {
+ if (message.severity !== 2) {
+ return '';
+ }
+
+ return `${message.line}:${message.column}: ${message.message} (${message.ruleId})`;
+ }).join('\n\n')
+}
+
+ `;
+
+ // return JSON.stringify(file, null, 2);
+ }).join('\n\n')
+}`;
+
+ if (process.env["BUILDKITE"]) {
+ const result = spawnSync(
+ 'buildkite-agent', [ 'annotate', '--context', 'eslint-errors', '--style', 'error', ],
+ { encoding: 'utf8', input: errorOutput }
+ );
+
+ console.log(result.output.join('\n'));
+ console.log('Exit code: ' + result.status);
+
+ if (result.error) {
+ throw result.error;
+ }
+ } else {
+ console.log(errorOutput);
+ }
+ }
+
+ if (warning.length > 0) {
+ let warningOutput = `
+#### ESLint Warnings
+
+${
+ warning.map(function(file) {
+ return `
+${relative('.', file.filePath)}
+
+${
+ file.messages.map(function(message) {
+ if (message.severity > 1) {
+ return '';
+ }
+
+ return `${message.line}:${message.column}: ${message.message} (${message.ruleId})`;
+ }).join('\n\n')
+}
+
+ `;
+
+ // return JSON.stringify(file, null, 2);
+ }).join('\n\n')
+}`;
+
+ if (process.env["BUILDKITE"]) {
+ const result = spawnSync(
+ 'buildkite-agent', [ 'annotate', '--context', 'eslint-warnings', '--style', 'warning' ],
+ { encoding: 'utf8', input: warningOutput }
+ );
+
+ console.log(result.output.join('\n'));
+ console.log('Exit code: ' + result.status);
+
+ if (result.error) {
+ throw result.error;
+ }
+ } else {
+ console.log(warningOutput);
+ }
+ }
+
+ return '';
+};
diff --git a/.buildkite/eslint-formatter-multi.js b/.buildkite/eslint-formatter-multi.js
new file mode 100644
index 000000000..10e0d8d36
--- /dev/null
+++ b/.buildkite/eslint-formatter-multi.js
@@ -0,0 +1,32 @@
+// Pull in ESLint's own "getFormatter" method (https://git.io/fpAqw), which
+// normalises both ESLint's friendly names, npm package names, and files
+// on-disk, and then returns the result of requiring them.
+let getFormatter = require('eslint/lib/cli-engine').prototype.getFormatter.bind({});
+
+module.exports = function(results) {
+ // Since ESLint doesn't give us access to any context or config,
+ // we have to resort to pulling Environment Variables
+ let formatters = (
+ process.env['ESLINT_MULTI_FORMATTERS'].split(';')
+ || [ false ]
+ );
+
+ // Map over each formatter, calling it with the result array we got given,
+ // then return the combination of all the outputs.
+ return formatters
+ .map(function (formatterName) {
+ let formatter = getFormatter(formatterName);
+
+ // TODO: When would this happen, and not just be a thrown error?
+ if (!formatter) {
+ console.debug('Weird! "' + formatterName + '" isn\'t a real formatter...');
+ return;
+ }
+
+ return formatter(results);
+ })
+ .filter(function(output) {
+ return output && output.trim().length > 0;
+ })
+ .join('\n\n');
+};
diff --git a/Dockerfile b/Dockerfile
index 2ee7a401f..b2e478b53 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -4,6 +4,16 @@ EXPOSE 4890
ENV EMOJI_HOST=http://buildkite.localhost/_frontend/vendor/emojis
+ADD --chown=root:root https://apt.buildkite.com/keys/6452D198.asc /etc/apt/trusted.gpg.d/buildkite.asc
+
+RUN echo "--- :package: Installing system deps" \
+ # Buildkite apt sources
+ && chmod 644 /etc/apt/trusted.gpg.d/buildkite.asc \
+ && echo "deb http://apt.buildkite.com/buildkite-agent unstable main" > /etc/apt/sources.list.d/buildkite.list \
+ # Install buildkite-agent
+ && apt-get update \
+ && DEBIAN_FRONTEND=noninteractive apt-get install --assume-yes --no-install-recommends buildkite-agent
+
WORKDIR /frontend
# Install yarn dependencies
diff --git a/app/components/layout/Navigation/index.js b/app/components/layout/Navigation/index.js
index 07cb9b3ff..1576aa72c 100644
--- a/app/components/layout/Navigation/index.js
+++ b/app/components/layout/Navigation/index.js
@@ -82,7 +82,7 @@ class Navigation extends React.PureComponent {
) {
this.setState({
lastDefaultTeam: UserSessionStore.get(`organization-default-team:${nextProps.organization.id}`)
- });
+ })
}
}
diff --git a/docker-compose.yml b/docker-compose.yml
index 7b8321c03..59750c2ac 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -9,8 +9,11 @@ services:
- BUILDKITE_COMMIT
- BUILDKITE_ORGANIZATION_SLUG
- BUILDKITE_PIPELINE_SLUG
+ - BUILDKITE_BUILD_URL
+ - BUILDKITE_JOB_ID
+ - BUILDKITE_AGENT_ACCESS_TOKEN
- CI
volumes:
- "./bundle-analysis:/frontend/bundle-analysis"
- "./coverage:/frontend/coverage"
- - "./dist:/host/dist"
\ No newline at end of file
+ - "./dist:/host/dist"
diff --git a/package.json b/package.json
index b6ad2d38a..c2a37d85b 100644
--- a/package.json
+++ b/package.json
@@ -13,8 +13,8 @@
"test": "NODE_ENV=test jest --colors",
"test-with-coverage": "yarn test --coverage",
"flow": "flow",
- "lint": "eslint . --color",
- "lint-and-fix": "eslint --fix --color .",
+ "lint": "ESLINT_MULTI_FORMATTERS=\"stylish;./.buildkite/eslint-formatter-buildkite.js\" eslint . -f='./.buildkite/eslint-formatter-multi.js' --color",
+ "lint-and-fix": "ESLINT_MULTI_FORMATTERS=\"stylish;./.buildkite/eslint-formatter-buildkite.js\" eslint --fix -f='./.buildkite/eslint-formatter-multi.js' --color .",
"relay-compile": "relay-compiler --schema app/graph/schema.json --src app",
"prebuild": "yarn run relay-compile",
"build": "NODE_ENV=development webpack --config webpack/config.js --progress --bail --cache",