Merge pull request #10948 from backstage/jhaals/simplify-create-app
Remove database choice from `create-app` command
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user