Merge pull request #9371 from backstage/rugvip/td-cli-build
techdocs-cli: simplify dev setup and optimize build
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@techdocs/cli': patch
|
||||
---
|
||||
|
||||
Updated the HTTP server to allow for simplification of the development of the CLI itself.
|
||||
@@ -1,12 +0,0 @@
|
||||
# NOTE: This file is used for testing techdocs-cli locally
|
||||
|
||||
app:
|
||||
title: Techdocs Preview App
|
||||
baseUrl: http://localhost:3000
|
||||
|
||||
backend:
|
||||
baseUrl: http://localhost:7007
|
||||
|
||||
techdocs:
|
||||
builder: 'external'
|
||||
requestUrl: http://localhost:7007/api
|
||||
@@ -39,9 +39,8 @@
|
||||
"start-server-and-test": "^1.10.11"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "backstage-cli app:serve --config ./app-config.yaml --config ./app-config.dev.yaml",
|
||||
"start": "backstage-cli app:serve --config ./app-config.yaml",
|
||||
"build": "backstage-cli app:build --config ./app-config.yaml",
|
||||
"build:dev": "backstage-cli app:build --config ./app-config.dev.yaml",
|
||||
"clean": "backstage-cli clean",
|
||||
"test": "backstage-cli test",
|
||||
"lint": "backstage-cli lint",
|
||||
|
||||
@@ -18,25 +18,24 @@ import React from 'react';
|
||||
import { renderWithEffects } from '@backstage/test-utils';
|
||||
import App from './App';
|
||||
|
||||
jest.mock('./config', () => ({
|
||||
configLoader: async () => [
|
||||
{
|
||||
data: {
|
||||
app: { title: 'Test' },
|
||||
backend: { baseUrl: 'http://localhost:7007' },
|
||||
techdocs: {
|
||||
storageUrl: 'http://localhost:7007/api/techdocs/static/docs',
|
||||
},
|
||||
},
|
||||
context: 'test',
|
||||
},
|
||||
],
|
||||
}));
|
||||
|
||||
describe('App', () => {
|
||||
it('should render', async () => {
|
||||
process.env = {
|
||||
NODE_ENV: 'test',
|
||||
APP_CONFIG: [
|
||||
{
|
||||
data: {
|
||||
app: { title: 'Test' },
|
||||
backend: { baseUrl: 'http://localhost:7007' },
|
||||
techdocs: {
|
||||
storageUrl: 'http://localhost:7007/api/techdocs/static/docs',
|
||||
},
|
||||
},
|
||||
context: 'test',
|
||||
},
|
||||
] as any,
|
||||
};
|
||||
|
||||
const rendered = await renderWithEffects(<App />);
|
||||
expect(rendered.baseElement).toBeInTheDocument();
|
||||
expect(rendered.getByText('Docs Preview')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,9 +29,11 @@ import { apis } from './apis';
|
||||
import { Root } from './components/Root';
|
||||
import { techDocsPage } from './components/TechDocsPage';
|
||||
import * as plugins from './plugins';
|
||||
import { configLoader } from './config';
|
||||
|
||||
const app = createApp({
|
||||
apis,
|
||||
configLoader,
|
||||
plugins: Object.values(plugins),
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2020 The Backstage Authors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { defaultConfigLoader } from '@backstage/core-app-api';
|
||||
|
||||
const PRODUCTION_CONFIG = {
|
||||
backend: {
|
||||
baseUrl: 'http://localhost:3000',
|
||||
},
|
||||
techdocs: {
|
||||
builder: 'external',
|
||||
requestUrl: 'http://localhost:3000/api',
|
||||
},
|
||||
};
|
||||
|
||||
const DEVELOPMENT_CONFIG = {
|
||||
backend: {
|
||||
baseUrl: 'http://localhost:7007',
|
||||
},
|
||||
techdocs: {
|
||||
builder: 'external',
|
||||
requestUrl: 'http://localhost:7007/api',
|
||||
},
|
||||
};
|
||||
|
||||
async function isProductionServe() {
|
||||
const res = await fetch('/.detect');
|
||||
if (!res.ok) {
|
||||
return false;
|
||||
}
|
||||
const text = await res.text();
|
||||
return text.trim() === 'techdocs-cli-server';
|
||||
}
|
||||
|
||||
export async function configLoader() {
|
||||
const defaultConfigs = await defaultConfigLoader();
|
||||
const isProduction = await isProductionServe();
|
||||
|
||||
return [
|
||||
...defaultConfigs,
|
||||
{
|
||||
context: 'detected',
|
||||
data: isProduction ? PRODUCTION_CONFIG : DEVELOPMENT_CONFIG,
|
||||
},
|
||||
];
|
||||
}
|
||||
@@ -21,12 +21,13 @@
|
||||
"types": "",
|
||||
"scripts": {
|
||||
"start": "nodemon --",
|
||||
"build": "./scripts/build.sh",
|
||||
"build": "backstage-cli build --outputs cjs",
|
||||
"clean": "backstage-cli clean",
|
||||
"lint": "backstage-cli lint",
|
||||
"test": "backstage-cli test --testPathIgnorePatterns=src/e2e.test.ts",
|
||||
"test:e2e": "backstage-cli test src/e2e.test.ts",
|
||||
"test:e2e:ci": "backstage-cli test --watchAll=false --ci src/e2e.test.ts"
|
||||
"test:e2e:ci": "backstage-cli test --watchAll=false --ci src/e2e.test.ts",
|
||||
"prepack": "./scripts/prepack.sh"
|
||||
},
|
||||
"bin": {
|
||||
"techdocs-cli": "bin/techdocs-cli"
|
||||
@@ -57,6 +58,7 @@
|
||||
"dependencies": {
|
||||
"@backstage/backend-common": "^0.10.6",
|
||||
"@backstage/catalog-model": "^0.9.10",
|
||||
"@backstage/cli-common": "^0.1.6",
|
||||
"@backstage/config": "^0.1.13",
|
||||
"@backstage/techdocs-common": "^0.11.6",
|
||||
"@types/dockerode": "^3.3.0",
|
||||
|
||||
@@ -20,25 +20,7 @@ SCRIPT_DIR=$(dirname $0)
|
||||
TECHDOCS_CLI_DIR="$SCRIPT_DIR"/..
|
||||
TECHDOCS_CLI_EMBEDDED_APP_DIR="$TECHDOCS_CLI_DIR"/../techdocs-cli-embedded-app
|
||||
|
||||
compile_and_build_cli() {
|
||||
echo "📄 Compiling..."
|
||||
yarn workspace @techdocs/cli tsc > /dev/null
|
||||
echo "📦️ Building..."
|
||||
pushd $TECHDOCS_CLI_DIR > /dev/null
|
||||
npx backstage-cli build --outputs cjs > /dev/null
|
||||
popd > /dev/null
|
||||
}
|
||||
|
||||
build_and_embed_app() {
|
||||
echo "🚚 Embedding app..."
|
||||
if [ "$TECHDOCS_CLI_DEV_MODE" = "true" ] ; then
|
||||
yarn workspace techdocs-cli-embedded-app build:dev > /dev/null
|
||||
else
|
||||
yarn workspace techdocs-cli-embedded-app build > /dev/null
|
||||
fi
|
||||
cp -r "$TECHDOCS_CLI_EMBEDDED_APP_DIR"/dist "$TECHDOCS_CLI_DIR"/dist/techdocs-preview-bundle > /dev/null
|
||||
}
|
||||
|
||||
compile_and_build_cli
|
||||
build_and_embed_app
|
||||
echo "🚚 Copying embedded app into dist/embedded-app"
|
||||
rm -r "$TECHDOCS_CLI_DIR"/dist/embedded-app
|
||||
cp -r "$TECHDOCS_CLI_EMBEDDED_APP_DIR"/dist "$TECHDOCS_CLI_DIR"/dist/embedded-app
|
||||
echo "🏁 Ready!"
|
||||
@@ -17,11 +17,30 @@
|
||||
import { Command } from 'commander';
|
||||
import path from 'path';
|
||||
import openBrowser from 'react-dev-utils/openBrowser';
|
||||
import { findPaths } from '@backstage/cli-common';
|
||||
import HTTPServer from '../../lib/httpServer';
|
||||
import { runMkdocsServer } from '../../lib/mkdocsServer';
|
||||
import { LogFunc, waitForSignal } from '../../lib/run';
|
||||
import { createLogger } from '../../lib/utility';
|
||||
|
||||
function findPreviewBundlePath(): string {
|
||||
try {
|
||||
return path.join(
|
||||
path.dirname(require.resolve('techdocs-cli-embedded-app/package.json')),
|
||||
'dist',
|
||||
);
|
||||
} catch {
|
||||
// If the techdocs-cli-embedded-app package is not available it means we're
|
||||
// running a published package. For published packages the preview bundle is
|
||||
// copied to dist/embedded-app be the prepack script.
|
||||
//
|
||||
// This can be tested by running `yarn pack` and extracting the resulting tarball into a directory.
|
||||
// Within the extracted directory, run `npm install --only=prod`.
|
||||
// Once that's done you can test the CLI in any directory using `node <tmp-dir>/package <command>`.
|
||||
return findPaths(__dirname).resolveOwn('dist/embedded-app');
|
||||
}
|
||||
}
|
||||
|
||||
export default async function serve(cmd: Command) {
|
||||
const logger = createLogger({ verbose: cmd.verbose });
|
||||
|
||||
@@ -91,16 +110,9 @@ export default async function serve(cmd: Command) {
|
||||
);
|
||||
}
|
||||
|
||||
// Run the embedded-techdocs Backstage app
|
||||
const techdocsPreviewBundlePath = path.join(
|
||||
path.dirname(require.resolve('@techdocs/cli/package.json')),
|
||||
'dist',
|
||||
'techdocs-preview-bundle',
|
||||
);
|
||||
|
||||
const port = isDevMode ? backstageBackendPort : backstagePort;
|
||||
const httpServer = new HTTPServer(
|
||||
techdocsPreviewBundlePath,
|
||||
findPreviewBundlePath(),
|
||||
port,
|
||||
cmd.mkdocsPort,
|
||||
cmd.verbose,
|
||||
|
||||
@@ -71,10 +71,18 @@ export default class HTTPServer {
|
||||
response.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
|
||||
|
||||
request.url = forwardPath;
|
||||
return proxy.web(request, response);
|
||||
proxy.web(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
return serveHandler(request, response, {
|
||||
// This endpoint is used by the frontend to detect where the backend is running.
|
||||
if (request.url === '/.detect') {
|
||||
response.setHeader('Content-Type', 'text/plain');
|
||||
response.end('techdocs-cli-server');
|
||||
return;
|
||||
}
|
||||
|
||||
serveHandler(request, response, {
|
||||
public: this.backstageBundleDir,
|
||||
trailingSlash: true,
|
||||
rewrites: [{ source: '**', destination: 'index.html' }],
|
||||
|
||||
Reference in New Issue
Block a user