You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aurora.apache.org by dm...@apache.org on 2017/08/24 23:47:33 UTC

aurora git commit: Add build and unit test pipeline for new Scheduler UI (using Preact).

Repository: aurora
Updated Branches:
  refs/heads/master 62e46cdea -> 364eac5d1


Add build and unit test pipeline for new Scheduler UI (using Preact).

Reviewed at https://reviews.apache.org/r/61864/


Project: http://git-wip-us.apache.org/repos/asf/aurora/repo
Commit: http://git-wip-us.apache.org/repos/asf/aurora/commit/364eac5d
Tree: http://git-wip-us.apache.org/repos/asf/aurora/tree/364eac5d
Diff: http://git-wip-us.apache.org/repos/asf/aurora/diff/364eac5d

Branch: refs/heads/master
Commit: 364eac5d1690e51e9796c712e4fd5f09977ccd2a
Parents: 62e46cd
Author: David McLaughlin <da...@dmclaughlin.com>
Authored: Thu Aug 24 16:40:38 2017 -0700
Committer: David McLaughlin <da...@dmclaughlin.com>
Committed: Thu Aug 24 16:40:38 2017 -0700

----------------------------------------------------------------------
 .gitignore                                      |  4 +
 build.gradle                                    | 79 +++++++++++---------
 settings.gradle                                 |  2 +-
 .../scheduler/http/JettyServerModule.java       |  1 +
 .../scheduler/assets/scheduler/new-index.html   | 31 ++++++++
 ui/.babelrc                                     |  3 +
 ui/.eslintrc                                    | 29 +++++++
 ui/karma.conf.js                                | 23 ++++++
 ui/package.json                                 | 52 +++++++++++++
 ui/src/main/js/components/Home.js               |  4 +
 .../main/js/components/__tests__/Home-test.js   | 12 +++
 ui/src/main/js/index.js                         | 21 ++++++
 ui/webpack.config.js                            | 42 +++++++++++
 13 files changed, 268 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/aurora/blob/364eac5d/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index b4e2bcb..2f24af5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@
 *.iws
 *.pyc
 *~
+*bundle.js*
 .gradle
 /.cache/
 /.coverage
@@ -33,3 +34,6 @@
 /out/
 /requirements.txt
 /third_party/
+/ui/dist/
+/ui/node_modules/
+/ui/out/

http://git-wip-us.apache.org/repos/asf/aurora/blob/364eac5d/build.gradle
----------------------------------------------------------------------
diff --git a/build.gradle b/build.gradle
index c2c402f..0467338 100644
--- a/build.gradle
+++ b/build.gradle
@@ -18,6 +18,7 @@ plugins {
   id 'com.eriwen.gradle.js' version '1.12.1'
   id 'com.github.ben-manes.versions' version '0.11.3'
   id 'com.github.hierynomus.license' version '0.11.0'
+  id 'com.moowork.node' version '1.1.1'
   id 'me.champeau.gradle.jmh' version '0.2.0'
 }
 
@@ -130,6 +131,50 @@ For more details, please see https://issues.apache.org/jira/browse/AURORA-1169
   }
 }
 
