diff --git a/.changeset/selfish-games-deny.md b/.changeset/selfish-games-deny.md new file mode 100644 index 0000000000..2d283b10de --- /dev/null +++ b/.changeset/selfish-games-deny.md @@ -0,0 +1,5 @@ +--- +'@techdocs/cli': minor +--- + +validate Docker status before running mkdocs server diff --git a/packages/techdocs-cli/src/commands/serve/mkdocs.ts b/packages/techdocs-cli/src/commands/serve/mkdocs.ts index c061d4474f..00c5e5f0ed 100644 --- a/packages/techdocs-cli/src/commands/serve/mkdocs.ts +++ b/packages/techdocs-cli/src/commands/serve/mkdocs.ts @@ -21,6 +21,7 @@ import { runMkdocsServer } from '../../lib/mkdocsServer'; import { LogFunc, waitForSignal } from '../../lib/run'; import { getMkdocsYml } from '@backstage/plugin-techdocs-node'; import fs from 'fs-extra'; +import { checkIfDockerIsOperational } from './utils'; export default async function serveMkdocs(opts: OptionValues) { const logger = createLogger({ verbose: opts.verbose }); @@ -29,6 +30,13 @@ export default async function serveMkdocs(opts: OptionValues) { const localAddr = `http://127.0.0.1:${opts.port}`; const expectedDevAddr = opts.docker ? dockerAddr : localAddr; + if (opts.docker) { + const isDockerOperational = await checkIfDockerIsOperational(logger); + if (!isDockerOperational) { + return; + } + } + const { path: mkdocsYmlPath, configIsTemporary } = await getMkdocsYml( './', opts.siteName, diff --git a/packages/techdocs-cli/src/commands/serve/serve.ts b/packages/techdocs-cli/src/commands/serve/serve.ts index 5fcf1787d3..98c9982b21 100644 --- a/packages/techdocs-cli/src/commands/serve/serve.ts +++ b/packages/techdocs-cli/src/commands/serve/serve.ts @@ -24,6 +24,7 @@ import { LogFunc, waitForSignal } from '../../lib/run'; import { createLogger } from '../../lib/utility'; import { getMkdocsYml } from '@backstage/plugin-techdocs-node'; import fs from 'fs-extra'; +import { checkIfDockerIsOperational } from './utils'; function findPreviewBundlePath(): string { try { @@ -73,6 +74,14 @@ export default async function serve(opts: OptionValues) { mkdocsConfigFileName, }); + // Validate that Docker is up and running + if (opts.docker) { + const isDockerOperational = await checkIfDockerIsOperational(logger); + if (!isDockerOperational) { + return; + } + } + let mkdocsServerHasStarted = false; const mkdocsLogFunc: LogFunc = data => { // Sometimes the lines contain an unnecessary extra new line diff --git a/packages/techdocs-cli/src/commands/serve/utils.ts b/packages/techdocs-cli/src/commands/serve/utils.ts new file mode 100644 index 0000000000..2b19b0fbc0 --- /dev/null +++ b/packages/techdocs-cli/src/commands/serve/utils.ts @@ -0,0 +1,38 @@ +/* + * Copyright 2023 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 { promisify } from 'util'; +import * as winston from 'winston'; +import { execFile } from 'child_process'; + +export async function checkIfDockerIsOperational( + logger: winston.Logger, +): Promise { + logger.info('Checking Docker status...'); + try { + const runCheck = promisify(execFile); + await runCheck('docker', ['info'], { shell: true }); + logger.info( + 'Docker is up and running. Proceed to starting up mkdocs server', + ); + return true; + } catch { + logger.error( + 'Docker is not running. Exiting. Please check status of Docker daemon with `docker info` before re-running', + ); + return false; + } +}