diff --git a/.github/scripts/docker-compose.yml b/.github/scripts/docker-compose.yml new file mode 100644 index 0000000000..eb2caaeed9 --- /dev/null +++ b/.github/scripts/docker-compose.yml @@ -0,0 +1,19 @@ +version: '3.8' + +services: + mysql: + image: mysql:8.0.35 + container_name: ghost-mysql + ports: + - "3306:3306" + environment: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: ghost + restart: always + volumes: + # Turns out you can drop .sql or .sql.gz files in here, cool! + - ./mysql-preload:/docker-entrypoint-initdb.d + healthcheck: + test: "mysql -uroot -proot ghost -e 'select 1'" + interval: 1s + retries: 120 diff --git a/.github/scripts/mysql-preload/.keep b/.github/scripts/mysql-preload/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.github/scripts/setup.js b/.github/scripts/setup.js new file mode 100644 index 0000000000..59fd37b3b5 --- /dev/null +++ b/.github/scripts/setup.js @@ -0,0 +1,94 @@ +const {spawn} = require('child_process'); +const fs = require('fs').promises; +const path = require('path'); + +const chalk = require('chalk'); + +/** + * Run a command and stream output to the console + * + * @param {string} command + * @param {string[]} args + * @param {object} options + */ +async function runAndStream(command, args, options) { + return new Promise((resolve, reject) => { + const child = spawn(command, args, { + stdio: 'inherit', + ...options + }); + + child.on('close', (code) => { + if (code === 0) { + resolve(code); + } else { + reject(new Error(`'${command} ${args.join(' ')}' exited with code ${code}`)); + } + }); + + }); +} + +(async () => { + if (process.env.NODE_ENV !== 'development') { + console.log(chalk.yellow(`NODE_ENV is not development, skipping setup`)); + return; + } + + const coreFolder = path.join(__dirname, '../../ghost/core'); + const config = require('../../ghost/core/core/shared/config/loader').loadNconf({ + customConfigPath: coreFolder + }); + + const dbClient = config.get('database:client'); + + if (!dbClient.includes('mysql')) { + let mysqlSetup = false; + console.log(chalk.blue(`Attempting to setup MySQL via Docker`)); + try { + await runAndStream('yarn', ['docker:reset'], {cwd: path.join(__dirname, '../../')}); + mysqlSetup = true; + } catch (err) { + console.error(chalk.red('Failed to run MySQL Docker container'), err); + console.error(chalk.red('Hint: is Docker installed and running?')); + } + + if (mysqlSetup) { + console.log(chalk.blue(`Adding MySQL credentials to config.local.json`)); + const currentConfigPath = path.join(coreFolder, 'config.local.json'); + + let currentConfig; + try { + currentConfig = require(currentConfigPath); + } catch (err) { + currentConfig = {}; + } + + currentConfig.database = { + client: 'mysql', + connection: { + host: '127.0.0.1', + user: 'root', + password: 'root', + database: 'ghost' + } + }; + + try { + await fs.writeFile(currentConfigPath, JSON.stringify(currentConfig, null, 4)); + } catch (err) { + console.error(chalk.red('Failed to write config.local.json'), err); + console.log(chalk.yellow(`Please add the following to config.local.json:\n`), JSON.stringify(currentConfig, null, 4)); + process.exit(1); + } + + console.log(chalk.blue(`Running knex-migrator init`)); + await runAndStream('yarn', ['knex-migrator', 'init'], {cwd: coreFolder}); + + //console.log(chalk.blue(`Running data generator`)); + //await runAndStream('node', ['index.js', 'generate-data'], {cwd: coreFolder}); + } + } else { + console.log(chalk.green(`MySQL already configured, skipping setup`)); + } +})(); diff --git a/package.json b/package.json index a4a986bedc..3f8b7f6848 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,8 @@ "dev": "node .github/scripts/dev.js", "fix": "yarn cache clean && rm -rf node_modules && yarn", "knex-migrator": "yarn workspace ghost run knex-migrator", - "setup": "yarn && git submodule update --init", + "setup": "yarn && git submodule update --init && NODE_ENV=development node .github/scripts/setup.js", + "docker:reset": "docker-compose -f .github/scripts/docker-compose.yml down -v && docker-compose -f .github/scripts/docker-compose.yml up -d --wait", "lint": "nx run-many -t lint", "test": "nx run-many -t test", "test:unit": "nx run-many -t test:unit",