+/**
+ * This gradle project contains the logic to bootstrap and build the UI bundle using NodeJS.
+ * The core logic of UI building is delegated to npm and Webpack. Webpack writes the UI bundle
+ * into the resources directory of the Scheduler, so it must be built before the Scheduler.
+ */
+project(':ui') {
+  apply plugin: 'com.moowork.node'
+  node {
+    download = true
+  }
+
+  task test(type: NpmTask, overwrite: true) {
+    inputs.files(fileTree('src'))
+    outputs.files(fileTree('dist'))
+    args = ['test']
+  }
+
+  task install(type: NpmTask) {
+    inputs.files(file('package.json'))
+    outputs.files(fileTree('node_modules'))
+    // Install into the project dir to sandbox everything under ui/
+    args = ['install']
+  }
+
+  task lint(type: NpmTask, dependsOn: 'install') {
+    inputs.files(fileTree('src'))
+    outputs.files(fileTree('.'))
+    args = ['run-script', 'lint']
+  }
+
+  task webpack(type: NodeTask, dependsOn: 'install') {
+    inputs.files(fileTree('src'))
+    outputs.files(sourceSets.main.java)
+    script = file('node_modules/.bin/webpack')
+  }
+
+  tasks.build.dependsOn(lint)
+  tasks.build.dependsOn(webpack)
+  tasks.build.dependsOn(npm_test)
+}
+// Make sure UI webpack is run as part of 'processResources --continuous'. Also makes sure when
+// building the Scheduler JAR, the JS bundle is built first.
+tasks.processResources.dependsOn(':ui:webpack')
+
 /* This gradle project contains the annotation procesor from
  * com.twitter.common.args and related dependencies. It needs to be outside of
  * the commons project because gradle needs to compile the annotation processor
@@ -447,40 +492,6 @@ pmdTest {
   ruleSetFiles = files('config/pmd/common.xml', 'config/pmd/test.xml')
 }
 
-/**
- * There is a jshint target recommended in the README for gradle-js-plugin
- * but it does not work. This workaround from here:
- * https://github.com/eriwen/gradle-js-plugin/issues/73
- */
-task jsHint(type:com.eriwen.gradle.js.tasks.JsHintTask) {
-  source = fileTree("src/main/resources/$httpAssetsPath/js/")
-  dest file("${buildDir}/jshint.out")
-  // Set this to false once JS code complies with JSHint.
-  ignoreExitCode false
-  outputToStdOut true
-  jshint.options = [
-    // See: http://www.jshint.com/docs/options/ for explanation.
-    browser: true,
-    camelcase: true,
-    curly: true,
-    eqeqeq: true,
-    indent: 2,
-    maxlen: 100,
-    quotmark: true,
-    trailing: true,
-    undef: true,
-    unused: 'vars',
-    white: true
-  ]
-  jshint.predef = [
-    '_': true,
-    'angular': true,
-    'moment': true,
-    'Thrift': true
-  ]
-}
-tasks.checkstyleMain.dependsOn(jsHint)
-
 tasks.withType(Test) {
   maxParallelForks = Runtime.runtime.availableProcessors()
 }

http://git-wip-us.apache.org/repos/asf/aurora/blob/364eac5d/settings.gradle
----------------------------------------------------------------------
diff --git a/settings.gradle b/settings.gradle
index b097e2f..264426d 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -12,4 +12,4 @@
  * limitations under the License.
  */
 rootProject.name = 'aurora'
-include 'api', 'buildSrc', 'commons-args', 'commons'
+include 'ui', 'api', 'buildSrc', 'commons-args', 'commons'

