ソースを参照

Various tweaks and improvements to Console plugin template

Vojtech Szocs 2 年 前
コミット
e1cf3c5a43

+ 3 - 5
.gitignore

@@ -1,8 +1,6 @@
-node_modules/
-dist/
+**/node_modules
+**/dist
+**/.DS_Store
 .devcontainer/dev.env
 integration-tests/videos
 integration-tests/screenshots
-integration-tests/.DS_Store
-yarn-error.log
-.DS_Store

+ 1 - 0
.prettierrc.yml

@@ -1,3 +1,4 @@
 arrowParens: always
+printWidth: 100
 singleQuote: true
 trailingComma: all

+ 18 - 8
.vscode/settings.json

@@ -1,8 +1,18 @@
-{
-  "json.schemas": [
-    {
-      "fileMatch": ["console-extensions.json", "**/console-extensions.json"],
-      "url": "./node_modules/@openshift-console/dynamic-plugin-sdk-webpack/schema/console-extensions.json"
-    }
-  ]
-}
+{
+  "typescript.tsdk": "./node_modules/typescript/lib",
+  "search.exclude": {
+    "**/node_modules": true
+  },
+  "files.watcherExclude": {
+    "**/node_modules/**": true
+  },
+  "files.associations": {
+    "**/console-extensions.json": "jsonc"
+  },
+  "json.schemas": [
+    {
+      "fileMatch": ["**/console-extensions.json"],
+      "url": "./node_modules/@openshift-console/dynamic-plugin-sdk-webpack/schema/console-extensions.json"
+    }
+  ]
+}

+ 1 - 3
integration-tests/plugins/index.ts

@@ -19,9 +19,7 @@ module.exports = (on, config) => {
   };
   on('file:preprocessor', wp(options));
   // `config` is the resolved Cypress config
-  config.baseUrl = `${
-    process.env.BRIDGE_BASE_ADDRESS || 'http://localhost:9000/'
-  }`;
+  config.baseUrl = `${process.env.BRIDGE_BASE_ADDRESS || 'http://localhost:9000/'}`;
   config.env.BRIDGE_KUBEADMIN_PASSWORD = process.env.BRIDGE_KUBEADMIN_PASSWORD;
   return config;
 };

+ 2 - 6
integration-tests/support/login.ts

@@ -8,9 +8,7 @@ declare global {
 }
 
 const KUBEADMIN_USERNAME = 'kubeadmin';
-const loginUsername = Cypress.env('BRIDGE_KUBEADMIN_PASSWORD')
-  ? 'user-dropdown'
-  : 'username';
+const loginUsername = Cypress.env('BRIDGE_KUBEADMIN_PASSWORD') ? 'user-dropdown' : 'username';
 
 // This will add 'cy.login(...)'
 // ex: cy.login('my-user', 'my-password')
@@ -26,9 +24,7 @@ Cypress.Commands.add('login', (username: string, password: string) => {
     cy.clearCookie('openshift-session-token');
 
     cy.get('#inputUsername').type(username || KUBEADMIN_USERNAME);
-    cy.get('#inputPassword').type(
-      password || Cypress.env('BRIDGE_KUBEADMIN_PASSWORD'),
-    );
+    cy.get('#inputPassword').type(password || Cypress.env('BRIDGE_KUBEADMIN_PASSWORD'));
     cy.get('button[type=submit]').click();
 
     cy.get(`[data-test="${loginUsername}"]`).should('be.visible');

+ 3 - 10
integration-tests/tests/example-page.cy.ts

@@ -2,8 +2,7 @@ import { checkErrors } from '../support';
 
 const PLUGIN_TEMPLATE_NAME = 'console-plugin-template';
 const PLUGIN_TEMPLATE_PULL_SPEC = Cypress.env('PLUGIN_TEMPLATE_PULL_SPEC');
-export const isLocalDevEnvironment =
-  Cypress.config('baseUrl').includes('localhost');
+export const isLocalDevEnvironment = Cypress.config('baseUrl').includes('localhost');
 
 const installHelmChart = (path: string) => {
   cy.exec(
@@ -44,10 +43,7 @@ describe('Console plugin template test', () => {
         failOnNonZeroExit: false,
       }).then((result) => {
         cy.log('Error installing helm binary: ', result.stderr);
-        cy.log(
-          'Successfully installed helm binary in "/tmp" directory: ',
-          result.stdout,
-        );
+        cy.log('Successfully installed helm binary in "/tmp" directory: ', result.stdout);
 
         installHelmChart('/tmp/helm');
       });
@@ -75,9 +71,6 @@ describe('Console plugin template test', () => {
     cy.get('[data-quickstart-id="qs-nav-home"]').click();
     cy.get('[data-test="nav"]').contains('Plugin Example').click();
     cy.url().should('include', '/example');
-    cy.get('[data-test="example-page-title"]').should(
-      'contain',
-      'Hello, Plugin!',
-    );
+    cy.get('[data-test="example-page-title"]').should('contain', 'Hello, Plugin!');
   });
 });

+ 1 - 1
locales/en/plugin__console-plugin-template.json

@@ -9,4 +9,4 @@
   "Success!": "Success!",
   "This is a custom page contributed by the console plugin template. The extension that adds the page is declared in console-extensions.json in the project root along with the corresponding nav item. Update console-extensions.json to change or add extensions. Code references in console-extensions.json must have a corresponding property": "This is a custom page contributed by the console plugin template. The extension that adds the page is declared in console-extensions.json in the project root along with the corresponding nav item. Update console-extensions.json to change or add extensions. Code references in console-extensions.json must have a corresponding property",
   "Your plugin is working.": "Your plugin is working."
-}
+}

