mirror of
https://github.com/d0zingcat/ghost-docker.git
synced 2026-05-13 15:09:34 +00:00
Add script to migrate existing Ghost config
- Ghost requires env variables to be in a special `__` format which is hard to construct manually - This script automates that for ease of migration - Currently doesn't meet our ESLint rules in the slightest so will need tweaking
This commit is contained in:
142
scripts/config-to-env.js
Normal file
142
scripts/config-to-env.js
Normal file
@@ -0,0 +1,142 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Hardcoded exclusions - add any default exclusions here
|
||||
// Can be exact matches or prefixes (to exclude entire sections)
|
||||
const HARDCODED_EXCLUSIONS = [
|
||||
// We don't want the database, server, logging, process or paths
|
||||
// entries since they're not relevant in Docker anymore
|
||||
'database',
|
||||
'server',
|
||||
'logging',
|
||||
'process',
|
||||
'paths',
|
||||
// We don't need URL because its already set in our env
|
||||
'url',
|
||||
];
|
||||
|
||||
// Parse command line arguments
|
||||
function parseArgs() {
|
||||
const args = process.argv.slice(2);
|
||||
const options = {
|
||||
configFile: null,
|
||||
exclude: [],
|
||||
include: null
|
||||
};
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
if (args[i] === '--exclude' && i + 1 < args.length) {
|
||||
options.exclude = args[i + 1].split(',').map(s => s.trim());
|
||||
i++; // Skip next argument
|
||||
} else if (args[i] === '--include' && i + 1 < args.length) {
|
||||
options.include = args[i + 1].split(',').map(s => s.trim());
|
||||
i++; // Skip next argument
|
||||
} else if (!args[i].startsWith('--')) {
|
||||
options.configFile = args[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (!options.configFile) {
|
||||
console.error('Usage: node config-to-env.js <config.json> [--exclude key1,key2] [--include key1,key2]');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
// Flatten nested JSON object to environment variable format
|
||||
function flattenObject(obj, prefix = '') {
|
||||
const result = {};
|
||||
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
const newKey = prefix ? `${prefix}__${key}` : key;
|
||||
|
||||
if (value === null || value === undefined) {
|
||||
// Skip null/undefined values
|
||||
continue;
|
||||
} else if (typeof value === 'object' && !Array.isArray(value)) {
|
||||
// Recursively flatten nested objects
|
||||
Object.assign(result, flattenObject(value, newKey));
|
||||
} else if (Array.isArray(value)) {
|
||||
// Convert arrays to JSON strings
|
||||
result[newKey] = JSON.stringify(value);
|
||||
} else if (typeof value === 'boolean') {
|
||||
// Convert booleans to lowercase strings
|
||||
result[newKey] = value.toString();
|
||||
} else {
|
||||
// Store primitive values as-is
|
||||
result[newKey] = value.toString();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Format value for shell output
|
||||
function formatValue(value) {
|
||||
// If value contains spaces, newlines, or quotes, wrap in quotes
|
||||
if (typeof value === 'string' && (value.includes(' ') || value.includes('\n') || value.includes('"') || value.includes("'"))) {
|
||||
// Escape any existing double quotes
|
||||
value = value.replace(/"/g, '\\"');
|
||||
return `"${value}"`;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// Main function
|
||||
function main() {
|
||||
const options = parseArgs();
|
||||
|
||||
// Read and parse config file
|
||||
let config;
|
||||
try {
|
||||
const configContent = fs.readFileSync(options.configFile, 'utf8');
|
||||
config = JSON.parse(configContent);
|
||||
} catch (error) {
|
||||
console.error(`Error reading config file: ${error.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Flatten the configuration
|
||||
const flattened = flattenObject(config);
|
||||
|
||||
// Combine exclusions
|
||||
const allExclusions = new Set([...HARDCODED_EXCLUSIONS, ...options.exclude]);
|
||||
|
||||
// Helper function to check if key matches any exclusion pattern
|
||||
function isExcluded(key, exclusions) {
|
||||
for (const exclusion of exclusions) {
|
||||
// Check for exact match
|
||||
if (key === exclusion) {
|
||||
return true;
|
||||
}
|
||||
// Check if key starts with exclusion pattern (prefix matching)
|
||||
// This allows excluding entire sections like 'database' or 'database__connection'
|
||||
if (key.startsWith(exclusion + '__')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Filter and output environment variables
|
||||
for (const [key, value] of Object.entries(flattened)) {
|
||||
// If include list is specified, only include those keys
|
||||
if (options.include && !options.include.includes(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip excluded keys (with prefix matching)
|
||||
if (isExcluded(key, allExclusions)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Output in KEY=VALUE format
|
||||
console.log(`${key}=${formatValue(value)}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Run the script
|
||||
if (require.main === module) {
|
||||
main();
|
||||
}
|
||||
@@ -109,8 +109,25 @@ echo " MySQL is ready!"
|
||||
echo "Importing database..."
|
||||
docker compose exec -T db sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" $MYSQL_DATABASE' < "${PWD}/data/ghost_import.sql"
|
||||
|
||||
echo "The migrator will now try and import your existing configuration: "
|
||||
|
||||
# Run the config-to-env.js script
|
||||
node "${PWD}/scripts/config-to-env.js" "${current_location}/config.production.json"
|
||||
|
||||
read -rp 'Are you happy with the configuration? [y/n]: ' confirm
|
||||
case "$confirm" in
|
||||
[yY][eE][sS]|[yY])
|
||||
echo "Adding configuration to .env..."
|
||||
node "${PWD}/scripts/config-to-env.js" "${current_location}/config.production.json" >> "${PWD}/.env"
|
||||
;;
|
||||
*)
|
||||
echo "Skipping, you can manually add the configuration to .env later"
|
||||
echo "Note: Mail configuration is not imported, if you send email you will need to set it up manually"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Starting Ghost container
|
||||
echo "Starting Ghost and containers..."
|
||||
echo "Starting Ghost..."
|
||||
docker compose up ghost -d
|
||||
|
||||
read -rp 'Would you like to start Caddy? This will stop your existing Nginx installation. [y/n]: ' confirm
|
||||
|
||||
Reference in New Issue
Block a user