http://git-wip-us.apache.org/repos/asf/aurora/blob/364eac5d/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java b/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java
index f7e72e7..e29bb41 100644
--- a/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java
+++ b/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java
@@ -324,6 +324,7 @@ public class JettyServerModule extends AbstractModule {
             .put("/graphview(?:/index.html)?", "/assets/graphview/graphview.html")
             .put("/graphview/(.*)", "/assets/graphview/$1")
             .put("/(?:scheduler|updates)(?:/.*)?", "/assets/scheduler/index.html")
+            .put("/beta/(?:scheduler|updates)(?:/.*)?", "/assets/scheduler/new-index.html")
             .put("/slaves", "/agents")
             .build();
 

http://git-wip-us.apache.org/repos/asf/aurora/blob/364eac5d/src/main/resources/scheduler/assets/scheduler/new-index.html
----------------------------------------------------------------------
diff --git a/src/main/resources/scheduler/assets/scheduler/new-index.html b/src/main/resources/scheduler/assets/scheduler/new-index.html
new file mode 100644
index 0000000..d59a6f5
--- /dev/null
+++ b/src/main/resources/scheduler/assets/scheduler/new-index.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<!--
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+      http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<html lang='en'>
+  <head>
+    <meta charset='utf-8'>
+    <meta name='google' value='notranslate'>
+    <link rel='icon' href='/assets/images/aurora.png' type='image/png'/>
+    <title>Aurora</title>
+    <!-- Load our css at the end so we can override bootstrap css properties as needed -->
+    <link href='/assets/bower_components/bootstrap/dist/css/bootstrap.min.css' rel='stylesheet'>
+  </head>
+  <body>
+    <div id="root"></div>
+    <script src='/assets/bower_components/jquery/dist/jquery.js'></script>
+    <!-- Thrift -->
+    <script src='/assets/js/thrift.js'></script>
+    <script src='/apiclient/api_types.js'></script>
+    <script src='/apiclient/ReadOnlyScheduler.js'></script>
+    <script src="/assets/js/bundle.js"></script>
+  </body>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/aurora/blob/364eac5d/ui/.babelrc
----------------------------------------------------------------------
diff --git a/ui/.babelrc b/ui/.babelrc
new file mode 100644
index 0000000..86c445f
--- /dev/null
+++ b/ui/.babelrc
@@ -0,0 +1,3 @@
+{
+  "presets": ["es2015", "react"]
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/364eac5d/ui/.eslintrc
----------------------------------------------------------------------
diff --git a/ui/.eslintrc b/ui/.eslintrc
new file mode 100644
index 0000000..355b6a8
--- /dev/null
+++ b/ui/.eslintrc
@@ -0,0 +1,29 @@
+{
+  // babel parser to support ES features
+  "parser": "babel-eslint",
+  "extends": [
+    "standard",
+    "standard-react"
+  ],
+  "globals": {
+    "Thrift": true,
+    "ReadOnlySchedulerClient"
+  },
+  "rules": {
+    "arrow-parens": [2, "always"],
+    // not covered in standard
+    "no-var": 2,
+    "prefer-const": 2,
+    // overrides of the standard style
+    "curly": [2, "all"],
+    "max-len": [2, 100, 4],
+    "semi": [2, "always"],
+    "space-before-function-paren": [2, {"anonymous": "always", "named": "never"}],
+    "wrap-iife": [2, "outside"],
+    // overrides of the standard-react style
+    "react/jsx-sort-props": 2,
+    "react/prop-types": 0,
+    "react/sort-prop-types": 2,
+    "camelcase": [2, {"properties": "never"}],
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/364eac5d/ui/karma.conf.js
----------------------------------------------------------------------
diff --git a/ui/karma.conf.js b/ui/karma.conf.js
new file mode 100644
index 0000000..d42cda7
--- /dev/null
+++ b/ui/karma.conf.js
@@ -0,0 +1,23 @@
+var webpackConfig = require('./webpack.config.js');
+
+module.exports = function(config) {
+  config.set({
+    basePath: '',
+    frameworks: ['jasmine'],
+    files: [
+      'src/**/*-test.js'
+    ],
+    preprocessors: {
+      'src/**/*-test.js': ['webpack']
+    },
+    reporters: ['spec'],
+    webpack: webpackConfig,
+    port: 9876,
+    colors: true,
+    logLevel: config.LOG_INFO,
+    autoWatch: true,
+    browsers: ['PhantomJS'],
+    singleRun: true,
+    concurrency: Infinity
+  })
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/364eac5d/ui/package.json
----------------------------------------------------------------------
diff --git a/ui/package.json b/ui/package.json
new file mode 100644
index 0000000..f712518
--- /dev/null
+++ b/ui/package.json
@@ -0,0 +1,52 @@
+{
+  "name": "apache-aurora",
+  "version": "1.0.0",
+  "description": "UI project for Apache Aurora",
+  "main": "index.js",
+  "dependencies": {
+    "preact": "^8.2.1",
+    "preact-compat": "^3.17.0",
+    "react-router-dom": "^4.1.2"
+  },
+  "devDependencies": {
+    "babel-core": "^6.26.0",
+    "babel-eslint": "^7.2.3",
+    "babel-loader": "^7.1.1",
+    "babel-plugin-react-transform": "^2.0.2",
+    "babel-plugin-transform-react-jsx": "^6.24.1",
+    "babel-preset-es2015": "^6.24.1",
+    "babel-preset-react": "^6.24.1",
+    "chai": "^4.1.1",
+    "css-loader": "^0.28.5",
+    "eslint": "^4.4.1",
+    "eslint-config-standard": "^10.2.1",
+    "eslint-config-standard-react": "^5.0.0",
+    "eslint-plugin-import": "^2.7.0",
+    "eslint-plugin-node": "^5.1.1",
+    "eslint-plugin-promise": "^3.5.0",
+    "eslint-plugin-react": "^7.2.1",
+    "eslint-plugin-standard": "^3.0.1",
+    "jasmine-core": "^2.7.0",
+    "karma": "^1.7.0",
+    "karma-cli": "^1.0.1",
+    "karma-jasmine": "^1.1.0",
+    "karma-phantomjs-launcher": "^1.0.4",
+    "karma-spec-reporter": "0.0.31",
+    "karma-webpack": "^2.0.4",
+    "node-sass": "^4.5.3",
+    "preact-jsx-chai": "^2.2.1",
+    "sass-loader": "^6.0.6",
+    "style-loader": "^0.18.2",
+    "webpack": "^2.6.1"
+  },
+  "scripts": {
+    "lint": "eslint ui/src/main/js --ext .js",
+    "test": "NODE_ENV=test karma start karma.conf.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://git-wip-us.apache.org/repos/asf/aurora"
+  },
+  "author": "",
+  "license": "Apache-2.0"
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/364eac5d/ui/src/main/js/components/Home.js
----------------------------------------------------------------------
diff --git a/ui/src/main/js/components/Home.js b/ui/src/main/js/components/Home.js
new file mode 100644
index 0000000..91d60b3
--- /dev/null
+++ b/ui/src/main/js/components/Home.js
@@ -0,0 +1,4 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+
+export default () => <div>Hello, World!</div>;

http://git-wip-us.apache.org/repos/asf/aurora/blob/364eac5d/ui/src/main/js/components/__tests__/Home-test.js
----------------------------------------------------------------------
diff --git a/ui/src/main/js/components/__tests__/Home-test.js b/ui/src/main/js/components/__tests__/Home-test.js
new file mode 100644
index 0000000..2a80958
--- /dev/null
+++ b/ui/src/main/js/components/__tests__/Home-test.js
@@ -0,0 +1,12 @@
+import React from 'react';
+import Home from '../Home';
+
+import chai, { expect } from 'chai';
+import assertJsx from 'preact-jsx-chai';
+chai.use(assertJsx);
+
+describe('Home', () => {
+  it('Should render Hello, World!', () => {
+    expect(<Home/>).to.deep.equal(<div>Hello, World!</div>);
+  });
+});

http://git-wip-us.apache.org/repos/asf/aurora/blob/364eac5d/ui/src/main/js/index.js
----------------------------------------------------------------------
diff --git a/ui/src/main/js/index.js b/ui/src/main/js/index.js
new file mode 100644
index 0000000..2f7467b
--- /dev/null
+++ b/ui/src/main/js/index.js
@@ -0,0 +1,21 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { BrowserRouter as Router, Route } from 'react-router-dom';
+
+import Home from 'components/Home';
+
+const SchedulerUI = () => (
+  <Router>
+    <div>
+      <Route component={Home} exact path='/beta/scheduler' />
+      <Route component={Home} exact path='/beta/scheduler/:role' />
+      <Route component={Home} exact path='/beta/scheduler/:role/:environment' />
+      <Route component={Home} exact path='/beta/scheduler/:role/:environment/:name' />
+      <Route component={Home} exact path='/beta/scheduler/:role/:environment/:name/:instance' />
+      <Route component={Home} exact path='/beta/scheduler/:role/:environment/:name/update/:uid' />
+      <Route component={Home} exact path='/beta/updates' />
+    </div>
+  </Router>
+);
+
+ReactDOM.render(<SchedulerUI />, document.getElementById('root'));

http://git-wip-us.apache.org/repos/asf/aurora/blob/364eac5d/ui/webpack.config.js
----------------------------------------------------------------------
diff --git a/ui/webpack.config.js b/ui/webpack.config.js
new file mode 100644
index 0000000..e7cd672
--- /dev/null
+++ b/ui/webpack.config.js
@@ -0,0 +1,42 @@
+var path = require('path');
+var webpack = require('webpack');
+
+var SOURCE_PATH = path.resolve(__dirname, 'src/main/js');
+var EXTENSION_PATH = path.resolve(__dirname, 'plugin/js')
+
+module.exports = {
+  devtool: 'source-map',
+  entry: './src/main/js/index',
+  output: {
+    path:  path.resolve(__dirname, '../src/main/resources/scheduler/assets/js'),
+    filename: 'bundle.js',
+    publicPath: '/'
+  },
+  resolve: {
+    alias: {
+      react: "preact-compat",
+      "react-dom": "preact-compat"
+    },
+    extensions: [ '.js' ],
+    modules: [EXTENSION_PATH, SOURCE_PATH, 'node_modules']
+  },
+  module: {
+    rules: [{
+        test: /\.js?$/,
+        loaders: ['babel-loader'],
+        include: [EXTENSION_PATH, SOURCE_PATH]
+      }, {
+      test: /\.scss$/,
+      use: [{
+        loader: 'style-loader'
+      }, {
+        loader: 'css-loader'
+      }, {
+        loader: 'sass-loader',
+        options: {
+          includePaths: [path.resolve(__dirname, 'src/main/sass')]
+        }
+      }]
+    }]
+  }
+};