-
Notifications
You must be signed in to change notification settings - Fork 900
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(plugins): able to load plugin stages into UI
This adds the ability to add stages as plugins in the UI. There is an interface for plugin developers to use to create a UI for their stages. The stage UI can be built using ReactJS. When Deck is starting up, it will look to see if any plugins are defined in `spinnakerSettings`. If there are plugins defined, a script tag will be appended to the bottom of the page and the plugin will have its initialized method called. The plugin initialize method takes in the `Registry` so the stage can register itself as a stage. Then the plugin developer has to call `window.spinnakerSettings.onPluginLoaded` with their plugin object. We removed the `ng-app` from `index.deck` because of using `modules` in a promise. The bootstrapping of deck now happens in a separate Javascript file `app/scripts/bootstrap.js`. This script is added to the page via webpack. The reason for this change was tests were failing when calling `bootstrap`. `bootstrap` only happened before when loading the page by hitting `index.deck`. The tests were expecting things to not be loaded, but with `bootstrap` the entire application was loaded. When loading plugins we didn't use CommonJS or ES modules due to keeping the list of supported browsers larger.
- Loading branch information
1 parent
225046c
commit ba56a2a
Showing
15 changed files
with
240 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { bootstrap, element } from 'angular'; | ||
|
||
element(document.documentElement).ready(() => { | ||
bootstrap(document.documentElement, ['netflix.spinnaker']); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"name": "@spinnaker/plugins", | ||
"version": "0.0.1", | ||
"main": "lib/lib.js", | ||
"types": "lib/plugins.d.ts", | ||
"scripts": { | ||
"clean": "../../../../node_modules/rimraf/bin.js lib", | ||
"lib": "npm run clean && ../../../../node_modules/typescript/bin/tsc && node ../../../../node_modules/webpack/bin/webpack.js", | ||
"prepublishOnly": "npm run lib" | ||
}, | ||
"dependencies": { | ||
"@spinnaker/core": "^0.0.406" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
// @ts-ignore | ||
export * from './plugins'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
declare module '@spinnaker/plugins'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { PipelineRegistry } from '@spinnaker/core'; | ||
|
||
export type IPluginInitialize = (registry: IStageRegistry) => void; | ||
|
||
export interface IStageRegistry { | ||
pipeline: PipelineRegistry; | ||
} | ||
|
||
declare global { | ||
interface Window { | ||
spinnakerSettings: any; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
{ | ||
"buildOnSave": false, | ||
"compileOnSave": true, | ||
"compilerOptions": { | ||
"allowJs": false, | ||
"baseUrl": "./src", | ||
"declaration": true, | ||
"declarationDir": "lib", | ||
"emitDecoratorMetadata": true, | ||
"experimentalDecorators": true, | ||
"jsx": "react", | ||
"lib": ["es2016", "dom"], | ||
"moduleResolution": "node", | ||
"module": "esnext", | ||
"noEmitHelpers": false, | ||
"noImplicitAny": true, | ||
"noImplicitReturns": true, | ||
"noImplicitThis": false, // should really get to a place where we can turn this on | ||
"noUnusedLocals": true, | ||
"noUnusedParameters": true, | ||
"outDir": "lib", | ||
"pretty": true, | ||
"removeComments": false, | ||
"rootDir": "./src", | ||
"skipLibCheck": true, | ||
"sourceMap": true, | ||
"inlineSources": true, | ||
"strictNullChecks": false, // should really get to a place where we can turn this on | ||
"target": "es6", | ||
"typeRoots": ["../../../../node_modules/@types"], | ||
"paths": { | ||
"@spinnaker/core": ["../../core/lib"], | ||
"core/*": ["core/src/*"] | ||
} | ||
}, | ||
"files": ["src/index.ts"], | ||
"exclude": ["./lib", "**/*.spec.*"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
'use strict'; | ||
|
||
const path = require('path'); | ||
const basePath = path.join(__dirname, '..', '..', '..', '..'); | ||
const NODE_MODULE_PATH = path.join(basePath, 'node_modules'); | ||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); | ||
const nodeExternals = require('webpack-node-externals'); | ||
const TerserPlugin = require('terser-webpack-plugin'); | ||
const exclusionPattern = /(node_modules|\.\.\/deck)/; | ||
const WEBPACK_THREADS = Math.max(require('physical-cpu-count') - 1, 1); | ||
|
||
const WATCH = process.env.WATCH === 'true'; | ||
const WEBPACK_MODE = WATCH ? 'development' : 'production'; | ||
const IS_PRODUCTION = WEBPACK_MODE === 'production'; | ||
|
||
module.exports = { | ||
context: basePath, | ||
mode: WEBPACK_MODE, | ||
stats: 'minimal', | ||
watch: WATCH, | ||
entry: { | ||
lib: path.join(__dirname, 'src', 'index.ts'), | ||
}, | ||
output: { | ||
path: path.join(__dirname, 'lib'), | ||
filename: '[name].js', | ||
library: '@spinnaker/plugins', | ||
libraryTarget: 'umd', | ||
umdNamedDefine: true, | ||
}, | ||
devtool: 'source-map', | ||
optimization: { | ||
minimizer: IS_PRODUCTION | ||
? [ | ||
new TerserPlugin({ | ||
cache: true, | ||
parallel: true, | ||
sourceMap: true, | ||
terserOptions: { | ||
ecma: 6, | ||
mangle: false, | ||
output: { | ||
comments: false, | ||
}, | ||
}, | ||
}), | ||
] | ||
: [], // disable minification in development mode | ||
}, | ||
resolve: { | ||
extensions: ['.json', '.js', '.jsx', '.ts', '.tsx', '.css', '.less', '.html'], | ||
modules: [NODE_MODULE_PATH, path.resolve('.')], | ||
alias: { | ||
'@spinnaker/plugins': path.join(__dirname, 'src'), | ||
plugins: path.join(__dirname, 'src'), | ||
}, | ||
}, | ||
module: { | ||
rules: [ | ||
{ | ||
test: /\.js$/, | ||
use: [ | ||
{ loader: 'cache-loader' }, | ||
{ loader: 'thread-loader', options: { workers: WEBPACK_THREADS } }, | ||
{ loader: 'babel-loader' }, | ||
{ loader: 'envify-loader' }, | ||
{ loader: 'eslint-loader' }, | ||
], | ||
exclude: exclusionPattern, | ||
}, | ||
{ | ||
test: /\.tsx?$/, | ||
use: [ | ||
{ loader: 'cache-loader' }, | ||
{ loader: 'thread-loader', options: { workers: WEBPACK_THREADS } }, | ||
{ loader: 'ts-loader', options: { happyPackMode: true } }, | ||
{ loader: 'tslint-loader' }, | ||
], | ||
exclude: exclusionPattern, | ||
}, | ||
{ | ||
test: /\.less$/, | ||
use: [ | ||
{ loader: 'style-loader' }, | ||
{ loader: 'css-loader' }, | ||
{ loader: 'postcss-loader' }, | ||
{ loader: 'less-loader' }, | ||
], | ||
}, | ||
{ | ||
test: /\.css$/, | ||
use: [{ loader: 'style-loader' }, { loader: 'css-loader' }, { loader: 'postcss-loader' }], | ||
}, | ||
{ | ||
test: /\.html$/, | ||
exclude: exclusionPattern, | ||
use: [ | ||
{ loader: 'ngtemplate-loader?relativeTo=' + path.resolve(__dirname) + '&prefix=plugins' }, | ||
{ loader: 'html-loader' }, | ||
], | ||
}, | ||
{ | ||
test: /\.(woff|woff2|otf|ttf|eot|png|gif|ico|svg)$/, | ||
use: [{ loader: 'file-loader', options: { name: '[name].[hash:5].[ext]' } }], | ||
}, | ||
{ | ||
test: require.resolve('jquery'), | ||
use: [{ loader: 'expose-loader?$' }, { loader: 'expose-loader?jQuery' }], | ||
}, | ||
], | ||
}, | ||
plugins: [new ForkTsCheckerWebpackPlugin({ checkSyntacticErrors: true })], | ||
externals: ['@spinnaker/core', nodeExternals({ modulesDir: '../../../../node_modules' })], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. | ||
# yarn lockfile v1 | ||
|
||
|
||
"@spinnaker/core@^0.0.406": | ||
version "0.0.406" | ||
resolved "https://registry.yarnpkg.com/@spinnaker/core/-/core-0.0.406.tgz#898f555a43b401f44561e8a742a92e51f128a476" | ||
integrity sha512-NTqryXCEpYL8feO4hMZyBH70gVBfVabyJ4nChgmIC8PlZ/TMCN8rpGOtr9Q9g/tqgMUXRYiGWnNqxRS/g2Zs4g== |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { Registry } from '@spinnaker/core'; | ||
|
||
// Appends plugin resources to the bottom of the page via a script | ||
// tag. This makes it so the plugins start loading after the Spinnaker | ||
// application is loaded. | ||
function loadPluginScript(plugin) { | ||
return new Promise((resolve, reject) => { | ||
var scriptTag = document.createElement('script'); | ||
scriptTag.src = plugin.location; | ||
scriptTag.onload = () => resolve(); | ||
scriptTag.onreadystatechange = () => resolve(); | ||
scriptTag.onerror = () => reject(); | ||
document.body.appendChild(scriptTag); | ||
}); | ||
} | ||
|
||
// This method grabs all plugins that are defined in Spinnaker settings | ||
// and will call their initialize method and append the script location | ||
// to the bottom of the page. The initialize function is based on the | ||
// interface defined in the plugins module. The Registry is passed into | ||
// the initialize method so the plugin can register itself as a stage. | ||
// This is done by calling window.spinnakerSettings.onPluginLoaded and | ||
// the plugin developer passes in their plugin object that contains | ||
// the initialize method. | ||
export function initPlugins() { | ||
const plugins = window.spinnakerSettings.plugins; | ||
window.spinnakerSettings.onPluginLoaded = plugin => plugin.initialize(Registry); | ||
return Promise.all(plugins.map(p => loadPluginScript(p))); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters