Merge pull request #10948 from backstage/jhaals/simplify-create-app

Remove database choice from `create-app` command
This commit is contained in:
Johan Haals
2022-05-03 09:22:45 +02:00
committed by GitHub
10 changed files with 93 additions and 79 deletions
-8
View File
@@ -50,15 +50,7 @@ export default async (opts: OptionValues): Promise<void> => {
return true;
},
},
{
type: 'list',
name: 'dbType',
message: chalk.blue('Select database for the backend [required]'),
choices: ['SQLite', 'PostgreSQL'],
},
]);
answers.dbTypePG = answers.dbType === 'PostgreSQL';
answers.dbTypeSqlite = answers.dbType === 'SQLite';
const templateDir = paths.resolveOwn('templates/default-app');
const tempDir = resolvePath(os.tmpdir(), answers.name);
@@ -0,0 +1 @@
# Backstage override configuration for your local development environment
@@ -17,3 +17,18 @@ backend:
# backend will bind on the interface that corresponds to the backend.baseUrl
# hostname.
host: 0.0.0.0
# config options: https://node-postgres.com/api/client
database:
client: pg
connection:
host: ${POSTGRES_HOST}
port: ${POSTGRES_PORT}
user: ${POSTGRES_USER}
password: ${POSTGRES_PASSWORD}
# https://node-postgres.com/features/ssl
# you can set the sslmode configuration option via the `PGSSLMODE` environment variable
# see https://www.postgresql.org/docs/current/libpq-ssl.html Table 33.1. SSL Mode Descriptions (e.g. require)
# ssl:
# ca: # if you have a CA file and want to verify it you can uncomment this section
# $file: <file-path>/ca/server.crt
@@ -26,27 +26,11 @@ backend:
origin: http://localhost:3000
methods: [GET, POST, PUT, DELETE]
credentials: true
{{#if dbTypeSqlite}}
# This is for local developement only, it is not recommended to use this in production
# The production database configuration is stored in app-config.production.yaml
database:
client: better-sqlite3
connection: ':memory:'
{{/if}}
{{#if dbTypePG}}
# config options: https://node-postgres.com/api/client
database:
client: pg
connection:
host: ${POSTGRES_HOST}
port: ${POSTGRES_PORT}
user: ${POSTGRES_USER}
password: ${POSTGRES_PASSWORD}
# https://node-postgres.com/features/ssl
# you can set the sslmode configuration option via the `PGSSLMODE` environment variable
# see https://www.postgresql.org/docs/current/libpq-ssl.html Table 33.1. SSL Mode Descriptions (e.g. require)
# ssl:
# ca: # if you have a CA file and want to verify it you can uncomment this section
# $file: <file-path>/ca/server.crt
{{/if}}
cache:
store: memory
# workingDirectory: /tmp # Use this to configure a working directory for the scaffolder, defaults to the OS temp-dir
@@ -30,29 +30,23 @@
"@backstage/plugin-proxy-backend": "^{{version '@backstage/plugin-proxy-backend'}}",
"@backstage/plugin-scaffolder-backend": "^{{version '@backstage/plugin-scaffolder-backend'}}",
"@backstage/plugin-search-backend": "^{{version '@backstage/plugin-search-backend'}}",
{{#if dbTypePG}}
"@backstage/plugin-search-backend-module-pg": "^{{version '@backstage/plugin-search-backend-module-pg'}}",
{{/if}}
"@backstage/plugin-search-backend-node": "^{{version '@backstage/plugin-search-backend-node'}}",
"@backstage/plugin-techdocs-backend": "^{{version '@backstage/plugin-techdocs-backend'}}",
"dockerode": "^3.3.1",
"express": "^4.17.1",
"express-promise-router": "^4.1.0",
"luxon": "^2.0.2",
{{#if dbTypePG}}
"pg": "^8.3.0",
{{/if}}
{{#if dbTypeSqlite}}
"better-sqlite3": "^7.5.0",
{{/if}}
"winston": "^3.2.1"
},
"devDependencies": {
"@backstage/cli": "^{{version '@backstage/cli'}}",
"@types/dockerode": "^3.3.0",
"@types/express": "^4.17.6",
"@types/express-serve-static-core": "^4.17.5",
"@types/luxon": "^2.0.4"
"@types/express": "^4.17.6",
"@types/luxon": "^2.0.4",
"better-sqlite3": "^7.5.0"
},
"files": [
"dist"
@@ -4,9 +4,6 @@ import {
IndexBuilder,
LunrSearchEngine,
} from '@backstage/plugin-search-backend-node';
{{#if dbTypePG}}
import { PgSearchEngine } from '@backstage/plugin-search-backend-module-pg';
{{/if}}
import { PluginEnvironment } from '../types';
import { DefaultCatalogCollatorFactory } from '@backstage/plugin-catalog-backend';
import { DefaultTechDocsCollatorFactory } from '@backstage/plugin-techdocs-backend';
@@ -17,16 +14,9 @@ export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
// Initialize a connection to a search engine.
{{#if dbTypeSqlite}}
const searchEngine = new LunrSearchEngine({
logger: env.logger,
});
{{/if}}
{{#if dbTypePG}}
const searchEngine = (await PgSearchEngine.supported(env.database))
? await PgSearchEngine.from({ database: env.database })
: new LunrSearchEngine({ logger: env.logger });
{{/if}}
const indexBuilder = new IndexBuilder({
logger: env.logger,
searchEngine,
+39 -34
View File
@@ -21,6 +21,7 @@ import handlebars from 'handlebars';
import killTree from 'tree-kill';
import { resolve as resolvePath, join as joinPath } from 'path';
import puppeteer from 'puppeteer';
import path from 'path';
import {
spawnPiped,
@@ -49,9 +50,8 @@ export async function run() {
print('Building dist workspace');
const workspaceDir = await buildDistWorkspace('workspace', rootDir);
const isPostgres = Boolean(process.env.POSTGRES_USER);
print('Creating a Backstage App');
const appDir = await createApp('test-app', isPostgres, workspaceDir, rootDir);
const appDir = await createApp('test-app', workspaceDir, rootDir);
print('Creating a Backstage Plugin');
const pluginName = await createPlugin('test-plugin', appDir);
@@ -62,8 +62,21 @@ export async function run() {
print('Starting the app');
await testAppServe(pluginName, appDir);
print('Testing the backend startup');
await testBackendStart(appDir, isPostgres);
if (Boolean(process.env.POSTGRES_USER)) {
print('Testing the PostgreSQL backend startup');
await preCleanPostgres();
const appConfig = path.resolve(appDir, 'app-config.yaml');
const productionConfig = path.resolve(appDir, 'app-config.production.yaml');
await testBackendStart(
appDir,
'--config',
appConfig,
'--config',
productionConfig,
);
}
print('Testing the SQLite backend startup');
await testBackendStart(appDir);
if (process.env.CI) {
// Cleanup actually takes significant time, so skip it in CI since the
@@ -100,8 +113,8 @@ async function buildDistWorkspace(workspaceName: string, rootDir: string) {
}
for (const pkgJsonPath of templatePackagePaths) {
const path = paths.resolveOwnRoot(pkgJsonPath);
const pkgTemplate = await fs.readFile(path, 'utf8');
const jsonPath = paths.resolveOwnRoot(pkgJsonPath);
const pkgTemplate = await fs.readFile(jsonPath, 'utf8');
const pkg = JSON.parse(
handlebars.compile(pkgTemplate)(
{
@@ -191,7 +204,6 @@ async function pinYarnVersion(dir: string) {
*/
async function createApp(
appName: string,
isPostgres: boolean,
workspaceDir: string,
rootDir: string,
) {
@@ -215,14 +227,6 @@ async function createApp(
await waitFor(() => stdout.includes('Enter a name for the app'));
child.stdin?.write(`${appName}\n`);
await waitFor(() => stdout.includes('Select database for the backend'));
if (isPostgres) {
// Simulate down arrow press
child.stdin?.write(`\u001B\u005B\u0042`);
}
child.stdin?.write(`\n`);
print('Waiting for app create script to be done');
await waitForExit(child);
@@ -404,33 +408,34 @@ async function dropDB(database: string) {
};
try {
await pgtools.dropdb({ config }, database);
await pgtools.dropdb(config, database);
} catch (_) {
/* do nothing*/
}
}
/** Clean remnants from prior e2e runs */
async function preCleanPostgres() {
print('Dropping old DBs');
await Promise.all(
[
'catalog',
'scaffolder',
'auth',
'identity',
'proxy',
'techdocs',
'search',
].map(name => dropDB(`backstage_plugin_${name}`)),
);
print('Created DBs');
}
/**
* Start serving the newly created backend and make sure that all db migrations works correctly
*/
async function testBackendStart(appDir: string, isPostgres: boolean) {
if (isPostgres) {
print('Dropping old DBs');
await Promise.all(
[
'catalog',
'scaffolder',
'auth',
'identity',
'proxy',
'techdocs',
'search',
].map(name => dropDB(`backstage_plugin_${name}`)),
);
print('Created DBs');
}
const child = spawnPiped(['yarn', 'workspace', 'backend', 'start'], {
async function testBackendStart(appDir: string, ...args: string[]) {
const child = spawnPiped(['yarn', 'workspace', 'backend', 'start', ...args], {
cwd: appDir,
env: {
...process.env,