+ 15 - 11
package.json

@@ -1,28 +1,32 @@
 {
   "name": "console-plugin-template",
   "version": "0.0.1",
+  "description": "Template project for OpenShift Console dynamic plugins",
   "private": true,
-  "repository": "git@github.com:spadgett/console-plugin-template.git",
   "license": "Apache-2.0",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/openshift/console-plugin-template.git"
+  },
   "scripts": {
     "clean": "rm -rf dist",
-    "build": "yarn clean && NODE_ENV=production yarn ts-node node_modules/.bin/webpack",
-    "build-dev": "yarn clean && yarn ts-node node_modules/.bin/webpack",
-    "start": "yarn ts-node node_modules/.bin/webpack serve",
+    "build": "yarn clean && NODE_ENV=production yarn webpack",
+    "build-dev": "yarn clean && yarn webpack",
+    "start": "yarn webpack serve --progress",
     "start-console": "./start-console.sh",
     "i18n": "./i18n-scripts/build-i18n.sh && node ./i18n-scripts/set-english-defaults.js",
-    "ts-node": "ts-node -O '{\"module\":\"commonjs\"}'",
-    "lint": "eslint ./src ./integration-tests --fix &&  stylelint \"src/**/*.css\" --allow-empty-input --fix",
-    "test-cypress": "cd integration-tests s && cypress open --env openshift=true",
+    "lint": "yarn eslint src integration-tests --fix && stylelint 'src/**/*.css' --allow-empty-input --fix",
+    "test-cypress": "cd integration-tests && cypress open --env openshift=true",
     "test-cypress-headless": "cd integration-tests && node --max-old-space-size=4096 ../node_modules/.bin/cypress run --env openshift=true --browser ${BRIDGE_E2E_BROWSER_NAME:=electron}",
     "cypress-merge": "mochawesome-merge ./integration-tests/screenshots/cypress_report*.json > ./integration-tests/screenshots/cypress.json",
     "cypress-generate": "marge -o ./integration-tests/screenshots/ -f cypress-report -t 'OpenShift Console Plugin Template Cypress Test Results' -p 'OpenShift Cypress Plugin Template Test Results' --showPassed false --assetsDir ./integration-tests/screenshots/cypress/assets ./integration-tests/screenshots/cypress.json",
-    "cypress-postreport": "yarn cypress-merge && yarn cypress-generate"
+    "cypress-postreport": "yarn cypress-merge && yarn cypress-generate",
+    "webpack": "node -r ts-node/register ./node_modules/.bin/webpack"
   },
   "devDependencies": {
     "@cypress/webpack-preprocessor": "^5.15.5",
-    "@openshift-console/dynamic-plugin-sdk": "^1.0.0",
-    "@openshift-console/dynamic-plugin-sdk-webpack": "^1.0.0",
+    "@openshift-console/dynamic-plugin-sdk": "1.2.0",
+    "@openshift-console/dynamic-plugin-sdk-webpack": "1.1.0",
     "@patternfly/react-core": "^5.1.1",
     "@patternfly/react-icons": "^5.1.1",
     "@patternfly/react-styles": "^5.1.1",
@@ -68,7 +72,7 @@
     "name": "console-plugin-template",
     "version": "0.0.1",
     "displayName": "OpenShift Console Plugin Template",
-    "description": "Template project for OpenShift console plugins. Edit package.json to change this message and the plugin name.",
+    "description": "Template project for OpenShift Console dynamic plugins. Edit package.json to change this message and the plugin name.",
     "exposedModules": {
       "ExamplePage": "./components/ExamplePage"
     },

+ 3 - 11
src/components/ExamplePage.tsx

@@ -1,15 +1,9 @@
 import * as React from 'react';
 import Helmet from 'react-helmet';
-import {
-  Page,
-  PageSection,
-  Text,
-  TextContent,
-  Title,
-} from '@patternfly/react-core';
+import { useTranslation } from 'react-i18next';
+import { Page, PageSection, Text, TextContent, Title } from '@patternfly/react-core';
 import { CheckCircleIcon } from '@patternfly/react-icons';
 import './example.css';
-import { useTranslation } from 'react-i18next';
 
 export default function ExamplePage() {
   const { t } = useTranslation('plugin__console-plugin-template');
@@ -41,9 +35,7 @@ export default function ExamplePage() {
             <Text component="p">
               {t('After cloning this project, replace references to')}{' '}
               <code>{t('console-template-plugin')}</code>{' '}
-              {t(
-                'and other plugin metadata in package.json with values for your plugin.',
-              )}
+              {t('and other plugin metadata in package.json with values for your plugin.')}
             </Text>
           </TextContent>
         </PageSection>

+ 7 - 4
start-console.sh

@@ -6,6 +6,9 @@ CONSOLE_IMAGE=${CONSOLE_IMAGE:="quay.io/openshift/origin-console:latest"}
 CONSOLE_PORT=${CONSOLE_PORT:=9000}
 CONSOLE_IMAGE_PLATFORM=${CONSOLE_IMAGE_PLATFORM:="linux/amd64"}
 
+# Plugin metadata is declared in package.json
+PLUGIN_NAME=${npm_package_consolePlugin_name}
+
 echo "Starting local OpenShift console..."
 
 BRIDGE_USER_AUTH="disabled"
@@ -20,7 +23,7 @@ BRIDGE_K8S_MODE_OFF_CLUSTER_ALERTMANAGER=$(oc -n openshift-config-managed get co
 set -e
 BRIDGE_K8S_AUTH_BEARER_TOKEN=$(oc whoami --show-token 2>/dev/null)
 BRIDGE_USER_SETTINGS_LOCATION="localstorage"
-BRIDGE_I18N_NAMESPACES="plugin__${npm_package_consolePlugin_name}"
+BRIDGE_I18N_NAMESPACES="plugin__${PLUGIN_NAME}"
 
 # Don't fail if the cluster doesn't have gitops.
 set +e
@@ -39,13 +42,13 @@ echo "Console Platform: $CONSOLE_IMAGE_PLATFORM"
 if [ -x "$(command -v podman)" ]; then
     if [ "$(uname -s)" = "Linux" ]; then
         # Use host networking on Linux since host.containers.internal is unreachable in some environments.
-        BRIDGE_PLUGINS="${npm_package_consolePlugin_name}=http://localhost:9001"
+        BRIDGE_PLUGINS="${PLUGIN_NAME}=http://localhost:9001"
         podman run --pull always --platform $CONSOLE_IMAGE_PLATFORM --rm --network=host --env-file <(set | grep BRIDGE) $CONSOLE_IMAGE
     else
-        BRIDGE_PLUGINS="${npm_package_consolePlugin_name}=http://host.containers.internal:9001"
+        BRIDGE_PLUGINS="${PLUGIN_NAME}=http://host.containers.internal:9001"
         podman run --pull always --platform $CONSOLE_IMAGE_PLATFORM --rm -p "$CONSOLE_PORT":9000 --env-file <(set | grep BRIDGE) $CONSOLE_IMAGE
     fi
 else
-    BRIDGE_PLUGINS="${npm_package_consolePlugin_name}=http://host.docker.internal:9001"
+    BRIDGE_PLUGINS="${PLUGIN_NAME}=http://host.docker.internal:9001"
     docker run --pull always --platform $CONSOLE_IMAGE_PLATFORM --rm -p "$CONSOLE_PORT":9000 --env-file <(set | grep BRIDGE) $CONSOLE_IMAGE
 fi

+ 11 - 3
tsconfig.json

@@ -4,11 +4,19 @@
     "module": "esnext",
     "moduleResolution": "node",
     "target": "es2020",
+    "sourceMap": true,
     "jsx": "react",
     "allowJs": true,
     "strict": false,
-    "noUnusedLocals": true,
-    "sourceMap": true
+    "noUnusedLocals": true
   },
-  "include": ["src"]
+  "include": ["src"],
+  "exclude": ["node_modules"],
+  "ts-node": {
+    "files": true,
+    "transpileOnly": true,
+    "compilerOptions": {
+      "module": "commonjs"
+    }
+  }
 }

+ 28 - 39
webpack.config.ts

@@ -1,56 +1,58 @@
 /* eslint-env node */
 
-import { Configuration as WebpackConfiguration } from "webpack";
-import { Configuration as WebpackDevServerConfiguration } from "webpack-dev-server";
-import * as path from "path";
-import { ConsoleRemotePlugin } from "@openshift-console/dynamic-plugin-sdk-webpack";
+import * as path from 'path';
+import { Configuration as WebpackConfiguration } from 'webpack';
+import { Configuration as WebpackDevServerConfiguration } from 'webpack-dev-server';
+import { ConsoleRemotePlugin } from '@openshift-console/dynamic-plugin-sdk-webpack';
 
 const CopyWebpackPlugin = require('copy-webpack-plugin');
 
+const isProd = process.env.NODE_ENV === 'production';
+
 interface Configuration extends WebpackConfiguration {
   devServer?: WebpackDevServerConfiguration;
 }
 
 const config: Configuration = {
-  mode: "development",
-  // No regular entry points. The remote container entry is handled by ConsoleRemotePlugin.
+  mode: isProd ? 'production' : 'development',
+  // No regular entry points needed. All plugin related scripts are generated via ConsoleRemotePlugin.
   entry: {},
-  context: path.resolve(__dirname, "src"),
+  context: path.resolve(__dirname, 'src'),
   output: {
-    path: path.resolve(__dirname, "dist"),
-    filename: "[name]-bundle.js",
-    chunkFilename: "[name]-chunk.js",
+    path: path.resolve(__dirname, 'dist'),
+    filename: isProd ? '[name]-bundle-[hash].min.js' : '[name]-bundle.js',
+    chunkFilename: isProd ? '[name]-chunk-[chunkhash].min.js' : '[name]-chunk.js',
   },
   resolve: {
-    extensions: [".ts", ".tsx", ".js", ".jsx"],
+    extensions: ['.ts', '.tsx', '.js', '.jsx'],
   },
   module: {
     rules: [
       {
         test: /\.(jsx?|tsx?)$/,
-        exclude: /node_modules/,
+        exclude: /\/node_modules\//,
         use: [
           {
-            loader: "ts-loader",
+            loader: 'ts-loader',
             options: {
-              configFile: path.resolve(__dirname, "tsconfig.json"),
+              configFile: path.resolve(__dirname, 'tsconfig.json'),
             },
           },
         ],
       },
       {
-        test: /\.css$/,
-        use: ["style-loader", "css-loader"],
+        test: /\.(css)$/,
+        use: ['style-loader', 'css-loader'],
       },
       {
         test: /\.(png|jpg|jpeg|gif|svg|woff2?|ttf|eot|otf)(\?.*$|$)/,
         type: 'asset/resource',
         generator: {
-          filename: 'assets/[name].[ext]',
+          filename: isProd ? 'assets/[contenthash][ext]' : 'assets/[name][ext]',
         },
       },
       {
-        test: /\.m?js/,
+        test: /\.(m?js)$/,
         resolve: {
           fullySpecified: false,
         },
@@ -60,41 +62,28 @@ const config: Configuration = {
   devServer: {
     static: './dist',
     port: 9001,
-    // Allow bridge running in a container to connect to the plugin dev server.
+    // Allow Bridge running in a container to connect to the plugin dev server.
     allowedHosts: 'all',
     headers: {
-      "Access-Control-Allow-Origin": "*",
-      "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
-      "Access-Control-Allow-Headers": "X-Requested-With, Content-Type, Authorization"
+      'Access-Control-Allow-Origin': '*',
+      'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
+      'Access-Control-Allow-Headers': 'X-Requested-With, Content-Type, Authorization',
     },
     devMiddleware: {
       writeToDisk: true,
     },
   },
   plugins: [
-    new ConsoleRemotePlugin(), 
+    new ConsoleRemotePlugin(),
     new CopyWebpackPlugin({
       patterns: [{ from: path.resolve(__dirname, 'locales'), to: 'locales' }],
     }),
   ],
-  devtool: "source-map",
+  devtool: isProd ? false : 'source-map',
   optimization: {
-    chunkIds: "named",
-    minimize: false,
+    chunkIds: isProd ? 'deterministic' : 'named',
+    minimize: isProd,
   },
 };
 
-if (process.env.NODE_ENV === "production") {
-  config.mode = "production";
-  if (config.output) {
-    config.output.filename = '[name]-bundle-[hash].min.js';
-    config.output.chunkFilename = '[name]-chunk-[chunkhash].min.js';
-  }
-  if (config.optimization) {
-    config.optimization.chunkIds = 'deterministic';
-    config.optimization.minimize = true;
-  }
-  config.devtool = false;
-}
-
 export default config;

+ 10 - 10
yarn.lock

@@ -237,12 +237,12 @@
     mkdirp "^1.0.4"
     rimraf "^3.0.2"
 
-"@openshift-console/dynamic-plugin-sdk-webpack@^1.0.0":
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/@openshift-console/dynamic-plugin-sdk-webpack/-/dynamic-plugin-sdk-webpack-1.0.0.tgz#dc557b8b282b58761b1c319d287d24653d322c7e"
-  integrity sha512-52Ac62Xh6TVX9cd/CZSQzwMytvtif7K5Bsdp7OQMqiw++dLnvUcRI6BDTAe3CQH/fAqi4vCMdISKTDPEYYGUOg==
+"@openshift-console/dynamic-plugin-sdk-webpack@1.1.0":
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/@openshift-console/dynamic-plugin-sdk-webpack/-/dynamic-plugin-sdk-webpack-1.1.0.tgz#d369c37b93cd0792960385728de5cd1f63c2187f"
+  integrity sha512-UukGhZOEGc5u22hoO3H0bP58r+Kw1gDFBe0EEJTkYkzYX6S0og5DNAVw/lzhwUorpbmy00B6cqWIuclmTo1+QA==
   dependencies:
-    "@openshift/dynamic-plugin-sdk-webpack" "^4.0.1"
+    "@openshift/dynamic-plugin-sdk-webpack" "^4.0.2"
     ajv "^6.12.3"
     chalk "2.4.x"
     comment-json "4.x"
@@ -253,10 +253,10 @@
     semver "6.x"
     webpack "5.75.0"
 
-"@openshift-console/dynamic-plugin-sdk@^1.0.0":
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/@openshift-console/dynamic-plugin-sdk/-/dynamic-plugin-sdk-1.0.0.tgz#af281184805b79e6891145fd1d915e01e869b295"
-  integrity sha512-Rgj3LuOPJGW1W/KP9luIvZMFHyb8qFTrH2RB2xJ9r4NY2enDLS8eaN79AejV9fNO7v025Fh6MKtTjMnYOoyZVg==
+"@openshift-console/dynamic-plugin-sdk@1.2.0":
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/@openshift-console/dynamic-plugin-sdk/-/dynamic-plugin-sdk-1.2.0.tgz#8cdc50240f1a171530ce0ddcd2a4f4006043eb1a"
+  integrity sha512-K/BqjyG0kSnPFtBlPQYlmcHa1xhozUX0ZaOB5S4vUN4x3hbvcJEeUy/l4RWMNH/+sW8ciuTaBlXCWTxTCfFAXg==
   dependencies:
     classnames "2.x"
     immutable "3.x"
@@ -273,7 +273,7 @@
     typesafe-actions "^4.2.1"
     whatwg-fetch "2.x"
 
-"@openshift/dynamic-plugin-sdk-webpack@^4.0.1":
+"@openshift/dynamic-plugin-sdk-webpack@^4.0.2":
   version "4.0.2"
   resolved "https://registry.yarnpkg.com/@openshift/dynamic-plugin-sdk-webpack/-/dynamic-plugin-sdk-webpack-4.0.2.tgz#0304911c9c27ecff7ba5d2df5ca24f781fd445ec"
   integrity sha512-zgRLt9WM63aGYygrQEtd8QtWoP5zYWr67kzlRKzGcHeRbWDgiHnY7FOiDUM04bYeb4lL6qv3iErEnrtvVpyh0Q==