From 03f4b62b5a12304bd9b1f5a264c6fbb573567d8e Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 9 Feb 2016 22:26:45 -0800 Subject: [PATCH 01/66] Updated npm deps and engine in package.json; updated travis nvm version --- .travis.yml | 2 +- package.json | 24 ++++++++++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index b0142cb1..a00b20b2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ addons: - www.example.com before_install: # node setup (for yeoman/bower) - - nvm install 0.10 + - nvm install 4.0 - node --version - npm --version - nvm --version diff --git a/package.json b/package.json index 7ff7499b..b6c54f4a 100644 --- a/package.json +++ b/package.json @@ -4,22 +4,26 @@ "version": "1.3.5", "description": "Libraries for a multi-staged WordPress workflow with Vagrant", "main": "lib/yeoman/index.js", + "engines": { + "node": ">=4.0" + }, "dependencies": { - "chalk": "^0.5.1", - "fs-extra": "^0.20.1", - "request": "^2.42.0", + "chalk": "^1.1.1", + "fs-extra": "^0.26.4", + "request": "^2.67.0", "ssh-keygen": "^0.2.1", - "in-words": "^0.1.0", - "yeoman-generator": "^0.16.0", - "deasync": "^0.1.0", - "inquirer": "^0.8.5", + "in-words": "^0.2.0", + "yeoman-generator": "^0.22.4", + "yeoman-test": "^1.0.0", + "deasync": "^0.1.4", + "inquirer": "^0.11.2", "replace": "^0.3.0", "adm-zip": "^0.4.7", - "glob": "^4.0.4" + "glob": "^6.0.4" }, "devDependencies": { - "mocha": "^1.20.1", - "zombie": "^3.1.1" + "mocha": "^2.3.4", + "zombie": "^4.2.1" }, "scripts": { "test": "./bin/test" From 3dedd38fecccf5516f99479dc98486b4c839a526 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 9 Feb 2016 22:41:07 -0800 Subject: [PATCH 02/66] Node 4 improvements --- bin/import | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/bin/import b/bin/import index f02c52e1..21f3bd1e 100755 --- a/bin/import +++ b/bin/import @@ -1,7 +1,6 @@ #!/usr/bin/env node -var fs = require('fs'); -var fsx = require('fs-extra'); +var fs = require('fs-extra'); var os = require('os'); var path = require('path'); var cp = require('child_process'); @@ -9,7 +8,7 @@ var util = require('util'); var chalk = require('chalk'); var deasync = require('deasync'); var inquirer = require('inquirer'); -var replace = require("replace"); +var replace = require('replace'); var AdmZip = require('adm-zip'); // Evolution site working directory @@ -36,7 +35,7 @@ catch(e) { // extract zip to tmpdir var extractedPath = path.join(os.tmpdir(), path.basename(answers.zipfile, '.zip')); -fsx.emptyDirSync(extractedPath); +fs.emptyDirSync(extractedPath); console.log('Extracting', chalk.yellow(answers.zipfile), 'to', chalk.green(extractedPath)); @@ -124,16 +123,15 @@ if (searchDomains.length) { } // run sql against db -var cpExec = deasync(cp.exec); var capCmd = 'bundle exec cap local evolve:db:exec[' + path.join(extractedPath, 'wordpress.sql') + ']'; console.log('importing sql via:', chalk.cyan(capCmd)); -cpExec(capCmd, {cwd: siteDirectory, env: util._extend(process.env, {evolution_non_interactive: 1}), stdio: 'inherit'}); +cp.execSync(capCmd, {cwd: siteDirectory, env: util._extend(process.env, {evolution_non_interactive: 1}), stdio: 'inherit'}); // list all users via wp-cli capCmd = 'bundle exec cap local wp:user:list:--fields=ID,user_login,roles:--format=json'; console.log('listing users via:', chalk.cyan(capCmd)); -var capOut = cpExec(capCmd, {cwd: siteDirectory, env: process.env, stdio: 'inherit'}); +var capOut = cp.execSync(capCmd, {cwd: siteDirectory, env: process.env, stdio: 'inherit'}); // prompt for role of any users lacking one var existingUsers = capOut.match(/\s+(\[\{"ID":[^\r\n]+)/); @@ -162,7 +160,7 @@ if (existingUsers) { capCmd = 'bundle exec cap local wp:user:add-role:'+user.ID+':'+answers.role; console.log('assigning user role via:', chalk.cyan(capCmd)); - cpExec(capCmd, {cwd: siteDirectory, env: process.env, stdio: 'inherit'}); + cp.execSync(capCmd, {cwd: siteDirectory, env: process.env, stdio: 'inherit'}); } }); } @@ -170,18 +168,18 @@ if (existingUsers) { // Copying Themes / Plugins / Uploads var pluginsPath = path.join(extractedPath, 'plugins'); console.log('installing plugins from', chalk.cyan(pluginsPath)); -fsx.copySync(pluginsPath, path.join(siteDirectory, 'web', 'wp-content', 'plugins'), {clobber: true}); +fs.copySync(pluginsPath, path.join(siteDirectory, 'web', 'wp-content', 'plugins'), {clobber: true}); var themesPath = path.join(extractedPath, 'themes'); console.log('installing themes from', chalk.cyan(themesPath)); -fsx.copySync(themesPath, path.join(siteDirectory, 'web', 'wp-content', 'themes'), {clobber: true}); +fs.copySync(themesPath, path.join(siteDirectory, 'web', 'wp-content', 'themes'), {clobber: true}); var uploadsPath = path.join(extractedPath, 'uploads'); if (manifest.is_multisite) { uploadsPath = path.join(uploadsPath, 'sites', manifest.blogid); } console.log('installing uploads from', chalk.cyan(uploadsPath)); -fsx.copySync(uploadsPath, path.join(siteDirectory, 'web', 'wp-content', 'uploads'), {clobber: true}); +fs.copySync(uploadsPath, path.join(siteDirectory, 'web', 'wp-content', 'uploads'), {clobber: true}); console.log(chalk.green('looks like we\'re done here!')); From 313cead96650bda955996ac7c9af06e9c62cb314 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 9 Feb 2016 22:43:45 -0800 Subject: [PATCH 03/66] Updating generator and yeoman test hooks --- bin/mock | 2 +- lib/yeoman/index.js | 148 +++++++++++++++++++++++++------------------- 2 files changed, 87 insertions(+), 63 deletions(-) diff --git a/bin/mock b/bin/mock index 79fd89d7..58cb48cd 100755 --- a/bin/mock +++ b/bin/mock @@ -2,7 +2,7 @@ var fs = require('fs-extra'); var exec = require('child_process').exec; -var helpers = require('yeoman-generator').test; +var helpers = require('yeoman-test'); var path = require('path'); var outputDir = path.join(__dirname, '..', 'temp'); diff --git a/lib/yeoman/index.js b/lib/yeoman/index.js index 12b9bb2f..eefba938 100644 --- a/lib/yeoman/index.js +++ b/lib/yeoman/index.js @@ -9,10 +9,11 @@ var keygen = require('ssh-keygen'); var request = require('request'); var yeoman = require('yeoman-generator'); var util = require('util'); +var cp = require('child_process'); -var WordpressGenerator = yeoman.generators.Base.extend({ +var WordpressGenerator = yeoman.Base.extend({ init: function() { - this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../../package.json'))); + this.pkg = this.fs.readJSON(path.join(__dirname, '../../package.json')); this.prompts = []; this.option('dev', { @@ -37,7 +38,7 @@ var WordpressGenerator = yeoman.generators.Base.extend({ }, welcome: function() { - var message = this.readFileAsString(path.join(__dirname, 'welcome.txt')); + var message = this.fs.read(path.join(__dirname, 'welcome.txt')); message = message.replace(/./g, function(match) { return /\w/.test(match) ? chalk.yellow(match) : chalk.cyan(match); @@ -95,7 +96,7 @@ var WordpressGenerator = yeoman.generators.Base.extend({ ]; var existing = function() { try { - var bower = JSON.parse(this.readFileAsString(bowerFile)); + var bower = this.fs.readJSON(bowerFile); return !bower.private; } catch(e) {}; @@ -117,7 +118,7 @@ var WordpressGenerator = yeoman.generators.Base.extend({ var defaultSsl = true; try { - var provisionYml = this.readFileAsString(path.join(this.env.cwd, 'lib', 'ansible', 'provision.yml')); + var provisionYml = this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'provision.yml')); defaultSsl = !!provisionYml.match(/^\s*-\s+pound/m); } catch(e) {}; @@ -188,7 +189,7 @@ var WordpressGenerator = yeoman.generators.Base.extend({ promptForName: function() { var existing = function() { try { - var bower = JSON.parse(this.readFileAsString(path.join(this.env.cwd, 'bower.json'))); + var bower = this.fs.readJSON(path.join(this.env.cwd, 'bower.json')); return bower.name; } catch(e) {}; @@ -208,7 +209,7 @@ var WordpressGenerator = yeoman.generators.Base.extend({ promptForDomain: function() { var existing = function() { try { - var match = this.readFileAsString(path.join(this.env.cwd, 'Vagrantfile')) + var match = this.fs.read(path.join(this.env.cwd, 'Vagrantfile')) .match(/box.vm.hostname[ ]*=[ ]*"local.([^"]+)"/); return match[1]; @@ -248,7 +249,7 @@ var WordpressGenerator = yeoman.generators.Base.extend({ ]; var existing = function() { try { - var match = this.readFileAsString(path.join(this.env.cwd, 'lib', 'ansible', 'group_vars', 'all')) + var match = this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'group_vars', 'all')) .match(/www[ ]*:[ ]*(true)/i); return match[1]; @@ -271,7 +272,7 @@ var WordpressGenerator = yeoman.generators.Base.extend({ promptForNewrelic: function() { var existing = function() { try { - var match = this.readFileAsString(path.join(this.env.cwd, 'lib', 'ansible', 'group_vars', 'all')) + var match = this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'group_vars', 'all')) .match(/newrelic[ ]*:[ ]*(?:'|")?([^'"\s]+)/i); return match[1]; @@ -291,7 +292,7 @@ var WordpressGenerator = yeoman.generators.Base.extend({ promptForRoles: function() { try { - var provisionYml = this.readFileAsString(path.join(this.env.cwd, 'lib', 'ansible', 'provision.yml')); + var provisionYml = this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'provision.yml')); WordpressGenerator.roles.forEach(function (role, index) { var regex = new RegExp('^\\s*-\\s+' + role.value.split(' ')[0], 'm'); @@ -314,7 +315,7 @@ var WordpressGenerator = yeoman.generators.Base.extend({ promptForWordPress: function() { var existing = function() { try { - var file = this.readFileAsString(path.join(this.env.cwd, 'web', 'wp', 'wp-includes', 'version.php')); + var file = this.fs.read(path.join(this.env.cwd, 'web', 'wp', 'wp-includes', 'version.php')); var version = file.match(/\$wp_version\s=\s['"]([^'"]+)/); if (version.length) { @@ -342,7 +343,7 @@ var WordpressGenerator = yeoman.generators.Base.extend({ promptForTablePrefix: function() { var existing = function() { try { - var config = this.readFileAsString(path.join(this.env.cwd, 'web', 'wp-config.php')); + var config = this.fs.read(path.join(this.env.cwd, 'web', 'wp-config.php')); var prefix = config.match(/\$table_prefix\s*=\s*['"]([^'"]+)/); if (prefix.length) { @@ -365,7 +366,7 @@ var WordpressGenerator = yeoman.generators.Base.extend({ var done = this.async(); var existing = function(constant) { try { - var config = this.readFileAsString(path.join(this.env.cwd, 'web', 'wp-config.php')); + var config = this.fs.read(path.join(this.env.cwd, 'web', 'wp-config.php')); var regex = new RegExp(constant + '[\'"],\\s*[\\w:(]*[\'"]([^\'"]+)'); var matches = regex.exec(config); @@ -436,7 +437,7 @@ var WordpressGenerator = yeoman.generators.Base.extend({ }); try { - var vagrant = this.readFileAsString('Vagrantfile').match(/ip:\s['"]([\d\.]+)['"]/); + var vagrant = this.fs.read('Vagrantfile').match(/ip:\s['"]([\d\.]+)['"]/); if (vagrant.length) { ips.unshift(vagrant[1]); @@ -465,10 +466,10 @@ var WordpressGenerator = yeoman.generators.Base.extend({ prepareReadme: function() { try { - this.readmeFile = this.readFileAsString(path.join(this.env.cwd, 'README.md')); + this.readmeFile = this.fs.read(path.join(this.env.cwd, 'README.md')); this.readmeFile = this.readmeFile .replace(/^(?:\[[^\]\r\n]+\]){1,2}(?:\([^\)\r\n]+\))?[\r\n]+=+[\r\n]+> Powered by \[(?:Genesis|Evolution)[^\r\n]+[\r\n]+/i, '') - .replace(/[\r\n]\[[^\]\r\n]+\]:\s*http[^\r\n]+[\r\n]+\[(?:genesis|evolution)-wordpress\]:\s*http[^\r\n]+[\r\n]*$/i, '') + .replace(/(?:^|[\r\n])\[[^\]\r\n]+\]:\s*http[^\r\n]+[\r\n]+\[(?:genesis|evolution)-wordpress\]:\s*http[^\r\n]+[\r\n]*$/i, '') ; } catch(e) { this.readmeFile = ''; @@ -477,7 +478,7 @@ var WordpressGenerator = yeoman.generators.Base.extend({ prepareHtaccess: function() { try { - this.htaccessFile = this.readFileAsString(path.join(this.env.cwd, 'web', '.htaccess')); + this.htaccessFile = this.fs.read(path.join(this.env.cwd, 'web', '.htaccess')); this.htaccessFile = this.htaccessFile.replace(/# BEGIN Evolution WordPress(?:.|[\r\n]+)+?# END Evolution WordPress[\r\n]*/i, '').trim(); this.htaccessWpBlock = !!this.htaccessFile.match(/# BEGIN WordPress(?:.|[\r\n]+)+?# END WordPress[\r\n]*/i); @@ -489,7 +490,7 @@ var WordpressGenerator = yeoman.generators.Base.extend({ prepareGitignore: function () { try { - this.gitignoreFile = this.readFileAsString(path.join(this.env.cwd, '.gitignore')); + this.gitignoreFile = this.fs.read(path.join(this.env.cwd, '.gitignore')); this.gitignoreFile = this.gitignoreFile.match(/[\r\n]+# Generated file, don't edit above this line[\r\n]*([\S\s]*?)[\r\n]*$/i)[1]; } catch(e) { this.gitignoreFile = ''; @@ -528,7 +529,7 @@ var WordpressGenerator = yeoman.generators.Base.extend({ this.log.info('Creating SSH keys...'); - this.mkdir(path.dirname(location)); + fs.mkdirsSync(path.dirname(location)); keygen({ location: location, @@ -538,8 +539,9 @@ var WordpressGenerator = yeoman.generators.Base.extend({ }, prepareTemplates: function() { - this.templates = this.expandFiles('**/*', { + this.templates = glob.sync('**/*', { cwd: this.sourceRoot(), + nodir: true, }); }, @@ -555,53 +557,60 @@ var WordpressGenerator = yeoman.generators.Base.extend({ this.log.info(chalk.green('Symlinking local Evolution WordPress as dependency...')); - var srcpath = '../../../wordpress'; + var srcpath = path.join(__dirname, '../../../wordpress'); var dstpath = path.join(this.env.cwd, 'bower_components', 'evolution-wordpress'); - this.mkdir(path.dirname(dstpath)); + this.log.info('symlinking from', chalk.red(srcpath), 'to', chalk.blue(dstpath)); - fs.symlinkSync(srcpath, dstpath); + fs.mkdirsSync(path.dirname(dstpath)); + fs.ensureSymlinkSync(srcpath, dstpath); }, - /** - * Specify project dependencies (e.g. WordPress, Evolution, etc.) via `bower.json` - */ - copyBower: function() { - this.template('bower.json', 'bower.json'); - this.template('_bowerrc', '.bowerrc'); - }, + bootstrapBower: function() { + // bower files we'll be bootstrapping + var bowerJson = this.destinationPath('bower.json'); + var bowerRc = this.destinationPath('.bowerrc'); - /** - * Install project dependencies (e.g. WordPress, Evolution) for later usage by the generator - */ - runBower: function() { - var done = this.async(); + // minimum viable json for bower install + postinstall + var bowerBootstrap = { + "name": this.props.name, + "dependencies": { + "evolution-wordpress": (this.options.dev ? 'master' : '~' + this.pkg.version), + "wordpress": this.props.wordpress, + } + }; - this.log.info(chalk.green('Installing project dependencies...')); + // backup existing bower files as necessary + var backupBowerJson = fs.existsSync(bowerJson) ? fs.readFileSync(bowerJson) : null; + var backupBowerRc = fs.existsSync(bowerRc) ? fs.readFileSync(bowerRc) : null; - this.bowerInstall(null, null, done); - }, + // bootstrap bower files + fs.writeFileSync(bowerJson, JSON.stringify(bowerBootstrap)); + fs.copySync(this.templatePath('_bowerrc'), bowerRc, {clobber:true}); - /** - * Bower's `postInstall` can only be ran after all other dependencies have been installed - */ - copyBowerrc: function() { - this.template('_bowerrc', '.bowerrc'); + // bower install from bootstrapped files + cp.spawnSync('bower', ['install'], {cwd: this.env.cwd, env: process.env, stdio: 'inherit'}); + + // restore existing bower files as necessary + backupBowerJson ? fs.writeFileSync(bowerJson, backupBowerJson) : fs.unlinkSync(bowerJson); + backupBowerRc ? fs.writeFileSync(bowerRc, backupBowerRc) : fs.unlinkSync(bowerRc); }, prepareWpConfig: function() { - this.wpConfigFile = this.readFileAsString(path.join(this.env.cwd, 'web', 'wp', 'wp-config-sample.php')); + this.wpConfigFile = this.fs.read(path.join(this.env.cwd, 'web', 'wp', 'wp-config-sample.php')); }, scaffold: function() { this.log.info(chalk.green('Scaffolding...')); this.templates.forEach(function(file) { + this.log.info('scaffolding', chalk.red(file)); this.template(file, file.replace(/(^|\/)_/, '$1.')); + this.log.info('scaffolded', chalk.blue(file)); }.bind(this)); }, - generateSslCert: function() { + generateSslCerts: function() { if (!this.props.ssl) { return false; } @@ -624,7 +633,7 @@ var WordpressGenerator = yeoman.generators.Base.extend({ this.log.info('Creating self-signed SSL certificate...'); - this.mkdir(path.dirname(location)); + fs.mkdirsSync(path.dirname(location)); stages.forEach(function (stage) { this.emit('sslInstall'+stage); @@ -681,26 +690,41 @@ var WordpressGenerator = yeoman.generators.Base.extend({ fs.chmodSync(path.join(this.env.cwd, 'lib', 'ansible', 'files', 'ssh', 'id_rsa'), '600'); }, - installGems: function() { - var done = this.async(); - var installer = 'bundle'; + install: { + installGems: function() { + var done = this.async(); + var installer = 'bundle'; - this.log.info(chalk.green('Installing Gems...')); + this.log.info(chalk.green('Installing Gems...')); - this.emit(installer + 'Install'); + this.emit(installer + 'Install'); - this - .spawnCommand(installer, ['install'], done) - .on('error', done) - .on('exit', this.emit.bind(this, installer + 'Install:end')) - .on('exit', function (err) { - if (err === 127) { - this.log.error('Could not run bundler. Please install with `sudo ' + installer + ' install`.'); - } + this + .spawnCommand(installer, ['install']) + .on('error', done) + .on('exit', this.emit.bind(this, installer + 'Install:end')) + .on('exit', function (err) { + if (err === 127) { + this.log.error('Could not run bundler. Please install with `sudo ' + installer + ' install`.'); + } - done(err); - }.bind(this)) - ; + done(err); + }.bind(this)) + ; + }, + + installBower: function () { + var done = this.async(); + + this.log.info(chalk.green('Reinstalling bower...')); + + this.spawnCommand('bower', ['install']) + .on('error', function (err) { + this.log.error('Could not run', chalk.yellow('bower install')); + }.bind(this)) + .on('exit', done) + ; + }, }, }); From c408432545b6ca522de19a3baa86422bf5b9e06d Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 9 Feb 2016 22:59:50 -0800 Subject: [PATCH 04/66] Slight template engine syntax change --- lib/yeoman/templates/Evolution.php | 2 +- lib/yeoman/templates/README.md | 10 +++++----- lib/yeoman/templates/Vagrantfile | 8 ++++---- lib/yeoman/templates/_gitignore | 2 +- lib/yeoman/templates/bower.json | 8 ++++---- .../templates/lib/ansible/files/ssl/local.cfg | 2 +- .../lib/ansible/files/ssl/production.cfg | 6 +++--- .../lib/ansible/files/ssl/staging.cfg | 4 ++-- .../templates/lib/ansible/group_vars/all | 18 +++++++++--------- lib/yeoman/templates/lib/ansible/hosts | 6 +++--- lib/yeoman/templates/lib/ansible/provision.yml | 4 ++-- lib/yeoman/templates/lib/capistrano/deploy.rb | 6 +++--- .../templates/lib/capistrano/deploy/local.rb | 2 +- .../lib/capistrano/deploy/production.rb | 2 +- .../templates/lib/capistrano/deploy/staging.rb | 2 +- lib/yeoman/templates/web/_htaccess | 12 ++++++------ lib/yeoman/templates/web/robots.txt | 2 +- lib/yeoman/templates/web/wp-config.php | 2 +- 18 files changed, 49 insertions(+), 49 deletions(-) diff --git a/lib/yeoman/templates/Evolution.php b/lib/yeoman/templates/Evolution.php index 6cae73c8..64edd92f 100644 --- a/lib/yeoman/templates/Evolution.php +++ b/lib/yeoman/templates/Evolution.php @@ -2,7 +2,7 @@ class Evolution { - const DOMAIN = '<%= props.domain %>'; + const DOMAIN = '<%- props.domain %>'; public static $hostname; public static $env; diff --git a/lib/yeoman/templates/README.md b/lib/yeoman/templates/README.md index 4e01e958..3aaebc4b 100644 --- a/lib/yeoman/templates/README.md +++ b/lib/yeoman/templates/README.md @@ -1,8 +1,8 @@ -[<%= props.name %>][<%= props.domain %>] -<%= new Array(props.name.length + props.domain.length + 5).join('=') %> +[<%- props.name %>][<%- props.domain %>] +<%- new Array(props.name.length + props.domain.length + 5).join('=') %> -> Powered by [Evolution WordPress][evolution-wordpress] *v<%= pkg.version %>* +> Powered by [Evolution WordPress][evolution-wordpress] *v<%- pkg.version %>* -<%= readmeFile %> -[<%= props.domain %>]: http://<%= props.domain %>/ +<%- readmeFile %> +[<%- props.domain %>]: http://<%- props.domain %>/ [evolution-wordpress]: https://github.com/evolution/wordpress/ diff --git a/lib/yeoman/templates/Vagrantfile b/lib/yeoman/templates/Vagrantfile index 6c79308c..a90d6ddb 100644 --- a/lib/yeoman/templates/Vagrantfile +++ b/lib/yeoman/templates/Vagrantfile @@ -33,16 +33,16 @@ Vagrant.configure("2") do |config| end config.vm.define :local do |box| - box.vm.hostname = "local.<%= props.domain %>" + box.vm.hostname = "local.<%- props.domain %>" # Static IP for testing. - box.vm.network :private_network, ip: "<%= props.ip %>" - box.vm.network :forwarded_port, guest: 22, id: 'ssh', host: <%= props.ip.split('.').join('').split('0').join('').slice(-4) %>, auto_correct: true + box.vm.network :private_network, ip: "<%- props.ip %>" + box.vm.network :forwarded_port, guest: 22, id: 'ssh', host: <%- props.ip.split('.').join('').split('0').join('').slice(-4) %>, auto_correct: true # Remount the default shared folder as NFS for caching and speed box.vm.synced_folder ".", "/vagrant", :nfs => true - # Provision local.<%= props.domain %> + # Provision local.<%- props.domain %> box.vm.provision :ansible do |ansible| ansible.playbook = "lib/ansible/provision.yml" ansible.inventory_path = "lib/ansible/hosts" diff --git a/lib/yeoman/templates/_gitignore b/lib/yeoman/templates/_gitignore index a3aa65e8..57435253 100644 --- a/lib/yeoman/templates/_gitignore +++ b/lib/yeoman/templates/_gitignore @@ -55,4 +55,4 @@ backups web/wp # Generated file, don't edit above this line -<%= gitignoreFile %> +<%- gitignoreFile %> diff --git a/lib/yeoman/templates/bower.json b/lib/yeoman/templates/bower.json index 9e14db28..e76dbfb2 100644 --- a/lib/yeoman/templates/bower.json +++ b/lib/yeoman/templates/bower.json @@ -1,9 +1,9 @@ { - "private": <%= props.private ? 'true' : 'false' %>, - "name": "<%= props.name %>", + "private": <%- props.private ? 'true' : 'false' %>, + "name": "<%- props.name %>", "version": "1.0.0", "dependencies": { - "evolution-wordpress": "<%= options.dev ? 'master' : '~' + pkg.version %>", - "wordpress": "<%= props.wordpress %>" + "evolution-wordpress": "<%- options.dev ? 'master' : '~' + pkg.version %>", + "wordpress": "<%- props.wordpress %>" } } diff --git a/lib/yeoman/templates/lib/ansible/files/ssl/local.cfg b/lib/yeoman/templates/lib/ansible/files/ssl/local.cfg index 226e67ca..c4db4ac2 100644 --- a/lib/yeoman/templates/lib/ansible/files/ssl/local.cfg +++ b/lib/yeoman/templates/lib/ansible/files/ssl/local.cfg @@ -11,7 +11,7 @@ C=US ST=Texas L=Houston O=IT -CN=local.<%= props.domain %> +CN=local.<%- props.domain %> [ v3_req ] basicConstraints = CA:FALSE diff --git a/lib/yeoman/templates/lib/ansible/files/ssl/production.cfg b/lib/yeoman/templates/lib/ansible/files/ssl/production.cfg index 7b724cb7..e52ccec6 100644 --- a/lib/yeoman/templates/lib/ansible/files/ssl/production.cfg +++ b/lib/yeoman/templates/lib/ansible/files/ssl/production.cfg @@ -11,7 +11,7 @@ C=US ST=Texas L=Houston O=IT -CN=<%= props.domain %> +CN=<%- props.domain %> [ v3_req ] basicConstraints = CA:FALSE @@ -19,5 +19,5 @@ keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName = @alt_names [ alt_names ] -DNS.1 = www.<%= props.domain %> -DNS.2 = production.<%= props.domain %> +DNS.1 = www.<%- props.domain %> +DNS.2 = production.<%- props.domain %> diff --git a/lib/yeoman/templates/lib/ansible/files/ssl/staging.cfg b/lib/yeoman/templates/lib/ansible/files/ssl/staging.cfg index a7e9d062..413aca62 100644 --- a/lib/yeoman/templates/lib/ansible/files/ssl/staging.cfg +++ b/lib/yeoman/templates/lib/ansible/files/ssl/staging.cfg @@ -11,7 +11,7 @@ C=US ST=Texas L=Houston O=IT -CN=staging.<%= props.domain %> +CN=staging.<%- props.domain %> [ v3_req ] basicConstraints = CA:FALSE @@ -19,4 +19,4 @@ keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName = @alt_names [ alt_names ] -DNS.1 = *.staging.<%= props.domain %> +DNS.1 = *.staging.<%- props.domain %> diff --git a/lib/yeoman/templates/lib/ansible/group_vars/all b/lib/yeoman/templates/lib/ansible/group_vars/all index e5b34f98..1cdac582 100644 --- a/lib/yeoman/templates/lib/ansible/group_vars/all +++ b/lib/yeoman/templates/lib/ansible/group_vars/all @@ -1,16 +1,16 @@ --- -evolve_version: <%= pkg.version %> -domain: <%= props.domain %> -www: <%= props.www %> +evolve_version: <%- pkg.version %> +domain: <%- props.domain %> +www: <%- props.www %> monitoring: - newrelic: '<%= props.newrelic %>' + newrelic: '<%- props.newrelic %>' mysql: - name: <%= props.DB_NAME %> - user: <%= props.DB_USER %> - password: <%= props.DB_PASSWORD %> - host: <%= props.DB_HOST %> + name: <%- props.DB_NAME %> + user: <%- props.DB_USER %> + password: <%- props.DB_PASSWORD %> + host: <%- props.DB_HOST %> # php__memory_limit: @@ -20,7 +20,7 @@ mysql: # apache__max_clients: # apache__max_requests_per_child: -mail__postmaster: no-reply@<%= props.domain %> +mail__postmaster: no-reply@<%- props.domain %> # iptables__ipv6: 0 diff --git a/lib/yeoman/templates/lib/ansible/hosts b/lib/yeoman/templates/lib/ansible/hosts index 1dc71f2b..1df75e8d 100644 --- a/lib/yeoman/templates/lib/ansible/hosts +++ b/lib/yeoman/templates/lib/ansible/hosts @@ -1,8 +1,8 @@ [local] -local.<%= props.domain %> stage=local +local.<%- props.domain %> stage=local [production] -production.<%= props.domain %> stage=production +production.<%- props.domain %> stage=production [staging] -staging.<%= props.domain %> stage=staging +staging.<%- props.domain %> stage=staging diff --git a/lib/yeoman/templates/lib/ansible/provision.yml b/lib/yeoman/templates/lib/ansible/provision.yml index 1f704b3e..0bb77db6 100644 --- a/lib/yeoman/templates/lib/ansible/provision.yml +++ b/lib/yeoman/templates/lib/ansible/provision.yml @@ -14,8 +14,8 @@ - wp-cli # (Required) CLI for managing WordPress # Optional Features - <% if (props.ssl) { %>- pound # (Optional) SSL support & decryption<% } %><% props.roles.map(function(role) { %> - <%= role.checked ? '-' : '#' %> <%= role.value %><% }) %> + <%- props.ssl ? '-' : '#' %> pound # (Optional) SSL support & decryption<% props.roles.map(function(role) { %> + <%- role.checked ? '-' : '#' %> <%- role.value %><% }) %> <% if (props.newrelic) { %> - newrelic # (Optional) New Relic application/server monitoring <% } %> # /Optional Features diff --git a/lib/yeoman/templates/lib/capistrano/deploy.rb b/lib/yeoman/templates/lib/capistrano/deploy.rb index f46208ba..d7725796 100644 --- a/lib/yeoman/templates/lib/capistrano/deploy.rb +++ b/lib/yeoman/templates/lib/capistrano/deploy.rb @@ -10,12 +10,12 @@ end # Repository name -set :application, "<%= props.name %>" -set :domain, "<%= props.domain %>" +set :application, "<%- props.name %>" +set :domain, "<%- props.domain %>" set :deploy_to, "/var/www/#{fetch(:domain)}/#{fetch(:stage)}/#{fetch(:branch)}" set :linked_dirs, %w{web/wp-content/uploads} set :wp_path, "#{release_path}/web/wp" -set :www, <%= props.www ? 'true' : 'false' %> +set :www, <%- props.www ? 'true' : 'false' %> namespace :deploy do after :updated, :bower_install do diff --git a/lib/yeoman/templates/lib/capistrano/deploy/local.rb b/lib/yeoman/templates/lib/capistrano/deploy/local.rb index 381b0c6c..22e94486 100644 --- a/lib/yeoman/templates/lib/capistrano/deploy/local.rb +++ b/lib/yeoman/templates/lib/capistrano/deploy/local.rb @@ -1,4 +1,4 @@ -server 'local.<%= props.domain %>', +server 'local.<%- props.domain %>', roles: %w{db web}, user: fetch(:user), ssh_options: fetch(:ssh_options) diff --git a/lib/yeoman/templates/lib/capistrano/deploy/production.rb b/lib/yeoman/templates/lib/capistrano/deploy/production.rb index df047e7a..79a2e4bd 100644 --- a/lib/yeoman/templates/lib/capistrano/deploy/production.rb +++ b/lib/yeoman/templates/lib/capistrano/deploy/production.rb @@ -1,4 +1,4 @@ -server 'production.<%= props.domain %>', +server 'production.<%- props.domain %>', roles: %w{db web}, user: fetch(:user), ssh_options: fetch(:ssh_options) diff --git a/lib/yeoman/templates/lib/capistrano/deploy/staging.rb b/lib/yeoman/templates/lib/capistrano/deploy/staging.rb index cfb86674..ac520b04 100644 --- a/lib/yeoman/templates/lib/capistrano/deploy/staging.rb +++ b/lib/yeoman/templates/lib/capistrano/deploy/staging.rb @@ -1,4 +1,4 @@ -server 'staging.<%= props.domain %>', +server 'staging.<%- props.domain %>', roles: %w{db web}, user: fetch(:user), ssh_options: fetch(:ssh_options) diff --git a/lib/yeoman/templates/web/_htaccess b/lib/yeoman/templates/web/_htaccess index c50b858b..293e7dd6 100644 --- a/lib/yeoman/templates/web/_htaccess +++ b/lib/yeoman/templates/web/_htaccess @@ -3,13 +3,13 @@ RewriteEngine On RewriteBase / - # Force <%= props.www ? '' : 'non-' %>www for production - RewriteCond %{HTTP_HOST} ^<%= props.www ? '' : 'www\\.' %><%= props.domain.replace('.', '\\.') %>$ [NC] + # Force <%- props.www ? '' : 'non-' %>www for production + RewriteCond %{HTTP_HOST} ^<%- props.www ? '' : 'www\\.' %><%- props.domain.replace('.', '\\.') %>$ [NC] RewriteCond %{HTTP:X-Forwarded-Proto} ^http(s)| [NC] - RewriteRule ^(.*)$ http%1://<%= props.www ? 'www.' : '' %><%= props.domain %>/$1 [L,R=301,NC] + RewriteRule ^(.*)$ http%1://<%- props.www ? 'www.' : '' %><%- props.domain %>/$1 [L,R=301,NC] # Prevent spidering of non-canonical URLs, such as `[*.]staging.*` and `production.*`. - RewriteCond %{HTTP_HOST} (^local|staging|^production)\.<%= props.domain.replace('.', '\\.') %>$ [NC] + RewriteCond %{HTTP_HOST} (^local|staging|^production)\.<%- props.domain.replace('.', '\\.') %>$ [NC] RewriteRule ^robots.txt$ no_robots.txt [L] ## SECURITY @@ -41,13 +41,13 @@ # Rules to help reduce spam RewriteCond %{REQUEST_METHOD} POST RewriteCond %{REQUEST_URI} ^(.*)wp-comments-post\.php* - RewriteCond %{HTTP_REFERER} !^(.*)<%= props.domain %>.* + RewriteCond %{HTTP_REFERER} !^(.*)<%- props.domain %>.* RewriteCond %{HTTP_REFERER} !^http://jetpack\.wordpress\.com/jetpack-comment/ [OR] RewriteCond %{HTTP_USER_AGENT} ^$ RewriteRule ^(.*)$ - [F] # END Evolution WordPress -<%= htaccessFile %> +<%- htaccessFile %> <% if (!htaccessWpBlock) { %># BEGIN WordPress RewriteEngine On diff --git a/lib/yeoman/templates/web/robots.txt b/lib/yeoman/templates/web/robots.txt index 03275bf8..dd9e59f6 100644 --- a/lib/yeoman/templates/web/robots.txt +++ b/lib/yeoman/templates/web/robots.txt @@ -12,4 +12,4 @@ Disallow: /wp/trackback Disallow: /wp/xmlrpc.php Disallow: ?wptheme= -# Sitemap: http://<%= props.domain %>/sitemap.xml +# Sitemap: http://<%- props.domain %>/sitemap.xml diff --git a/lib/yeoman/templates/web/wp-config.php b/lib/yeoman/templates/web/wp-config.php index 9820f233..3441015f 100644 --- a/lib/yeoman/templates/web/wp-config.php +++ b/lib/yeoman/templates/web/wp-config.php @@ -2,7 +2,7 @@ /* Include Evolution to use with WordPress */ require_once(dirname(__FILE__) . '/../Evolution.php'); -<%= wpConfigFile +<%- wpConfigFile // Already started PHP .replace(' Date: Tue, 9 Feb 2016 23:29:49 -0800 Subject: [PATCH 05/66] Reordered methods within running contexts --- lib/yeoman/index.js | 1046 ++++++++++++++++++++++--------------------- 1 file changed, 527 insertions(+), 519 deletions(-) diff --git a/lib/yeoman/index.js b/lib/yeoman/index.js index eefba938..5835e0a9 100644 --- a/lib/yeoman/index.js +++ b/lib/yeoman/index.js @@ -12,537 +12,543 @@ var util = require('util'); var cp = require('child_process'); var WordpressGenerator = yeoman.Base.extend({ - init: function() { - this.pkg = this.fs.readJSON(path.join(__dirname, '../../package.json')); - this.prompts = []; - - this.option('dev', { - desc: 'Dev-mode for localized development of the generator', - defaults: false, - }); - - this.on('end', function() { - this.installDependencies({ - bower: true, - npm: false, - skipInstall: this.options['skip-install'], - skipMessage: true, - callback: function() { - this.log.write(); - this.log.ok('All done! Run ' + chalk.yellow('vagrant up') + ' to get started!'); - }.bind(this) + initializing: { + init: function() { + this.pkg = this.fs.readJSON(path.join(__dirname, '../../package.json')); + this.prompts = []; + + this.option('dev', { + desc: 'Dev-mode for localized development of the generator', + defaults: false, }); - }); - this.sourceRoot(path.join(__dirname, 'templates')); - }, + this.on('end', function() { + this.installDependencies({ + bower: true, + npm: false, + skipInstall: this.options['skip-install'], + skipMessage: true, + callback: function() { + this.log.write(); + this.log.ok('All done! Run ' + chalk.yellow('vagrant up') + ' to get started!'); + }.bind(this) + }); + }); - welcome: function() { - var message = this.fs.read(path.join(__dirname, 'welcome.txt')); + this.sourceRoot(path.join(__dirname, 'templates')); + }, - message = message.replace(/./g, function(match) { - return /\w/.test(match) ? chalk.yellow(match) : chalk.cyan(match); - }); + welcome: function() { + var message = this.fs.read(path.join(__dirname, 'welcome.txt')); - this.log.writeln(message); - }, + message = message.replace(/./g, function(match) { + return /\w/.test(match) ? chalk.yellow(match) : chalk.cyan(match); + }); - checkDeps: function() { - if(process.env.CI) { - return true; - } + this.log.writeln(message); + }, + + checkDeps: function() { + if(process.env.CI) { + return true; + } - var done = this.async(); - var deps = ['sshpass', 'bundler', 'ansible', 'bower', 'npm']; - var missing = []; - var exited = function(dependency, err) { - deps.pop(); + var done = this.async(); + var deps = ['sshpass', 'bundler', 'ansible', 'bower', 'npm']; + var missing = []; + var exited = function(dependency, err) { + deps.pop(); - if (err) { missing.push(dependency); } + if (err) { missing.push(dependency); } - if (!deps.length) { - if (missing.length) { - err = new Error('Missing prerequisites'); - this.log.error('Could not find dependencies:' + chalk.red("\n\t- "+missing.join("\n\t- ")) ); + if (!deps.length) { + if (missing.length) { + err = new Error('Missing prerequisites'); + this.log.error('Could not find dependencies:' + chalk.red("\n\t- "+missing.join("\n\t- ")) ); + } + done(err); } - done(err); } - } - this.log.info('Checking for installed prerequisites...'); - deps.forEach(function (dependency) { - this.emit('dependencyCheck'+dependency); - - this - .spawnCommand('which', [dependency], {cwd: this.env.cwd, env: process.env}) - .on('error', exited.bind(this, dependency)) - .on('exit', this.emit.bind(this, 'dependencyCheck'+dependency+':end')) - .on('exit', exited.bind(this, dependency)) - ; - }.bind(this)); + this.log.info('Checking for installed prerequisites...'); + deps.forEach(function (dependency) { + this.emit('dependencyCheck'+dependency); + + this + .spawnCommand('which', [dependency], {cwd: this.env.cwd, env: process.env}) + .on('error', exited.bind(this, dependency)) + .on('exit', this.emit.bind(this, 'dependencyCheck'+dependency+':end')) + .on('exit', exited.bind(this, dependency)) + ; + }.bind(this)); + }, }, - promptForPrivate: function() { - var bowerFile = path.join(this.env.cwd, 'bower.json'); - var choices = [ - { - name: 'Private', - value: true, - }, - { - name: 'Public', - value: false, - }, - ]; - var existing = function() { - try { - var bower = this.fs.readJSON(bowerFile); + prompting: { + promptForPrivate: function() { + var bowerFile = path.join(this.env.cwd, 'bower.json'); + var choices = [ + { + name: 'Private', + value: true, + }, + { + name: 'Public', + value: false, + }, + ]; + var existing = function() { + try { + var bower = this.fs.readJSON(bowerFile); - return !bower.private; - } catch(e) {}; - }.bind(this); + return !bower.private; + } catch(e) {}; + }.bind(this); - if(existing()) { - choices.reverse(); - } + if(existing()) { + choices.reverse(); + } - this.prompts.push({ - type: 'list', - name: 'private', - message: 'This repository is', - choices: choices, - }); - }, + this.prompts.push({ + type: 'list', + name: 'private', + message: 'This repository is', + choices: choices, + }); + }, - promptForSsl: function() { - var defaultSsl = true; + promptForSsl: function() { + var defaultSsl = true; - try { - var provisionYml = this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'provision.yml')); - defaultSsl = !!provisionYml.match(/^\s*-\s+pound/m); - } catch(e) {}; - - var choices = [ - { - name: 'Yes, HTTPS (SSL)', - value: true, - }, - { - name: 'No, HTTP-only', - value: false, - }, - ]; - - if(!defaultSsl) { - choices.reverse(); - } + try { + var provisionYml = this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'provision.yml')); + defaultSsl = !!provisionYml.match(/^\s*-\s+pound/m); + } catch(e) {}; + + var choices = [ + { + name: 'Yes, HTTPS (SSL)', + value: true, + }, + { + name: 'No, HTTP-only', + value: false, + }, + ]; - this.prompts.push({ - type: 'list', - name: 'ssl', - message: 'Will this site serve HTTPS (SSL) traffic?', - choices: choices - }); + if(!defaultSsl) { + choices.reverse(); + } - if(glob.sync('lib/ansible/files/ssl/*.pem').length) { this.prompts.push({ type: 'list', - name: 'sslOverwrite', - message: 'Overwrite existing SSL certificates?', - when: function (props) { - return props.ssl; - }, - choices: [ - { - name: 'Do not overwrite', - value: false, - }, - { - name: 'Overwrite', - value: true, - }, - ] + name: 'ssl', + message: 'Will this site serve HTTPS (SSL) traffic?', + choices: choices }); - } - }, - promptForSSHOverwrite: function() { - if(glob.sync('lib/ansible/files/ssh/id_rsa*').length) { - this.prompts.push({ - type: 'list', - name: 'sshOverwrite', - message: 'Overwrite existing SSH keys?', - choices: [ - { - name: 'Do not overwrite', - value: false, + if(glob.sync('lib/ansible/files/ssl/*.pem').length) { + this.prompts.push({ + type: 'list', + name: 'sslOverwrite', + message: 'Overwrite existing SSL certificates?', + when: function (props) { + return props.ssl; }, - { - name: 'Overwrite', - value: true, - }, - ] + choices: [ + { + name: 'Do not overwrite', + value: false, + }, + { + name: 'Overwrite', + value: true, + }, + ] + }); + } + }, + + promptForSSHOverwrite: function() { + if(glob.sync('lib/ansible/files/ssh/id_rsa*').length) { + this.prompts.push({ + type: 'list', + name: 'sshOverwrite', + message: 'Overwrite existing SSH keys?', + choices: [ + { + name: 'Do not overwrite', + value: false, + }, + { + name: 'Overwrite', + value: true, + }, + ] + }); + } + }, + + promptForName: function() { + var existing = function() { + try { + var bower = this.fs.readJSON(path.join(this.env.cwd, 'bower.json')); + + return bower.name; + } catch(e) {}; + }.bind(this); + + this.prompts.push({ + required: true, + type: 'text', + name: 'name', + message: 'Repository name (e.g. MySite)', + default: function() { + return existing() || path.basename(this.env.cwd); + }.bind(this) }); - } - }, + }, - promptForName: function() { - var existing = function() { - try { - var bower = this.fs.readJSON(path.join(this.env.cwd, 'bower.json')); + promptForDomain: function() { + var existing = function() { + try { + var match = this.fs.read(path.join(this.env.cwd, 'Vagrantfile')) + .match(/box.vm.hostname[ ]*=[ ]*"local.([^"]+)"/); - return bower.name; - } catch(e) {}; - }.bind(this); - - this.prompts.push({ - required: true, - type: 'text', - name: 'name', - message: 'Repository name (e.g. MySite)', - default: function() { - return existing() || path.basename(this.env.cwd); - }.bind(this) - }); - }, + return match[1]; + } catch(e) {}; + }.bind(this); - promptForDomain: function() { - var existing = function() { - try { - var match = this.fs.read(path.join(this.env.cwd, 'Vagrantfile')) - .match(/box.vm.hostname[ ]*=[ ]*"local.([^"]+)"/); + this.prompts.push({ + required: true, + type: 'text', + name: 'domain', + message: 'Domain name (e.g. mysite.com)', + default: function () { + return existing() || path.basename(this.env.cwd).toLowerCase(); + }.bind(this), + validate: function(input) { + if (/^[\w-]+\.\w+(?:\.\w{2,3})?$/.test(input)) { + return true; + } else if (!input) { + return "Domain is required"; + } - return match[1]; - } catch(e) {}; - }.bind(this); - - this.prompts.push({ - required: true, - type: 'text', - name: 'domain', - message: 'Domain name (e.g. mysite.com)', - default: function () { - return existing() || path.basename(this.env.cwd).toLowerCase(); - }.bind(this), - validate: function(input) { - if (/^[\w-]+\.\w+(?:\.\w{2,3})?$/.test(input)) { - return true; - } else if (!input) { - return "Domain is required"; + return chalk.yellow(input) + ' does not appear to be a domain'; } + }); + }, - return chalk.yellow(input) + ' does not appear to be a domain'; + promptForWww: function() { + var choices = [ + { + name: 'No, just the domain', + value: false, + }, + { + name: 'Yes, www is preferred', + value: true, + }, + ]; + var existing = function() { + try { + var match = this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'group_vars', 'all')) + .match(/www[ ]*:[ ]*(true)/i); + + return match[1]; + } catch(e) {}; + }.bind(this); + + if(existing()) { + choices.reverse(); } - }); - }, - promptForWww: function() { - var choices = [ - { - name: 'No, just the domain', - value: false, - }, - { - name: 'Yes, www is preferred', - value: true, - }, - ]; - var existing = function() { - try { - var match = this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'group_vars', 'all')) - .match(/www[ ]*:[ ]*(true)/i); + this.prompts.push({ + required: true, + type: 'list', + name: 'www', + message: 'Should this site enforce a www subdomain in production? (e.g. www.mysite.com)', + choices: choices + }); + }, - return match[1]; - } catch(e) {}; - }.bind(this); + promptForNewrelic: function() { + var existing = function() { + try { + var match = this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'group_vars', 'all')) + .match(/newrelic[ ]*:[ ]*(?:'|")?([^'"\s]+)/i); - if(existing()) { - choices.reverse(); - } + return match[1]; + } catch(e) {}; + }.bind(this); - this.prompts.push({ - required: true, - type: 'list', - name: 'www', - message: 'Should this site enforce a www subdomain in production? (e.g. www.mysite.com)', - choices: choices - }); - }, + this.prompts.push({ + required: true, + type: 'text', + name: 'newrelic', + message: 'New Relic license key (leave blank to disable)', + default: function () { + return existing() || ''; + }.bind(this) + }); + }, - promptForNewrelic: function() { - var existing = function() { + promptForRoles: function() { try { - var match = this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'group_vars', 'all')) - .match(/newrelic[ ]*:[ ]*(?:'|")?([^'"\s]+)/i); + var provisionYml = this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'provision.yml')); + + WordpressGenerator.roles.forEach(function (role, index) { + var regex = new RegExp('^\\s*-\\s+' + role.value.split(' ')[0], 'm'); - return match[1]; + if (!regex.exec(provisionYml)) { + WordpressGenerator.roles[index].checked = false; + } + }); } catch(e) {}; - }.bind(this); - - this.prompts.push({ - required: true, - type: 'text', - name: 'newrelic', - message: 'New Relic license key (leave blank to disable)', - default: function () { - return existing() || ''; - }.bind(this) - }); - }, - promptForRoles: function() { - try { - var provisionYml = this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'provision.yml')); + this.prompts.push({ + required: true, + type: 'checkbox', + name: 'roles', + message: 'Optional features', + choices: WordpressGenerator.roles, + }); + }, - WordpressGenerator.roles.forEach(function (role, index) { - var regex = new RegExp('^\\s*-\\s+' + role.value.split(' ')[0], 'm'); + promptForWordPress: function() { + var existing = function() { + try { + var file = this.fs.read(path.join(this.env.cwd, 'web', 'wp', 'wp-includes', 'version.php')); + var version = file.match(/\$wp_version\s=\s['"]([^'"]+)/); - if (!regex.exec(provisionYml)) { - WordpressGenerator.roles[index].checked = false; - } - }); - } catch(e) {}; - - this.prompts.push({ - required: true, - type: 'checkbox', - name: 'roles', - message: 'Optional features', - choices: WordpressGenerator.roles, - }); - }, + if (version.length) { + return version[1]; + } + } catch(e) {} + }.bind(this); - promptForWordPress: function() { - var existing = function() { - try { - var file = this.fs.read(path.join(this.env.cwd, 'web', 'wp', 'wp-includes', 'version.php')); - var version = file.match(/\$wp_version\s=\s['"]([^'"]+)/); + var done = this.async(); - if (version.length) { - return version[1]; - } - } catch(e) {} - }.bind(this); + WordpressGenerator.latest('wordpress', 'wordpress', function(err, tag) { + this.prompts.push({ + type: 'text', + name: 'wordpress', + message: 'WordPress version', + default: function() { + return existing() || tag || '4.2'; + } + }); + + done(); + }.bind(this)); + }, + + promptForTablePrefix: function() { + var existing = function() { + try { + var config = this.fs.read(path.join(this.env.cwd, 'web', 'wp-config.php')); + var prefix = config.match(/\$table_prefix\s*=\s*['"]([^'"]+)/); - var done = this.async(); + if (prefix.length) { + return prefix[1]; + } + } catch(e) {} + }.bind(this); - WordpressGenerator.latest('wordpress', 'wordpress', function(err, tag) { this.prompts.push({ type: 'text', - name: 'wordpress', - message: 'WordPress version', + name: 'prefix', + message: 'WordPress table prefix', default: function() { - return existing() || tag || '4.2'; + return existing() || 'wp_'; } }); + }, - done(); - }.bind(this)); - }, + promptForDatabase: function() { + var done = this.async(); + var existing = function(constant) { + try { + var config = this.fs.read(path.join(this.env.cwd, 'web', 'wp-config.php')); + var regex = new RegExp(constant + '[\'"],\\s*[\\w:(]*[\'"]([^\'"]+)'); + var matches = regex.exec(config); + + return matches && matches[1]; + } catch(e) {} + }.bind(this); + + crypto.randomBytes(12, function(err, buffer) { + this.prompts.push({ + type: 'text', + name: 'DB_NAME', + message: 'Database name', + default: function() { return existing('DB_NAME') || 'wordpress'; } + }); - promptForTablePrefix: function() { - var existing = function() { - try { - var config = this.fs.read(path.join(this.env.cwd, 'web', 'wp-config.php')); - var prefix = config.match(/\$table_prefix\s*=\s*['"]([^'"]+)/); + this.prompts.push({ + type: 'text', + name: 'DB_USER', + message: 'Database user', + default: function() { return existing('DB_USER') || 'wordpress'; } + }); - if (prefix.length) { - return prefix[1]; - } - } catch(e) {} - }.bind(this); - - this.prompts.push({ - type: 'text', - name: 'prefix', - message: 'WordPress table prefix', - default: function() { - return existing() || 'wp_'; - } - }); - }, + this.prompts.push({ + type: 'text', + name: 'DB_PASSWORD', + message: 'Database password', + default: function() { return existing('DB_PASSWORD') || buffer.toString('base64'); } + }); - promptForDatabase: function() { - var done = this.async(); - var existing = function(constant) { - try { - var config = this.fs.read(path.join(this.env.cwd, 'web', 'wp-config.php')); - var regex = new RegExp(constant + '[\'"],\\s*[\\w:(]*[\'"]([^\'"]+)'); - var matches = regex.exec(config); + this.prompts.push({ + type: 'text', + name: 'DB_HOST', + message: 'Database host', + default: function() { return existing('DB_HOST') || '127.0.0.1'; } + }); - return matches && matches[1]; - } catch(e) {} - }.bind(this); + done(); + }.bind(this)); + }, - crypto.randomBytes(12, function(err, buffer) { - this.prompts.push({ - type: 'text', - name: 'DB_NAME', - message: 'Database name', - default: function() { return existing('DB_NAME') || 'wordpress'; } - }); + promptForIp: function() { + // Private IP blocks + var blocks = [ + ['192.168.0.0', '192.168.255.255'], + ['172.16.0.0', '172.31.255.255'], + ['10.0.0.0', '10.255.255.255'] + ]; - this.prompts.push({ - type: 'text', - name: 'DB_USER', - message: 'Database user', - default: function() { return existing('DB_USER') || 'wordpress'; } - }); + // Long IP ranges + var ranges = blocks.map(function(block) { + return block.map(function(ip) { + var parts = ip.split('.'); - this.prompts.push({ - type: 'text', - name: 'DB_PASSWORD', - message: 'Database password', - default: function() { return existing('DB_PASSWORD') || buffer.toString('base64'); } + return parts[0] << 24 | parts[1] << 16 | parts[2] << 8 | parts[3] >>> 0; + }); }); - this.prompts.push({ - type: 'text', - name: 'DB_HOST', - message: 'Database host', - default: function() { return existing('DB_HOST') || '127.0.0.1'; } + // Randomize IP addresses + var ips = ranges.map(function(range) { + return Math.random() * (range[1] - range[0]) + range[0]; + }).map(function(ip) { + return [ + (ip & (0xff << 24)) >>> 24, + (ip & (0xff << 16)) >>> 16, + (ip & (0xff << 8)) >>> 8, + (ip & (0xff << 0)) >>> 0 + ].join('.'); }); - done(); - }.bind(this)); - }, - - promptForIp: function() { - // Private IP blocks - var blocks = [ - ['192.168.0.0', '192.168.255.255'], - ['172.16.0.0', '172.31.255.255'], - ['10.0.0.0', '10.255.255.255'] - ]; + try { + var vagrant = this.fs.read('Vagrantfile').match(/ip:\s['"]([\d\.]+)['"]/); - // Long IP ranges - var ranges = blocks.map(function(block) { - return block.map(function(ip) { - var parts = ip.split('.'); + if (vagrant.length) { + ips.unshift(vagrant[1]); + } + } catch(e) {} - return parts[0] << 24 | parts[1] << 16 | parts[2] << 8 | parts[3] >>> 0; + this.prompts.push({ + required: true, + type: 'list', + name: 'ip', + message: 'Vagrant IP', + pattern: /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/, + choices: ips }); - }); - - // Randomize IP addresses - var ips = ranges.map(function(range) { - return Math.random() * (range[1] - range[0]) + range[0]; - }).map(function(ip) { - return [ - (ip & (0xff << 24)) >>> 24, - (ip & (0xff << 16)) >>> 16, - (ip & (0xff << 8)) >>> 8, - (ip & (0xff << 0)) >>> 0 - ].join('.'); - }); - - try { - var vagrant = this.fs.read('Vagrantfile').match(/ip:\s['"]([\d\.]+)['"]/); - - if (vagrant.length) { - ips.unshift(vagrant[1]); - } - } catch(e) {} - - this.prompts.push({ - required: true, - type: 'list', - name: 'ip', - message: 'Vagrant IP', - pattern: /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/, - choices: ips - }); - }, + }, - ask: function() { - var done = this.async(); + ask: function() { + var done = this.async(); - this.prompt(this.prompts, function(props) { - this.props = props; + this.prompt(this.prompts, function(props) { + this.props = props; - done(); - }.bind(this)); + done(); + }.bind(this)); + }, }, - prepareReadme: function() { - try { - this.readmeFile = this.fs.read(path.join(this.env.cwd, 'README.md')); - this.readmeFile = this.readmeFile - .replace(/^(?:\[[^\]\r\n]+\]){1,2}(?:\([^\)\r\n]+\))?[\r\n]+=+[\r\n]+> Powered by \[(?:Genesis|Evolution)[^\r\n]+[\r\n]+/i, '') - .replace(/(?:^|[\r\n])\[[^\]\r\n]+\]:\s*http[^\r\n]+[\r\n]+\[(?:genesis|evolution)-wordpress\]:\s*http[^\r\n]+[\r\n]*$/i, '') - ; - } catch(e) { - this.readmeFile = ''; - } - }, + configuring: { + prepareReadme: function() { + try { + this.readmeFile = this.fs.read(path.join(this.env.cwd, 'README.md')); + this.readmeFile = this.readmeFile + .replace(/^(?:\[[^\]\r\n]+\]){1,2}(?:\([^\)\r\n]+\))?[\r\n]+=+[\r\n]+> Powered by \[(?:Genesis|Evolution)[^\r\n]+[\r\n]+/i, '') + .replace(/(?:^|[\r\n])\[[^\]\r\n]+\]:\s*http[^\r\n]+[\r\n]+\[(?:genesis|evolution)-wordpress\]:\s*http[^\r\n]+[\r\n]*$/i, '') + ; + } catch(e) { + this.readmeFile = ''; + } + }, - prepareHtaccess: function() { - try { - this.htaccessFile = this.fs.read(path.join(this.env.cwd, 'web', '.htaccess')); - this.htaccessFile = this.htaccessFile.replace(/# BEGIN Evolution WordPress(?:.|[\r\n]+)+?# END Evolution WordPress[\r\n]*/i, '').trim(); + prepareHtaccess: function() { + try { + this.htaccessFile = this.fs.read(path.join(this.env.cwd, 'web', '.htaccess')); + this.htaccessFile = this.htaccessFile.replace(/# BEGIN Evolution WordPress(?:.|[\r\n]+)+?# END Evolution WordPress[\r\n]*/i, '').trim(); - this.htaccessWpBlock = !!this.htaccessFile.match(/# BEGIN WordPress(?:.|[\r\n]+)+?# END WordPress[\r\n]*/i); - } catch(e) { - this.htaccessFile = ''; - this.htaccessWpBlock = false; - } - }, + this.htaccessWpBlock = !!this.htaccessFile.match(/# BEGIN WordPress(?:.|[\r\n]+)+?# END WordPress[\r\n]*/i); + } catch(e) { + this.htaccessFile = ''; + this.htaccessWpBlock = false; + } + }, - prepareGitignore: function () { - try { - this.gitignoreFile = this.fs.read(path.join(this.env.cwd, '.gitignore')); - this.gitignoreFile = this.gitignoreFile.match(/[\r\n]+# Generated file, don't edit above this line[\r\n]*([\S\s]*?)[\r\n]*$/i)[1]; - } catch(e) { - this.gitignoreFile = ''; - } - }, + prepareGitignore: function () { + try { + this.gitignoreFile = this.fs.read(path.join(this.env.cwd, '.gitignore')); + this.gitignoreFile = this.gitignoreFile.match(/[\r\n]+# Generated file, don't edit above this line[\r\n]*([\S\s]*?)[\r\n]*$/i)[1]; + } catch(e) { + this.gitignoreFile = ''; + } + }, - prepareRoles: function() { - this.props.roles = WordpressGenerator.roles.map(function(role) { - role.checked = !!~this.props.roles.indexOf(role.value); + prepareRoles: function() { + this.props.roles = WordpressGenerator.roles.map(function(role) { + role.checked = !!~this.props.roles.indexOf(role.value); - return role; - }.bind(this)); - }, + return role; + }.bind(this)); + }, - prepareSalts: function() { - var done = this.async(); + prepareSalts: function() { + var done = this.async(); - request('https://api.wordpress.org/secret-key/1.1/salt/', function(err, response, salts) { - if (err) { - throw err; - } + request('https://api.wordpress.org/secret-key/1.1/salt/', function(err, response, salts) { + if (err) { + throw err; + } - this.props.salts = salts; - done(); - }.bind(this)); - }, + this.props.salts = salts; + done(); + }.bind(this)); + }, - prepareSshKeys: function() { - if (typeof(this.props.sshOverwrite) !== 'undefined' && this.props.sshOverwrite !== true) { - this.log.skip('SSH keys exist, skipping keygen...'); - return false; - } + prepareSshKeys: function() { + if (typeof(this.props.sshOverwrite) !== 'undefined' && this.props.sshOverwrite !== true) { + this.log.skip('SSH keys exist, skipping keygen...'); + return false; + } - var done = this.async(); - var location = path.join(this.env.cwd, 'lib', 'ansible', 'files', 'ssh', 'id_rsa'); + var done = this.async(); + var location = path.join(this.env.cwd, 'lib', 'ansible', 'files', 'ssh', 'id_rsa'); - this.log.info('Creating SSH keys...'); + this.log.info('Creating SSH keys...'); - fs.mkdirsSync(path.dirname(location)); + fs.mkdirsSync(path.dirname(location)); - keygen({ - location: location, - comment: 'deploy@' + this.props.domain, - read: false - }, done); - }, + keygen({ + location: location, + comment: 'deploy@' + this.props.domain, + read: false + }, done); + }, - prepareTemplates: function() { - this.templates = glob.sync('**/*', { - cwd: this.sourceRoot(), - nodir: true, - }); + prepareTemplates: function() { + this.templates = glob.sync('**/*', { + cwd: this.sourceRoot(), + nodir: true, + }); + }, }, ready: function() { @@ -600,97 +606,99 @@ var WordpressGenerator = yeoman.Base.extend({ this.wpConfigFile = this.fs.read(path.join(this.env.cwd, 'web', 'wp', 'wp-config-sample.php')); }, - scaffold: function() { - this.log.info(chalk.green('Scaffolding...')); + writing: { + scaffold: function() { + this.log.info(chalk.green('Scaffolding...')); - this.templates.forEach(function(file) { - this.log.info('scaffolding', chalk.red(file)); - this.template(file, file.replace(/(^|\/)_/, '$1.')); - this.log.info('scaffolded', chalk.blue(file)); - }.bind(this)); + this.templates.forEach(function(file) { + this.log.info('scaffolding', chalk.red(file)); + this.template(file, file.replace(/(^|\/)_/, '$1.')); + this.log.info('scaffolded', chalk.blue(file)); + }.bind(this)); + }, }, - generateSslCerts: function() { - if (!this.props.ssl) { - return false; - } - - if (typeof(this.props.sslOverwrite) !== 'undefined' && this.props.sslOverwrite !== true) { - this.log.skip('SSL certificates exist, skipping creation...'); - return false; - } - - var done = this.async(); - var location = path.join(this.env.cwd, 'lib', 'ansible', 'files', 'ssl'); - var stages = ['local', 'staging', 'production']; - var exited = function (err) { - stages.pop(); - - if (err || !stages.length) { - done(err); + install: { + generateSslCerts: function() { + if (!this.props.ssl) { + return false; } - }; - this.log.info('Creating self-signed SSL certificate...'); - - fs.mkdirsSync(path.dirname(location)); - - stages.forEach(function (stage) { - this.emit('sslInstall'+stage); + if (typeof(this.props.sslOverwrite) !== 'undefined' && this.props.sslOverwrite !== true) { + this.log.skip('SSL certificates exist, skipping creation...'); + return false; + } - var cert = path.join(location, stage + '.' + this.props.domain + '.pem'); - var cfg = path.join(location, stage + '.cfg'); + var done = this.async(); + var location = path.join(this.env.cwd, 'lib', 'ansible', 'files', 'ssl'); + var stages = ['local', 'staging', 'production']; + var exited = function (err) { + stages.pop(); - this - .spawnCommand('openssl', [ - 'req', - '-x509', - '-nodes', - '-days', - '365', - '-newkey', - 'rsa:2048', - '-keyout', - cert, - '-out', - cert, - '-config', - cfg - ], { - cwd: this.env.cwd, - }) - .on('error', exited) - .on('exit', this.emit.bind(this, 'sslInstall'+stage+':end')) - .on('exit', function (err) { - if (err === 127) { - this.log.error('Could not generate SSL certificate for '+stage); - } + if (err || !stages.length) { + done(err); + } + }; + + this.log.info('Creating self-signed SSL certificate...'); + + fs.mkdirsSync(path.dirname(location)); + + stages.forEach(function (stage) { + this.emit('sslInstall'+stage); + + var cert = path.join(location, stage + '.' + this.props.domain + '.pem'); + var cfg = path.join(location, stage + '.cfg'); + + this + .spawnCommand('openssl', [ + 'req', + '-x509', + '-nodes', + '-days', + '365', + '-newkey', + 'rsa:2048', + '-keyout', + cert, + '-out', + cert, + '-config', + cfg + ], { + cwd: this.env.cwd, + }) + .on('error', exited) + .on('exit', this.emit.bind(this, 'sslInstall'+stage+':end')) + .on('exit', function (err) { + if (err === 127) { + this.log.error('Could not generate SSL certificate for '+stage); + } - exited(err); - }.bind(this)) - ; - }.bind(this)); - }, + exited(err); + }.bind(this)) + ; + }.bind(this)); + }, - symlinkBowerComponents: function() { - var bowerPath = path.join(this.env.cwd, 'web', 'bower_components'); + symlinkBowerComponents: function() { + var bowerPath = path.join(this.env.cwd, 'web', 'bower_components'); - if (fs.existsSync(bowerPath)) { - this.log.info(chalk.yellow('Removing `bower_components` symlink from `web`...')); + if (fs.existsSync(bowerPath)) { + this.log.info(chalk.yellow('Removing `bower_components` symlink from `web`...')); - fs.unlinkSync(bowerPath); - } + fs.unlinkSync(bowerPath); + } - this.log.info(chalk.green('Symlinking `bower_components` into `web`...')); + this.log.info(chalk.green('Symlinking `bower_components` into `web`...')); - fs.symlinkSync('../bower_components', bowerPath); - }, + fs.symlinkSync('../bower_components', bowerPath); + }, - fixPermissions: function() { - fs.chmodSync(path.join(this.env.cwd, 'lib', 'ansible', 'files', 'ssh', 'id_rsa'), '600'); - }, + fixPermissions: function() { + fs.chmodSync(path.join(this.env.cwd, 'lib', 'ansible', 'files', 'ssh', 'id_rsa'), '600'); + }, - install: { installGems: function() { var done = this.async(); var installer = 'bundle'; From 64dc947f901c1aa92866a192fa1fcc4098addbd4 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 16 Feb 2016 09:57:26 -0800 Subject: [PATCH 06/66] Ripping out bower, in favor of npm * SO MANY generator changes * dependency checking now supports regex-style version checks * on end, runs npm install rather than bower * rewrote existing prompt checks that relied on bower.json * for fetching wordpress, invokes postinstall rather than bootstrapping a bower.json * replaced hand-cobbled wp version checking with modified semver wrapper * Rewrote postinstall for npm * Removed templates for bower.json and .bowerrc * Added template for package.json * Added wp version to ansible group vars --- bin/postinstall | 91 +++++++++ lib/yeoman/bin/postinstall | 120 ----------- lib/yeoman/index.js | 186 +++++++----------- lib/yeoman/templates/_bowerrc | 5 - lib/yeoman/templates/bower.json | 9 - .../templates/lib/ansible/group_vars/all | 1 + lib/yeoman/templates/package.json | 13 ++ package.json | 24 ++- 8 files changed, 193 insertions(+), 256 deletions(-) create mode 100644 bin/postinstall delete mode 100755 lib/yeoman/bin/postinstall delete mode 100644 lib/yeoman/templates/_bowerrc delete mode 100644 lib/yeoman/templates/bower.json create mode 100644 lib/yeoman/templates/package.json diff --git a/bin/postinstall b/bin/postinstall new file mode 100644 index 00000000..8b27f236 --- /dev/null +++ b/bin/postinstall @@ -0,0 +1,91 @@ +#!/usr/bin/env node + +'use strict' + +var fs = require('fs-extra'); +var gh = require('github-download'); +var inWords = require('in-words').en; +var path = require('path'); +var util = require('util'); + +console.log('Evolution WordPress - npm `postinstall` Script\n'); + +// our point of reference on the filesystem +var siteDir = process.cwd(); + +// wordpress to install, by argument or groupvar +var wpVersion = process.argv[2]; +if (!wpVersion) { + var groupVars = fs.readFileSync(path.join(siteDir, 'lib/ansible/group_vars/all')).toString(); + var matched = groupVars.match(/^wp_version\s*:\s*['"]?([\d.]+)/m); + + if (!matched) { + throw new Error('Couldn\'t find wordpress version to install'); + } + + wpVersion = matched[1]; +} + +// ensure fresh install +var installDir = path.join(siteDir, 'web/wp'); +fs.removeSync(installDir); + +// install from github +console.log('Downloading wordpress `%s` to `%s`...', wpVersion, installDir); +gh({user: 'wordpress', repo: 'wordpress', ref: wpVersion}, installDir) + .on('error', function (err) { + throw err; + }) + .on('end', function () { + var toThemeDir = path.join(siteDir, 'web/wp-content/themes'); + var fromThemeDir = path.join(siteDir, 'web/wp/wp-content/themes'); + var latestTheme = null; + var themeExists = function (parents, name) { + var exists = false; + parents.forEach(function (directory) { + if (fs.existsSync(path.join(directory, name))) { + exists = true; + } + }); + return exists; + }; + + fs.ensureDirSync(toThemeDir); + + for (var testYear = new Date().getFullYear(); testYear > 2009; testYear--) { + var testName = inWords(testYear.toString().substr(0, 2)) + + inWords(testYear.toString().substr(2, 2)) + ; + + if (themeExists([toThemeDir, fromThemeDir], testName)) { + latestTheme = testName; + break; + } + else { + console.log('* No theme ' + testName); + } + } + + if (latestTheme === null) { + if (themeExists([fromThemeDir], 'default')) { + latestTheme = 'default'; + } + else { + throw new Error(util.format('Could not find WordPress core theme in `%s`', fromThemeDir)); + } + } + + if (themeExists([toThemeDir], latestTheme)) { + console.log('* Existing core theme ' + latestTheme); + } + else { + console.log('* Found theme ' + latestTheme); + + var fromTheme = path.join(fromThemeDir, latestTheme); + var toTheme = path.join(toThemeDir, latestTheme); + + console.log('* Moving theme `%s` to `%s`...', path.relative(siteDir, fromTheme), path.relative(siteDir, toTheme)); + fs.renameSync(fromTheme, toTheme); + } + }) +; diff --git a/lib/yeoman/bin/postinstall b/lib/yeoman/bin/postinstall deleted file mode 100755 index 2449977b..00000000 --- a/lib/yeoman/bin/postinstall +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/env node - -var fs = require('fs'); -var path = require('path'); -var util = require('util'); - -var cwd = process.cwd(); -var from = path.join(cwd, 'bower_components', 'wordpress'); -var to = path.join(cwd, 'web', 'wp'); - -console.log('Evolution WordPress - Bower `postinstall` Script\n'); - -// Ensure `bower_components/wordpress` has been installed -if (!fs.existsSync(from)) { - throw new Error(util.format('WordPress has not been installed to `%s`', from)); -} - -var toThemeDir = path.join(cwd, 'web', 'wp-content', 'themes'); - -if (!fs.existsSync(toThemeDir)) { - var parts = path.relative(cwd, toThemeDir).split(path.sep); - var toThemePartDir = cwd; - - while (parts.length) { - toThemePartDir = path.join(toThemePartDir, parts.shift()); - - console.info('Creating `%s`...', toThemePartDir); - fs.mkdirSync(toThemePartDir); - } -} - -var fromThemeDir = path.join(from, 'wp-content', 'themes'); -var latestTheme = null; -var themeExists = function (parents, name) { - var exists = false; - parents.forEach (function (directory) { - if (fs.existsSync( path.join(directory, name) )) { - exists = true; - } - }); - return exists; -}; -var words = function (num) { - var ones = ['','one','two','three','four','five','six','seven','eight','nine']; - var tens = ['','','twenty','thirty','forty','fifty','sixty','seventy','eighty','ninety']; - var teens = ['ten','eleven','twelve','thirteen','fourteen','fifteen','sixteen','seventeen','eighteen','nineteen']; - - if (num == 0) return 'zero'; - else if (num < 10) return ones[num]; - else if (num >= 10 && num < 20) return teens[ num - 10 ]; - else { - return tens[ Math.floor(num/10) ] + ones[ num % 10 ]; - } -} - -for (var testYear = new Date().getFullYear(); testYear > 2009; testYear--) { - var testName = words(testYear.toString().substr(0,2)) - + words(testYear.toString().substr(2,2)) - ; - - if (themeExists([toThemeDir,fromThemeDir], testName)) { - latestTheme = testName; - break; - } - else { - console.log('No theme ' + testName); - } -} - -if (latestTheme === null) { - if (themeExists([fromThemeDir], 'default')) { - latestTheme = 'default'; - } - else { - throw new Error(util.format('Could not find WordPress core theme in `%s`', fromThemeDir)); - } -} - -if (themeExists([toThemeDir], latestTheme)) { - console.log('Existing core theme ' + latestTheme); -} -else { - console.log('Found theme ' + latestTheme); - - var fromTheme = path.join(fromThemeDir, latestTheme); - var toTheme = path.join(toThemeDir, latestTheme); - - console.log('Moving theme `%s` to `%s`...', path.relative(cwd, fromTheme), path.relative(cwd, toTheme)); - fs.renameSync(fromTheme, toTheme); -} - -// Remove existing `web/wp` folder -if (fs.existsSync(to)) { - console.info('Removing `%s`...', to); - - var removeDir = function(dir) { - var nodes = fs.readdirSync(dir).map(function(node) { - return path.join(dir, node); - }); - - nodes.forEach(function(node) { - var stats = fs.lstatSync(node); - - if (stats.isDirectory()) { - removeDir(node); - } else { - fs.unlinkSync(node); - } - }); - - fs.rmdirSync(dir); - }; - - removeDir(to); -} - -console.info('Renaming `%s` to `%s`...', path.relative(cwd, from), path.relative(cwd, to)); -fs.renameSync(from, to); - -console.log('Done!'); diff --git a/lib/yeoman/index.js b/lib/yeoman/index.js index 5835e0a9..d211527e 100644 --- a/lib/yeoman/index.js +++ b/lib/yeoman/index.js @@ -4,12 +4,12 @@ var chalk = require('chalk'); var crypto = require('crypto'); var fs = require('fs-extra'); var glob = require('glob'); -var path = require('path'); var keygen = require('ssh-keygen'); +var path = require('path'); var request = require('request'); -var yeoman = require('yeoman-generator'); +var semver = require('semver'); var util = require('util'); -var cp = require('child_process'); +var yeoman = require('yeoman-generator'); var WordpressGenerator = yeoman.Base.extend({ initializing: { @@ -24,8 +24,8 @@ var WordpressGenerator = yeoman.Base.extend({ this.on('end', function() { this.installDependencies({ - bower: true, - npm: false, + bower: false, + npm: true, skipInstall: this.options['skip-install'], skipMessage: true, callback: function() { @@ -53,18 +53,39 @@ var WordpressGenerator = yeoman.Base.extend({ return true; } + // binaries, args, and callbacks for determining dependencies + var deps = [ + {bin: 'ansible', args: ['--version'], test: /ansible\s+2[.]/}, + {bin: 'bundler', args: ['--version']}, + {bin: 'npm', args: ['--version']}, + {bin: 'sshpass', args: ['-V']}, + ]; + var done = this.async(); - var deps = ['sshpass', 'bundler', 'ansible', 'bower', 'npm']; var missing = []; - var exited = function(dependency, err) { + var exited = function(dependency, proc, err) { deps.pop(); - if (err) { missing.push(dependency); } + // on error, note missing dep + if (err) { + missing.push('Could not find ' + dependency.bin); + } + // run test, when provided, against stdout/err + else { + if (dependency.hasOwnProperty('test')) { + var output = proc.stdout.read() + proc.stderr.read(); + output = output.replace(/\s+/g, ' '); + + if (!dependency.test.test(output)) { + missing.push('Insufficient version of ' + dependency.bin + ': ' + output); + } + } + } if (!deps.length) { if (missing.length) { - err = new Error('Missing prerequisites'); - this.log.error('Could not find dependencies:' + chalk.red("\n\t- "+missing.join("\n\t- ")) ); + err = new Error('Unsatisfied dependencies'); + this.log.error('Could not satisfy dependencies:' + chalk.red("\n\t- "+missing.join("\n\t- ")) ); } done(err); } @@ -72,13 +93,13 @@ var WordpressGenerator = yeoman.Base.extend({ this.log.info('Checking for installed prerequisites...'); deps.forEach(function (dependency) { - this.emit('dependencyCheck'+dependency); + this.emit('dependencyCheck'+dependency.bin); - this - .spawnCommand('which', [dependency], {cwd: this.env.cwd, env: process.env}) - .on('error', exited.bind(this, dependency)) - .on('exit', this.emit.bind(this, 'dependencyCheck'+dependency+':end')) - .on('exit', exited.bind(this, dependency)) + var proc = this.spawnCommand(dependency.bin, dependency.args, {cwd: this.env.cwd, env: process.env, stdio: 'pipe'}); + proc + .on('error', exited.bind(this, dependency, null)) + .on('exit', this.emit.bind(this, 'dependencyCheck'+dependency.bin+':end')) + .on('exit', exited.bind(this, dependency, proc)) ; }.bind(this)); }, @@ -86,7 +107,6 @@ var WordpressGenerator = yeoman.Base.extend({ prompting: { promptForPrivate: function() { - var bowerFile = path.join(this.env.cwd, 'bower.json'); var choices = [ { name: 'Private', @@ -99,9 +119,9 @@ var WordpressGenerator = yeoman.Base.extend({ ]; var existing = function() { try { - var bower = this.fs.readJSON(bowerFile); + var contents = this.fs.read(path.join(this.env.cwd, '.gitignore')); - return !bower.private; + return !contents.match(/lib\/ansible\/files\/ss(?:h|l)/); } catch(e) {}; }.bind(this); @@ -192,9 +212,10 @@ var WordpressGenerator = yeoman.Base.extend({ promptForName: function() { var existing = function() { try { - var bower = this.fs.readJSON(path.join(this.env.cwd, 'bower.json')); + var match = this.fs.read(path.join(this.env.cwd, 'lib/capistrano/deploy.rb')) + .match(/set :application,[ ]*["']([^"']+)/); - return bower.name; + return match[1]; } catch(e) {}; }.bind(this); @@ -564,7 +585,7 @@ var WordpressGenerator = yeoman.Base.extend({ this.log.info(chalk.green('Symlinking local Evolution WordPress as dependency...')); var srcpath = path.join(__dirname, '../../../wordpress'); - var dstpath = path.join(this.env.cwd, 'bower_components', 'evolution-wordpress'); + var dstpath = path.join(this.env.cwd, 'node_modules', 'evolution-wordpress'); this.log.info('symlinking from', chalk.red(srcpath), 'to', chalk.blue(dstpath)); @@ -572,50 +593,28 @@ var WordpressGenerator = yeoman.Base.extend({ fs.ensureSymlinkSync(srcpath, dstpath); }, - bootstrapBower: function() { - // bower files we'll be bootstrapping - var bowerJson = this.destinationPath('bower.json'); - var bowerRc = this.destinationPath('.bowerrc'); - - // minimum viable json for bower install + postinstall - var bowerBootstrap = { - "name": this.props.name, - "dependencies": { - "evolution-wordpress": (this.options.dev ? 'master' : '~' + this.pkg.version), - "wordpress": this.props.wordpress, - } - }; - - // backup existing bower files as necessary - var backupBowerJson = fs.existsSync(bowerJson) ? fs.readFileSync(bowerJson) : null; - var backupBowerRc = fs.existsSync(bowerRc) ? fs.readFileSync(bowerRc) : null; + postInstallWordpress: function () { + var done = this.async(); + var file = path.join(__dirname, '../../bin/postinstall'); - // bootstrap bower files - fs.writeFileSync(bowerJson, JSON.stringify(bowerBootstrap)); - fs.copySync(this.templatePath('_bowerrc'), bowerRc, {clobber:true}); - - // bower install from bootstrapped files - cp.spawnSync('bower', ['install'], {cwd: this.env.cwd, env: process.env, stdio: 'inherit'}); - - // restore existing bower files as necessary - backupBowerJson ? fs.writeFileSync(bowerJson, backupBowerJson) : fs.unlinkSync(bowerJson); - backupBowerRc ? fs.writeFileSync(bowerRc, backupBowerRc) : fs.unlinkSync(bowerRc); + this + .spawnCommand('node', [file, this.props.wordpress], {cwd: this.env.cwd, env: process.env}) + .on('error', done) + // .on('exit', this.emit.bind(this, installer + 'Install:end')) + .on('exit', done) + ; }, prepareWpConfig: function() { this.wpConfigFile = this.fs.read(path.join(this.env.cwd, 'web', 'wp', 'wp-config-sample.php')); }, - writing: { - scaffold: function() { - this.log.info(chalk.green('Scaffolding...')); + writing: function() { + this.log.info(chalk.green('Scaffolding...')); - this.templates.forEach(function(file) { - this.log.info('scaffolding', chalk.red(file)); - this.template(file, file.replace(/(^|\/)_/, '$1.')); - this.log.info('scaffolded', chalk.blue(file)); - }.bind(this)); - }, + this.templates.forEach(function(file) { + this.template(file, file.replace(/(^|\/)_/, '$1.')); + }.bind(this)); }, install: { @@ -681,20 +680,6 @@ var WordpressGenerator = yeoman.Base.extend({ }.bind(this)); }, - symlinkBowerComponents: function() { - var bowerPath = path.join(this.env.cwd, 'web', 'bower_components'); - - if (fs.existsSync(bowerPath)) { - this.log.info(chalk.yellow('Removing `bower_components` symlink from `web`...')); - - fs.unlinkSync(bowerPath); - } - - this.log.info(chalk.green('Symlinking `bower_components` into `web`...')); - - fs.symlinkSync('../bower_components', bowerPath); - }, - fixPermissions: function() { fs.chmodSync(path.join(this.env.cwd, 'lib', 'ansible', 'files', 'ssh', 'id_rsa'), '600'); }, @@ -720,19 +705,6 @@ var WordpressGenerator = yeoman.Base.extend({ }.bind(this)) ; }, - - installBower: function () { - var done = this.async(); - - this.log.info(chalk.green('Reinstalling bower...')); - - this.spawnCommand('bower', ['install']) - .on('error', function (err) { - this.log.error('Could not run', chalk.yellow('bower install')); - }.bind(this)) - .on('exit', done) - ; - }, }, }); @@ -783,42 +755,32 @@ WordpressGenerator.latest = function(username, repo, fn) { return fn(new Error(res.headers.status)); try { - var fuzzyver = /^\s*v?(\d+)\.(\d+)(?:\.(\d+))?\s*$/; var tags = JSON.parse(body) .map(function(item){ - return item.ref.split('/').pop(); + // fake two segment versions (X.Y) as semvers (X.Y.0) + var tag = item.ref.split('/').pop(); + if (/^\s*[v=]?\d+\.\d+\s*$/.test(tag)) { + return {raw: tag, sem: tag.trim()+'.0'}; + } + return {sem: tag}; + }) + // filter out anything that's not a valid semver + .filter(function (item) { + return semver.valid(item.sem); }) - .filter(RegExp.prototype.test.bind(fuzzyver)) + // sort semvers from high to low .sort(function (a, b) { - var ma = a.match(fuzzyver); - var mb = b.match(fuzzyver); - - if (ma[1] == mb[1]) { - if (ma[2] == mb[2]) { - ma[3] = ma[3] || '0'; - mb[3] = mb[3] || '0'; - if (ma[3] == mb[3]) - return 0; - else if (parseInt(ma[3]) > parseInt(mb[3])) - return 1; - else - return -1; - } - else if (parseInt(ma[2]) > parseInt(mb[2])) - return 1; - else - return -1; - } - else if (parseInt(ma[1]) > parseInt(mb[1])) - return 1; - else - return -1; + return semver.rcompare(a.sem, b.sem); }); } catch (e) { return fn(e); } - fn(null, tags.pop()); + if (!tags.length) { + return fn(new Error('Could not find latest matching version')); + } + + return fn(null, tags[0].hasOwnProperty('raw') ? tags[0].raw : tags[0].sem); }); }; diff --git a/lib/yeoman/templates/_bowerrc b/lib/yeoman/templates/_bowerrc deleted file mode 100644 index aa9fbc08..00000000 --- a/lib/yeoman/templates/_bowerrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "scripts": { - "postinstall": "./bower_components/evolution-wordpress/lib/yeoman/bin/postinstall" - } -} diff --git a/lib/yeoman/templates/bower.json b/lib/yeoman/templates/bower.json deleted file mode 100644 index e76dbfb2..00000000 --- a/lib/yeoman/templates/bower.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "private": <%- props.private ? 'true' : 'false' %>, - "name": "<%- props.name %>", - "version": "1.0.0", - "dependencies": { - "evolution-wordpress": "<%- options.dev ? 'master' : '~' + pkg.version %>", - "wordpress": "<%- props.wordpress %>" - } -} diff --git a/lib/yeoman/templates/lib/ansible/group_vars/all b/lib/yeoman/templates/lib/ansible/group_vars/all index 1cdac582..eed29ae9 100644 --- a/lib/yeoman/templates/lib/ansible/group_vars/all +++ b/lib/yeoman/templates/lib/ansible/group_vars/all @@ -1,5 +1,6 @@ --- evolve_version: <%- pkg.version %> +wp_version: <%- props.wordpress %> domain: <%- props.domain %> www: <%- props.www %> diff --git a/lib/yeoman/templates/package.json b/lib/yeoman/templates/package.json new file mode 100644 index 00000000..ddd5f27e --- /dev/null +++ b/lib/yeoman/templates/package.json @@ -0,0 +1,13 @@ +{ + "private": true, + "name": "<%- props.name %>", + "engines": { + "node": ">=4" + }, + "dependencies": { + "evolution-wordpress": "~v2.0.0-alpha" + }, + "scripts": { + "postinstall": "node node_modules/evolution-wordpress/bin/postinstall" + } +} diff --git a/package.json b/package.json index b6c54f4a..bddd13d6 100644 --- a/package.json +++ b/package.json @@ -1,25 +1,26 @@ { "private": true, "name": "evolution-wordpress", - "version": "1.3.5", + "version": "2.0.0-alpha.2", "description": "Libraries for a multi-staged WordPress workflow with Vagrant", "main": "lib/yeoman/index.js", "engines": { - "node": ">=4.0" + "node": ">=4" }, "dependencies": { + "adm-zip": "^0.4.7", "chalk": "^1.1.1", "fs-extra": "^0.26.4", - "request": "^2.67.0", - "ssh-keygen": "^0.2.1", + "github-download": "^0.4.0", + "glob": "^6.0.4", "in-words": "^0.2.0", - "yeoman-generator": "^0.22.4", - "yeoman-test": "^1.0.0", - "deasync": "^0.1.4", "inquirer": "^0.11.2", "replace": "^0.3.0", - "adm-zip": "^0.4.7", - "glob": "^6.0.4" + "request": "^2.67.0", + "semver": "^5.1.0", + "ssh-keygen": "^0.2.1", + "yeoman-generator": "^0.22.4", + "yeoman-test": "^1.0.0" }, "devDependencies": { "mocha": "^2.3.4", @@ -32,7 +33,10 @@ "type": "git", "url": "git://github.com/evolution/wordpress.git" }, - "author": "Eric Clemmons ", + "contributors": [ + "Evan Kaufman ", + "Eric Clemmons " + ], "license": "MIT", "bugs": { "url": "https://github.com/evolution/wordpress/issues" From 8885f2729792387b5f361bd97d8b7655a1541e1c Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 16 Feb 2016 18:35:25 -0800 Subject: [PATCH 07/66] Javascript cleanup, mainly strict mode and replacing deprecated fs.exists --- bin/import | 2 ++ bin/mock | 2 ++ bin/postinstall | 8 +++++--- bin/test | 2 ++ lib/yeoman/index.js | 3 +-- 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/bin/import b/bin/import index 21f3bd1e..810700aa 100755 --- a/bin/import +++ b/bin/import @@ -1,5 +1,7 @@ #!/usr/bin/env node +'use strict' + var fs = require('fs-extra'); var os = require('os'); var path = require('path'); diff --git a/bin/mock b/bin/mock index 58cb48cd..cf1dec78 100755 --- a/bin/mock +++ b/bin/mock @@ -1,5 +1,7 @@ #!/usr/bin/env node +'use strict' + var fs = require('fs-extra'); var exec = require('child_process').exec; var helpers = require('yeoman-test'); diff --git a/bin/postinstall b/bin/postinstall index 8b27f236..3f324576 100644 --- a/bin/postinstall +++ b/bin/postinstall @@ -43,9 +43,11 @@ gh({user: 'wordpress', repo: 'wordpress', ref: wpVersion}, installDir) var themeExists = function (parents, name) { var exists = false; parents.forEach(function (directory) { - if (fs.existsSync(path.join(directory, name))) { - exists = true; - } + try { + if (fs.statSync(path.join(directory, name)).isDirectory()) { + exists = true; + } + } catch (e) {}; }); return exists; }; diff --git a/bin/test b/bin/test index bba165a5..c29fb634 100755 --- a/bin/test +++ b/bin/test @@ -1,5 +1,7 @@ #!/usr/bin/env node +'use strict' + var glob = require('glob'); var Mocha = require('mocha'); var path = require('path'); diff --git a/lib/yeoman/index.js b/lib/yeoman/index.js index d211527e..5dd1db00 100644 --- a/lib/yeoman/index.js +++ b/lib/yeoman/index.js @@ -1,4 +1,4 @@ -'use strict'; +'use strict' var chalk = require('chalk'); var crypto = require('crypto'); @@ -600,7 +600,6 @@ var WordpressGenerator = yeoman.Base.extend({ this .spawnCommand('node', [file, this.props.wordpress], {cwd: this.env.cwd, env: process.env}) .on('error', done) - // .on('exit', this.emit.bind(this, installer + 'Install:end')) .on('exit', done) ; }, From 4ea6e0617be65d5f7b55ff1da379be579521f274 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 16 Feb 2016 18:36:24 -0800 Subject: [PATCH 08/66] Fixed flipped private/public logic, and added cleanup of old bower configs --- lib/yeoman/index.js | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/lib/yeoman/index.js b/lib/yeoman/index.js index 5dd1db00..d0982d3c 100644 --- a/lib/yeoman/index.js +++ b/lib/yeoman/index.js @@ -121,7 +121,7 @@ var WordpressGenerator = yeoman.Base.extend({ try { var contents = this.fs.read(path.join(this.env.cwd, '.gitignore')); - return !contents.match(/lib\/ansible\/files\/ss(?:h|l)/); + return contents.match(/lib\/ansible\/files\/ss(?:h|l)/); } catch(e) {}; }.bind(this); @@ -577,6 +577,41 @@ var WordpressGenerator = yeoman.Base.extend({ this.log.info(chalk.green('Here we go!')); }, + cleanupBower: function () { + // remove old bower postinstall + try { + var rcfile = path.join(this.env.cwd, '.bowerrc'); + var rcContents = this.fs.readJSON(rcfile); + if (rcContents.scripts.postinstall == './bower_components/evolution-wordpress/lib/yeoman/bin/postinstall') { + delete rcContents.scripts.postinstall; + fs.writeFileSync(rcfile, JSON.stringify(rcContents, null, 2)); + } + } catch (e) {}; + + // remove old bower deps + try { + var bowerfile = path.join(this.env.cwd, 'bower.json'); + var bowerContents = this.fs.readJSON(bowerfile); + var isChanged = false; + if (bowerContents.dependencies.hasOwnProperty('evolution-wordpress')) { + delete bowerContents.dependencies['evolution-wordpress']; + isChanged = true; + } + if (bowerContents.dependencies.hasOwnProperty('wordpress')) { + delete bowerContents.dependencies.wordpress; + isChanged = true; + } + if (isChanged) { + fs.writeFileSync(bowerfile, JSON.stringify(bowerContents, null, 2)); + } + } catch (e) {}; + + // remove old bower components + try { + fs.removeSync(path.join(this.env.cwd, 'bower_components/evolution-wordpress')); + } catch (e) {}; + }, + symlinkEvolutionWordPress: function() { if (!this.options.dev) { return false; From 7d06023ea7f8ff667260dceb2ca4da67c23d0cc7 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Wed, 17 Feb 2016 11:37:28 -0800 Subject: [PATCH 09/66] Removing bower, updating ansible and node, and all that entails * Updated travis yml * Removed bower * Updated to latest ansible (2+) * Updated ansible playbooks * Removed bower * Updated lookup plugin * Updated node install to 4.x * Removed apache 2.2 tasks (no longer needed for travis testing) * Updated capistrano * Updated README and other docs --- .travis.yml | 11 +- README.md | 16 ++- bin/postinstall | 132 ++++++++++-------- bower.json | 1 + docs/REF-generator-prompts.md | 4 +- docs/TUTORIAL-CLONE.md | 4 +- docs/TUTORIAL-UPGRADE.md | 4 +- lib/ansible/lookup_plugins/nested_dict.py | 83 ++++++++--- .../roles/apache-prefork/tasks/main.yml | 12 +- lib/ansible/roles/apache/tasks/main.yml | 16 +-- .../roles/apache/templates/virtualhost | 10 +- lib/ansible/roles/node/tasks/main.yml | 18 ++- lib/ansible/roles/node/vars/main.yml | 5 +- lib/yeoman/index.js | 2 +- lib/yeoman/templates/Capfile | 2 +- lib/yeoman/templates/ansible.cfg | 4 +- lib/yeoman/templates/bin/import | 4 +- .../templates/lib/ansible/provision.yml | 2 +- lib/yeoman/templates/lib/capistrano/deploy.rb | 4 +- package.json | 3 +- test/README.md | 13 +- 21 files changed, 193 insertions(+), 157 deletions(-) diff --git a/.travis.yml b/.travis.yml index a00b20b2..98cb1aee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,12 +8,11 @@ addons: - production.example.com - www.example.com before_install: - # node setup (for yeoman/bower) + # node setup (for yeoman) - nvm install 4.0 - node --version - npm --version - nvm --version - - npm install -g bower - npm install # ruby setup (for capistrano) - rvm use 1.9.3 @@ -23,7 +22,7 @@ before_install: - gem --version - bundle --version # python setup (for ansible) - - sudo pip install ansible==1.9.4 + - sudo pip install ansible - python --version - pip --version - ansible --version @@ -31,9 +30,9 @@ before_install: - $PWD/bin/mock - sudo mv $PWD/temp /vagrant - ln -s /vagrant $PWD/temp - # copy our local evolution-wordpress as bower dependency - - rm -rf /vagrant/bower_components/evolution-wordpress - - cp -RP $PWD /vagrant/bower_components/evolution-wordpress/ + # copy our local evolution-wordpress as npm dependency + - rm -rf /vagrant/node_modules/evolution-wordpress + - cp -RP $PWD /vagrant/node_modules/evolution-wordpress/ # invoke local provision (as default user with elevated permissions) - sudo cp $PWD/.travis.provision.bin $PWD/bin/provision - sudo chmod +x $PWD/bin/provision diff --git a/README.md b/README.md index 8f8a0c0a..6ab6f189 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,9 @@ Evolution lets you generate an entirely versioned, multi-environment Wordpress s ## Project Status -Evolution is _largely_ stable and usable at this point, but features are still being added and bugs being fixed. This documentation is also a work in progress. +Evolution is stable and usable in a production environment, but features are still being added and bugs being fixed. Suggestions, bug reports, and pull requests are welcome. + +This and [futher documentation](./docs/) are a constant work in progress. Contributions to documentation are _always_ welcome. ## Quick Start @@ -34,17 +36,17 @@ Evolution is intended for use in a POSIX environment, such as Linux or Mac OS. W You will need: -* [Vagrant](https://www.vagrantup.com/downloads.html) 1.1+ -* [Hostmanager for Vagrant](https://github.com/smdahlen/vagrant-hostmanager#installation) -* [npm](https://docs.npmjs.com/getting-started/installing-node) +* [Vagrant](https://www.vagrantup.com/downloads.html) 1.6+ +* ~~[Hostmanager for Vagrant](https://github.com/smdahlen/vagrant-hostmanager#installation)~~ +* [Node](https://nodejs.org/en/download/) 4.0+ * [Bundler](http://bundler.io/) -* [Ansible](http://docs.ansible.com/intro_installation.html) 1.6+ +* [Ansible](http://docs.ansible.com/intro_installation.html) 2.0+ * [sshpass](https://gist.github.com/arunoda/7790979) -You can then use npm to install Bower and the Yeoman generator: +You can then use npm to install the Yeoman generator: ``` -npm install -g bower yo generator-evolve +npm install -g yo generator-evolve ``` ### Common Workflows diff --git a/bin/postinstall b/bin/postinstall index 3f324576..1072e3da 100644 --- a/bin/postinstall +++ b/bin/postinstall @@ -2,11 +2,13 @@ 'use strict' -var fs = require('fs-extra'); -var gh = require('github-download'); -var inWords = require('in-words').en; -var path = require('path'); -var util = require('util'); +var AdmZip = require('adm-zip'); +var fs = require('fs-extra'); +var glob = require('glob'); +var inWords = require('in-words').en; +var path = require('path'); +var request = require('request'); +var util = require('util'); console.log('Evolution WordPress - npm `postinstall` Script\n'); @@ -32,62 +34,80 @@ fs.removeSync(installDir); // install from github console.log('Downloading wordpress `%s` to `%s`...', wpVersion, installDir); -gh({user: 'wordpress', repo: 'wordpress', ref: wpVersion}, installDir) - .on('error', function (err) { - throw err; - }) - .on('end', function () { - var toThemeDir = path.join(siteDir, 'web/wp-content/themes'); - var fromThemeDir = path.join(siteDir, 'web/wp/wp-content/themes'); - var latestTheme = null; - var themeExists = function (parents, name) { - var exists = false; - parents.forEach(function (directory) { - try { - if (fs.statSync(path.join(directory, name)).isDirectory()) { - exists = true; - } - } catch (e) {}; - }); - return exists; - }; - - fs.ensureDirSync(toThemeDir); - - for (var testYear = new Date().getFullYear(); testYear > 2009; testYear--) { - var testName = inWords(testYear.toString().substr(0, 2)) - + inWords(testYear.toString().substr(2, 2)) - ; - - if (themeExists([toThemeDir, fromThemeDir], testName)) { - latestTheme = testName; - break; - } - else { - console.log('* No theme ' + testName); - } +extract('wordpress', 'wordpress', wpVersion, installDir, function (err) { + if (err) throw err; + + var toThemeDir = path.join(siteDir, 'web/wp-content/themes'); + var fromThemeDir = path.join(siteDir, 'web/wp/wp-content/themes'); + var latestTheme = null; + var themeExists = function (parents, name) { + var exists = false; + parents.forEach(function (directory) { + try { + if (fs.statSync(path.join(directory, name)).isDirectory()) { + exists = true; + } + } catch (e) {}; + }); + return exists; + }; + + fs.ensureDirSync(toThemeDir); + + for (var testYear = new Date().getFullYear(); testYear > 2009; testYear--) { + var testName = inWords(testYear.toString().substr(0, 2)) + + inWords(testYear.toString().substr(2, 2)) + ; + + if (themeExists([toThemeDir, fromThemeDir], testName)) { + latestTheme = testName; + break; } - - if (latestTheme === null) { - if (themeExists([fromThemeDir], 'default')) { - latestTheme = 'default'; - } - else { - throw new Error(util.format('Could not find WordPress core theme in `%s`', fromThemeDir)); - } + else { + console.log('* No theme ' + testName); } + } - if (themeExists([toThemeDir], latestTheme)) { - console.log('* Existing core theme ' + latestTheme); + if (latestTheme === null) { + if (themeExists([fromThemeDir], 'default')) { + latestTheme = 'default'; } else { - console.log('* Found theme ' + latestTheme); + throw new Error(util.format('Could not find WordPress core theme in `%s`', fromThemeDir)); + } + } - var fromTheme = path.join(fromThemeDir, latestTheme); - var toTheme = path.join(toThemeDir, latestTheme); + if (themeExists([toThemeDir], latestTheme)) { + console.log('* Existing core theme ' + latestTheme); + } + else { + console.log('* Found theme ' + latestTheme); - console.log('* Moving theme `%s` to `%s`...', path.relative(siteDir, fromTheme), path.relative(siteDir, toTheme)); - fs.renameSync(fromTheme, toTheme); - } + var fromTheme = path.join(fromThemeDir, latestTheme); + var toTheme = path.join(toThemeDir, latestTheme); + + console.log('* Moving theme `%s` to `%s`...', path.relative(siteDir, fromTheme), path.relative(siteDir, toTheme)); + fs.renameSync(fromTheme, toTheme); + } +}); + +function extract(username, repo, version, directory, cb) { + var zipName = path.join(siteDir, [username, repo, version].join('-')); + request({ + url: 'https://github.com/' + username + '/' + repo + '/archive/' + version + '.zip', + headers: { 'user-agent': 'https://github.com/request/request' } }) -; + .on('error', function (err) { cb(err); }) + .pipe(fs.createWriteStream(zipName+'.zip')) + .on('close', function () { + var zip = new AdmZip(zipName+'.zip'); + zip.extractAllTo(zipName, true); + fs.unlinkSync(zipName+'.zip'); + + var entryDir = glob.sync(path.join(zipName, '*/'))[0]; + fs.copySync(entryDir, directory, {clobber:true}); + fs.removeSync(zipName); + + cb(); + }); +}; diff --git a/bower.json b/bower.json index 28ef973f..ee928244 100644 --- a/bower.json +++ b/bower.json @@ -3,6 +3,7 @@ "version": "1.3.5", "homepage": "https://github.com/evolution/wordpress", "authors": [ + "Evan Kaufman " "Eric Clemmons " ], "description": "Libraries for a multi-staged WordPress workflow with Vagrant", diff --git a/docs/REF-generator-prompts.md b/docs/REF-generator-prompts.md index ded696df..f2c17395 100644 --- a/docs/REF-generator-prompts.md +++ b/docs/REF-generator-prompts.md @@ -21,7 +21,7 @@ If you opt for a *public* project, the generator will configure your [`.gitignor **This is ideal if you plan to open-source your site on a free public repository (we recommend Github for this).** -If you opt for *private*, it will configure your [`bower.json`](https://github.com/bower/bower.json-spec#private) to prevent publication through Bower, but *your keys and certificates will be versioned*. +If you opt for *private*, it will configure your [`package.json`](https://docs.npmjs.com/files/package.json) to prevent publication through npm, but *your keys and certificates will be versioned*. **In this case, you should use a paid [private repository on Github](https://help.github.com/articles/making-a-public-repository-private/), or a free [private repository on Gitlab](http://doc.gitlab.com/ce/gitlab-basics/create-project.html).** @@ -89,7 +89,7 @@ This installs some command line utilities that are useful for monitoring process ### Wordpress version -This determines which version of Wordpress will be fetched from Github and installed as a bower dependency. **The default for this is the latest tagged version.** +This determines which version of Wordpress will be fetched and installed from Github. **The default for this is the latest tagged version.** ### Wordpress table prefix diff --git a/docs/TUTORIAL-CLONE.md b/docs/TUTORIAL-CLONE.md index 18460094..539cd95c 100644 --- a/docs/TUTORIAL-CLONE.md +++ b/docs/TUTORIAL-CLONE.md @@ -17,9 +17,9 @@ If you don't already have the site running locally (eg, someone else set it up), During generation of a new or existing site, the generator does this step for you. Manually installing dependencies is still quite simple, however: bundle install - bower install + npm install -Note that bower will automatically pull in non-breaking changes from the latest patch version of Evolution (eg, `v1.0.15` to `v1.0.16`). +Note that npm's postinstall will automatically pull in non-breaking changes from the latest patch version of Evolution (eg, `v1.0.15` to `v1.0.16`). ### Bringing up local diff --git a/docs/TUTORIAL-UPGRADE.md b/docs/TUTORIAL-UPGRADE.md index f305fe73..95035d24 100644 --- a/docs/TUTORIAL-UPGRADE.md +++ b/docs/TUTORIAL-UPGRADE.md @@ -2,7 +2,7 @@ ### Why regenerate your site? -Non-breaking changes to Evolution are added across **patch versions** (eg, `v1.0.15` to `v1.0.16`), and are automatically pulled down on `bower install` or deployment to a remote stage. +Non-breaking changes to Evolution are added across **patch versions** (eg, `v1.0.15` to `v1.0.16`), and are automatically pulled down on `npm install` or deployment to a remote stage. Breaking changes are added across **minor versions** (eg `v1.0.16` to `v1.1.0`), and require running the generator against your existing site codebase @@ -15,7 +15,7 @@ Bring up your local copy of the site, or [follow the guide](./TUTORIAL-ClONE.md# ### Regenerating -Now, run the generator and follow [the prompts](./REF-generator-prompts.md) -- it should pre-select the choices for which it was already configured, and install bundler and bower dependencies automatically: +Now, run the generator and follow [the prompts](./REF-generator-prompts.md) -- it should pre-select the choices for which it was already configured, and install bundler and npm dependencies automatically: yo evolve wordpress git status diff --git a/lib/ansible/lookup_plugins/nested_dict.py b/lib/ansible/lookup_plugins/nested_dict.py index 8f15eae7..af9d30ff 100644 --- a/lib/ansible/lookup_plugins/nested_dict.py +++ b/lib/ansible/lookup_plugins/nested_dict.py @@ -1,4 +1,4 @@ -# (c) 2014, Evan Kaufman +# (c) 2016, Evan Kaufman # # This file is part of Ansible # @@ -14,34 +14,71 @@ # # You should have received a copy of the GNU General Public License # along with Ansible. If not, see . +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type -from ansible.utils import safe_eval -import ansible.utils as utils -import ansible.errors as errors +from ansible.errors import AnsibleError +from ansible.plugins.lookup import LookupBase -def flatten_nested_hash_to_list(terms, result=None, stack=None, level=None): - result = [] if result is None else result - stack = {} if stack is None else stack - level = 0 if level is None else level +""" +Lookup plugin to flatten nested dictionaries for linear iteration +================================================================= - for key, val in terms.iteritems(): - stack['key_%s' % level] = key - if type(val) is dict: - flatten_nested_hash_to_list(terms=val, result=result, stack=stack.copy(), level=level+1) - else: - stack['value'] = val - result.append(stack.copy()) - return result +For example, a collection of holidays nested by year, month, and day: -class LookupModule(object): + { + '2016': { + 'January': { + '1': 'New Years Day', + '19': 'Martin Luther King Day', + }, + 'February': { + '14': 'Valentines Day', + '16': 'Presidents Day', + }, + ... + }, + ... + } - def __init__(self, basedir=None, **kwargs): - self.basedir = basedir +Would be flattened into an array of shallow dicts, with each original key denoted by its nesting level: - def run(self, terms, inject=None, **kwargs): - terms = utils.listify_lookup_plugin_terms(terms, self.basedir, inject) + [ + { 'key_0': '2016', 'key_1': 'January', 'key_2': '1', 'value': 'New Years Day' }, + { 'key_0': '2016', 'key_1': 'January', 'key_2': '19', 'value': 'Martin Luther King Day' }, + { 'key_0': '2016', 'key_1': 'February', 'key_2': '14', 'value': 'Valentines Day' }, + { 'key_0': '2016', 'key_1': 'February', 'key_2': '16', 'value': 'Presidents Day' }, + ... + ] +The nested keys and value of each are then exposed to an iterative task: + + - name: "Remind us what holidays are this month" + debug: + msg: "Remember {{value}} on {{key_1}} {{'%02d'|format(key_2)}} in the year {{key_0}}" + when: key_1 == current_month + with_nested_dict: holidays_by_year_month_day + +""" +class LookupModule(LookupBase): + + @staticmethod + def _flatten_nested_hash_to_list(terms, result=None, stack=None, level=None): + result = [] if result is None else result + stack = {} if stack is None else stack + level = 0 if level is None else level + + for key, val in terms.iteritems(): + stack['key_%s' % level] = key + if type(val) is dict: + LookupModule._flatten_nested_hash_to_list(terms=val, result=result, stack=stack.copy(), level=level+1) + else: + stack['value'] = val + result.append(stack.copy()) + return result + + def run(self, terms, variables=None, **kwargs): if not isinstance(terms, dict): - raise errors.AnsibleError("with_nested_dict expects a dict") + raise AnsibleError("with_nested_dict expects a dict") - return flatten_nested_hash_to_list(terms) + return self._flatten_nested_hash_to_list(terms) diff --git a/lib/ansible/roles/apache-prefork/tasks/main.yml b/lib/ansible/roles/apache-prefork/tasks/main.yml index 0e061711..f7dcc845 100644 --- a/lib/ansible/roles/apache-prefork/tasks/main.yml +++ b/lib/ansible/roles/apache-prefork/tasks/main.yml @@ -1,15 +1,5 @@ --- -- name: Create custom apache prefork config (2.2) - template: src=prefork.conf dest=/etc/apache2/prefork.conf mode=0644 - when: apache_version.stdout == '2.2' - sudo: yes - -- name: Remove default apache prefork config (2.2) - replace: dest=/etc/apache2/apache2.conf backup=yes regexp='^(?:#[^\n]+\n)*[^<]+?<\/IfModule>' replace='Include prefork.conf' validate='/usr/sbin/apache2ctl -f %s -t' - when: apache_version.stdout == '2.2' - sudo: yes - -- name: Override apache prefork module config (2.4) +- name: Override apache prefork module config template: src=prefork.conf dest=/etc/apache2/mods-available/mpm_prefork.conf backup=yes mode=0644 when: apache_version.stdout == '2.4' sudo: yes diff --git a/lib/ansible/roles/apache/tasks/main.yml b/lib/ansible/roles/apache/tasks/main.yml index 03458246..2a6b877c 100644 --- a/lib/ansible/roles/apache/tasks/main.yml +++ b/lib/ansible/roles/apache/tasks/main.yml @@ -26,29 +26,17 @@ copy: src=logrotate-apache dest=/etc/logrotate.d/apache2 owner=root group=root mode=644 sudo: yes -- name: Configure Apache canonical server name (2.2) - template: src=canonical dest=/etc/apache2/conf.d/canonical-servername.conf mode=0644 - notify: restart apache - when: apache_version.stdout == '2.2' - sudo: true - -- name: Configure Apache canonical server name (2.4) +- name: Configure Apache canonical server name template: src=canonical dest=/etc/apache2/conf-available/canonical-servername.conf mode=0644 when: apache_version.stdout == '2.4' sudo: true -- name: Enable canonical config (2.4) +- name: Enable canonical config command: a2enconf canonical-servername notify: restart apache when: apache_version.stdout == '2.4' sudo: yes -- name: Ensure Apache `NameVirtualHost` is 80 (2.2) - lineinfile: regexp='^NameVirtualHost' line='NameVirtualHost *:80' dest=/etc/apache2/ports.conf backup=yes - notify: restart apache - when: apache_version.stdout == '2.2' - sudo: yes - - name: Ensure Apache `Listen` is 80 lineinfile: regexp='^Listen' line='Listen 80' dest=/etc/apache2/ports.conf backup=yes notify: restart apache diff --git a/lib/ansible/roles/apache/templates/virtualhost b/lib/ansible/roles/apache/templates/virtualhost index bc5033f8..1bc89a9d 100644 --- a/lib/ansible/roles/apache/templates/virtualhost +++ b/lib/ansible/roles/apache/templates/virtualhost @@ -44,10 +44,7 @@ {% endif %} Options FollowSymLinks AllowOverride All -{% if apache_version.stdout == '2.2' %} - Order allow,deny - Allow from all -{% elif apache_version.stdout == '2.4' %} +{% if apache_version.stdout == '2.4' %} Require all granted {% endif %} @@ -140,7 +137,6 @@ # Compress all output labeled with one of the following media types. - {% if apache_version.stdout != '2.2' %} # # (!) For Apache versions below version 2.3.7 you don't need to @@ -150,7 +146,6 @@ # # https://httpd.apache.org/docs/current/mod/mod_filter.html#addoutputfilterbytype - {% endif %} AddOutputFilterByType DEFLATE "application/atom+xml" \ "application/javascript" \ "application/json" \ @@ -183,8 +178,7 @@ "text/x-component" \ "text/x-cross-domain-policy" \ "text/xml" - {% if apache_version.stdout != '2.2' %} - {% endif %} + # Map the following filename extensions to the specified # encoding type in order to make Apache serve the file types diff --git a/lib/ansible/roles/node/tasks/main.yml b/lib/ansible/roles/node/tasks/main.yml index 9a92770b..9dafecca 100644 --- a/lib/ansible/roles/node/tasks/main.yml +++ b/lib/ansible/roles/node/tasks/main.yml @@ -1,13 +1,17 @@ --- -- name: Add Node apt-repository - apt_repository: repo='ppa:chris-lea/node.js' state=present update_cache=yes +- name: Remove old node repository if necessary + apt_repository: repo='ppa:chris-lea/node.js' state=absent sudo: yes -- name: Install node - apt: pkg=nodejs state=present +- name: Add Nodesource apt key + apt_key: url=https://deb.nodesource.com/gpgkey/nodesource.gpg.key state=present + sudo: yes + +- name: Add Nodesource 4.x repos + apt_repository: repo={{item}} state=present update_cache=yes + with_items: node_repos sudo: yes -- name: Install global node modules - command: npm install -g {{ item }} - with_items: node_modules +- name: Install node + apt: pkg=nodejs state=present sudo: yes diff --git a/lib/ansible/roles/node/vars/main.yml b/lib/ansible/roles/node/vars/main.yml index 0e5ab3f3..d4d686ad 100644 --- a/lib/ansible/roles/node/vars/main.yml +++ b/lib/ansible/roles/node/vars/main.yml @@ -1,3 +1,4 @@ --- -node_modules: - - bower +node_repos: + - deb https://deb.nodesource.com/node_4.x trusty main + - deb-src https://deb.nodesource.com/node_4.x trusty main diff --git a/lib/yeoman/index.js b/lib/yeoman/index.js index d0982d3c..91a38ecd 100644 --- a/lib/yeoman/index.js +++ b/lib/yeoman/index.js @@ -622,7 +622,7 @@ var WordpressGenerator = yeoman.Base.extend({ var srcpath = path.join(__dirname, '../../../wordpress'); var dstpath = path.join(this.env.cwd, 'node_modules', 'evolution-wordpress'); - this.log.info('symlinking from', chalk.red(srcpath), 'to', chalk.blue(dstpath)); + this.log.info(chalk.red(srcpath), '~>', chalk.blue(dstpath)); fs.mkdirsSync(path.dirname(dstpath)); fs.ensureSymlinkSync(srcpath, dstpath); diff --git a/lib/yeoman/templates/Capfile b/lib/yeoman/templates/Capfile index 4cb85371..2ed26e15 100644 --- a/lib/yeoman/templates/Capfile +++ b/lib/yeoman/templates/Capfile @@ -25,7 +25,7 @@ require 'capistrano/deploy' # require 'capistrano/rails/migrations' # Load Evolution WordPress' tasks -load File.expand_path(File.dirname(__FILE__)) + '/bower_components/evolution-wordpress/lib/capistrano/bootstrap.rake' +load File.expand_path(File.dirname(__FILE__)) + '/node_modules/evolution-wordpress/lib/capistrano/bootstrap.rake' # Loads custom tasks from `lib/capistrano/tasks' if you have any defined. Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r } diff --git a/lib/yeoman/templates/ansible.cfg b/lib/yeoman/templates/ansible.cfg index f7f4326b..eccdc36c 100644 --- a/lib/yeoman/templates/ansible.cfg +++ b/lib/yeoman/templates/ansible.cfg @@ -3,5 +3,5 @@ hostfile = ./lib/ansible/hosts private_key_file = ./lib/ansible/files/ssh/id_rsa remote_user = deploy -roles_path = ./bower_components/evolution-wordpress/lib/ansible/roles -lookup_plugins = ./bower_components/evolution-wordpress/lib/ansible/lookup_plugins +roles_path = ./node_modules/evolution-wordpress/lib/ansible/roles +lookup_plugins = ./node_modules/evolution-wordpress/lib/ansible/lookup_plugins diff --git a/lib/yeoman/templates/bin/import b/lib/yeoman/templates/bin/import index 799e2c7e..46af5abc 100644 --- a/lib/yeoman/templates/bin/import +++ b/lib/yeoman/templates/bin/import @@ -1,12 +1,10 @@ #!/usr/bin/env bash -IMPORTER_PATH="$( dirname "$0" )/../bower_components/evolution-wordpress" +IMPORTER_PATH="$( dirname "$0" )/../node_modules/evolution-wordpress" IMPORTER_SCRIPT="$IMPORTER_PATH/bin/import" chmod +x "$IMPORTER_SCRIPT" -(cd "$IMPORTER_PATH"; npm install) - VAGRANT_STATUS=$(vagrant status) if [[ "$VAGRANT_STATUS" == *"running ("* ]]; then diff --git a/lib/yeoman/templates/lib/ansible/provision.yml b/lib/yeoman/templates/lib/ansible/provision.yml index 0bb77db6..0f2f5ee2 100644 --- a/lib/yeoman/templates/lib/ansible/provision.yml +++ b/lib/yeoman/templates/lib/ansible/provision.yml @@ -10,7 +10,7 @@ - apache # (Required) Web server (Soon: Nginx) - mysql # (Required) Database server (Soon: Maria) - php # (Required) PHP 5.3 - - node # (Required) Tools for deployment (e.g. `bower`) + - node # (Required) Tools for deployment + dependencies (e.g. `npm`) - wp-cli # (Required) CLI for managing WordPress # Optional Features diff --git a/lib/yeoman/templates/lib/capistrano/deploy.rb b/lib/yeoman/templates/lib/capistrano/deploy.rb index d7725796..e2b4439b 100644 --- a/lib/yeoman/templates/lib/capistrano/deploy.rb +++ b/lib/yeoman/templates/lib/capistrano/deploy.rb @@ -18,9 +18,9 @@ set :www, <%- props.www ? 'true' : 'false' %> namespace :deploy do - after :updated, :bower_install do + after :updated, :npm_install do on roles(:web) do - execute "cd #{release_path} && bower install --config.interactive=false" + execute "cd #{release_path} && npm install --production" end end after :finished, :launch_browser do diff --git a/package.json b/package.json index bddd13d6..8cb4546a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "evolution-wordpress", - "version": "2.0.0-alpha.2", + "version": "2.0.0-alpha.3", "description": "Libraries for a multi-staged WordPress workflow with Vagrant", "main": "lib/yeoman/index.js", "engines": { @@ -11,7 +11,6 @@ "adm-zip": "^0.4.7", "chalk": "^1.1.1", "fs-extra": "^0.26.4", - "github-download": "^0.4.0", "glob": "^6.0.4", "in-words": "^0.2.0", "inquirer": "^0.11.2", diff --git a/test/README.md b/test/README.md index 58ede28c..3b7750d0 100644 --- a/test/README.md +++ b/test/README.md @@ -3,15 +3,16 @@ ### Dependencies - Composer (`$ curl -sS https://getcomposer.org/installer | php`) -- Node + NPM +- Node + npm dev dependencies - Vagrant ### Setup -Install Composer dependencies: +Install Composer and dependencies: ```shell -$ php composer.phar install --dev +$ curl -sS https://getcomposer.org/installer | php +$ php composer.phar install ``` Install NPM dependencies: @@ -51,5 +52,7 @@ $ npm test ``` Tests will be ran against the new entries in `/etc/hosts`: - -> http://local.example.com and http://example.com/ +- local.example.com +- production.example.com +- www.example.com +- example.com From 442c03b0b6f3e29f8a57939d88041d730f9680c8 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Wed, 17 Feb 2016 17:33:48 -0800 Subject: [PATCH 10/66] Misc cleanup --- bower.json | 2 +- lib/ansible/roles/node/tasks/main.yml | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/bower.json b/bower.json index ee928244..2b716d4e 100644 --- a/bower.json +++ b/bower.json @@ -3,7 +3,7 @@ "version": "1.3.5", "homepage": "https://github.com/evolution/wordpress", "authors": [ - "Evan Kaufman " + "Evan Kaufman ", "Eric Clemmons " ], "description": "Libraries for a multi-staged WordPress workflow with Vagrant", diff --git a/lib/ansible/roles/node/tasks/main.yml b/lib/ansible/roles/node/tasks/main.yml index 9dafecca..7ddd1295 100644 --- a/lib/ansible/roles/node/tasks/main.yml +++ b/lib/ansible/roles/node/tasks/main.yml @@ -3,6 +3,11 @@ apt_repository: repo='ppa:chris-lea/node.js' state=absent sudo: yes +- name: Ensure removal of old node source lists + shell: rm -f /etc/apt/sources.list.d/chris-lea-node_js-*.list + ignore_errors: true + sudo: yes + - name: Add Nodesource apt key apt_key: url=https://deb.nodesource.com/gpgkey/nodesource.gpg.key state=present sudo: yes From edadec30076dc8f3d37d934dc6a1de7b128e4cf3 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Thu, 18 Feb 2016 18:01:02 -0800 Subject: [PATCH 11/66] Tweaking travis yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 98cb1aee..11861609 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,6 +32,7 @@ before_install: - ln -s /vagrant $PWD/temp # copy our local evolution-wordpress as npm dependency - rm -rf /vagrant/node_modules/evolution-wordpress + - mkdir -p /vagrant/node_modules/evolution-wordpress - cp -RP $PWD /vagrant/node_modules/evolution-wordpress/ # invoke local provision (as default user with elevated permissions) - sudo cp $PWD/.travis.provision.bin $PWD/bin/provision From db742a9fc7abd8835da660254fb7cfd2a26d0a96 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Thu, 18 Feb 2016 19:10:41 -0800 Subject: [PATCH 12/66] Troubleshooting travis build errors --- .travis.yml | 3 ++- bin/mock | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 11861609..c6407ece 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,9 +31,10 @@ before_install: - sudo mv $PWD/temp /vagrant - ln -s /vagrant $PWD/temp # copy our local evolution-wordpress as npm dependency - - rm -rf /vagrant/node_modules/evolution-wordpress - mkdir -p /vagrant/node_modules/evolution-wordpress - cp -RP $PWD /vagrant/node_modules/evolution-wordpress/ + - ls -al /vagrant/node_modules/evolution-wordpress/ + - ls -al /vagrant/node_modules/evolution-wordpress/lib/ansible/roles # invoke local provision (as default user with elevated permissions) - sudo cp $PWD/.travis.provision.bin $PWD/bin/provision - sudo chmod +x $PWD/bin/provision diff --git a/bin/mock b/bin/mock index 5bf0c01f..45808f07 100755 --- a/bin/mock +++ b/bin/mock @@ -120,7 +120,7 @@ helpers.testDirectory(outputDir, function(err) { if (isCI) { Array.prototype.push.apply(wrap, [ 'git commit -m "Something to deploy"', - 'git remote add origin ' + outputDir + '/.git', + 'git remote add origin /vagrant/.git', ]); } From 778ecf2e1c74e7a0132203d93a2cf6134b7442b3 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Thu, 18 Feb 2016 19:16:28 -0800 Subject: [PATCH 13/66] Try recursive copy without trailing slashes --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c6407ece..d961f261 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,8 +31,8 @@ before_install: - sudo mv $PWD/temp /vagrant - ln -s /vagrant $PWD/temp # copy our local evolution-wordpress as npm dependency - - mkdir -p /vagrant/node_modules/evolution-wordpress - - cp -RP $PWD /vagrant/node_modules/evolution-wordpress/ + - mkdir -p /vagrant/node_modules + - cp -RP $PWD /vagrant/node_modules/evolution-wordpress - ls -al /vagrant/node_modules/evolution-wordpress/ - ls -al /vagrant/node_modules/evolution-wordpress/lib/ansible/roles # invoke local provision (as default user with elevated permissions) From 5b7d6eca366746ba42d803783bcf0504e320b20c Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Fri, 19 Feb 2016 15:43:36 -0800 Subject: [PATCH 14/66] Normalize line endings in fetched wp-config --- .travis.yml | 2 -- lib/yeoman/templates/web/wp-config.php | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index d961f261..72ea9125 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,8 +33,6 @@ before_install: # copy our local evolution-wordpress as npm dependency - mkdir -p /vagrant/node_modules - cp -RP $PWD /vagrant/node_modules/evolution-wordpress - - ls -al /vagrant/node_modules/evolution-wordpress/ - - ls -al /vagrant/node_modules/evolution-wordpress/lib/ansible/roles # invoke local provision (as default user with elevated permissions) - sudo cp $PWD/.travis.provision.bin $PWD/bin/provision - sudo chmod +x $PWD/bin/provision diff --git a/lib/yeoman/templates/web/wp-config.php b/lib/yeoman/templates/web/wp-config.php index 3441015f..f0bb5c05 100644 --- a/lib/yeoman/templates/web/wp-config.php +++ b/lib/yeoman/templates/web/wp-config.php @@ -46,6 +46,9 @@ // Replace ABSPATH .replace(/define\('ABSPATH'.+\);/, "define('ABSPATH', dirname(__FILE__) . '/wp/');") + + // Normalize line endings + .replace(/(?:\r\n|\r|\n)/g, "\n") %> /** Output rewriting for production.DOMAIN or *.staging.DOMAIN **/ Evolution::rewriteUrls(); From f8120f5af3e67569a2a28e1cb8ce2136270663ec Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sun, 13 Mar 2016 16:42:31 -0700 Subject: [PATCH 15/66] Warn but allow outdated dep versions --- lib/yeoman/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/yeoman/index.js b/lib/yeoman/index.js index a15c6ce3..4cd26632 100644 --- a/lib/yeoman/index.js +++ b/lib/yeoman/index.js @@ -76,8 +76,9 @@ var WordpressGenerator = yeoman.Base.extend({ var output = proc.stdout.read() + proc.stderr.read(); output = output.replace(/\s+/g, ' '); + // warn (rather than bail) on dep with insufficient version if (!dependency.test.test(output)) { - missing.push('Insufficient version of ' + dependency.bin + ': ' + output); + this.log.skip('Warning: found ' + chalk.green(dependency.bin) + ', with insufficient version: ' + chalk.red(output)); } } } From 982229903684612b1b6d16d955f5349ee2314c79 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sat, 29 Oct 2016 11:41:25 -0700 Subject: [PATCH 16/66] Updated ruby setup for CI --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 72ea9125..c3dc7094 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,7 @@ before_install: - nvm --version - npm install # ruby setup (for capistrano) + - rvm install 1.9.3 - rvm use 1.9.3 - gem install bundler - ruby --version From 65c4e7042d6afe8a9d498bbcb03e7befc97d6555 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sun, 30 Oct 2016 17:16:02 -0700 Subject: [PATCH 17/66] Several updates to get this branch working: * updated postinstall to drop admzip and use yauzl instead * updated generator, fixed: * npm install (needed to be under `install` block) * prompting updated (to use promise-style from yeoman 1.8+) * updated package.json for publishing (local testing for now with sinopia) Also worth noting that this will require an updated node to 4.x and yeoman to 1.8 --- bin/postinstall | 62 +++++++++++++++++++++++++++++++++++++-------- lib/yeoman/index.js | 21 +++++---------- package.json | 4 +-- 3 files changed, 60 insertions(+), 27 deletions(-) diff --git a/bin/postinstall b/bin/postinstall index 1072e3da..539b63d3 100644 --- a/bin/postinstall +++ b/bin/postinstall @@ -2,13 +2,13 @@ 'use strict' -var AdmZip = require('adm-zip'); var fs = require('fs-extra'); var glob = require('glob'); var inWords = require('in-words').en; var path = require('path'); var request = require('request'); var util = require('util'); +var yauzl = require('yauzl'); console.log('Evolution WordPress - npm `postinstall` Script\n'); @@ -100,14 +100,56 @@ function extract(username, repo, version, directory, cb) { .on('error', function (err) { cb(err); }) .pipe(fs.createWriteStream(zipName+'.zip')) .on('close', function () { - var zip = new AdmZip(zipName+'.zip'); - zip.extractAllTo(zipName, true); - fs.unlinkSync(zipName+'.zip'); - - var entryDir = glob.sync(path.join(zipName, '*/'))[0]; - fs.copySync(entryDir, directory, {clobber:true}); - fs.removeSync(zipName); - - cb(); + console.log('Extracting '+zipName+'.zip to', zipName); + var extractedFiles = 0, + extractedDirs = 0; + fs.emptyDirSync(zipName); + yauzl.open(zipName+'.zip', {lazyEntries: true}, function(err, zipfile) { + if (err) throw err; + + zipfile.readEntry(); + zipfile.on('entry', function(entry) { + var extractedName = path.join(zipName, entry.fileName); + process.stdout.write("Extracted " + extractedFiles + " files and " + extractedDirs + " directories\r"); + + if (/\/$/.test(entry.fileName)) { + // create directories (names ending in '/') + extractedDirs++; + fs.mkdirs(extractedName, function(err) { + if (err) throw err; + zipfile.readEntry(); + }); + } else { + // write files via streams + extractedFiles++; + zipfile.openReadStream(entry, function(err, readStream) { + if (err) throw err; + // ensure parent directory exists + fs.mkdirs(path.dirname(extractedName), function(err) { + if (err) throw err; + readStream.pipe(fs.createWriteStream(extractedName)); + readStream.on('end', function() { + zipfile.readEntry(); + }); + }); + }); + } + }); + zipfile.on('end', function (err) { + if (err) console.log('Zip ended with an error:', err); + console.log('Extracted zip!'); + // gjve it a second to finish writing the last entry... + setTimeout(function() { + fs.unlinkSync(zipName+'.zip'); + + var entryDir = glob.sync(path.join(zipName, '*/'))[0]; + fs.copySync(entryDir, directory, {clobber:true}); + fs.removeSync(zipName); + + cb(); + }, 1000); + }) + + }); }); }; diff --git a/lib/yeoman/index.js b/lib/yeoman/index.js index 4cd26632..a8c83b05 100644 --- a/lib/yeoman/index.js +++ b/lib/yeoman/index.js @@ -23,16 +23,8 @@ var WordpressGenerator = yeoman.Base.extend({ }); this.on('end', function() { - this.installDependencies({ - bower: false, - npm: true, - skipInstall: this.options['skip-install'], - skipMessage: true, - callback: function() { - this.log.write(); - this.log.ok('All done! Run ' + chalk.yellow('vagrant up') + ' to get started!'); - }.bind(this) - }); + this.log.write(); + this.log.ok('All done! Run ' + chalk.yellow('vagrant up') + ' to get started!'); }); this.sourceRoot(path.join(__dirname, 'templates')); @@ -501,12 +493,8 @@ var WordpressGenerator = yeoman.Base.extend({ }, ask: function() { - var done = this.async(); - - this.prompt(this.prompts, function(props) { + return this.prompt(this.prompts).then(function(props) { this.props = props; - - done(); }.bind(this)); }, }, @@ -761,6 +749,9 @@ var WordpressGenerator = yeoman.Base.extend({ }.bind(this)) ; }, + installNpm: function() { + this.npmInstall(); + } }, }); diff --git a/package.json b/package.json index d1bf7a71..6b616c88 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "private": true, + "private": false, "name": "evolution-wordpress", - "version": "1.4.5", + "version": "v2.0.0-alpha", "description": "Libraries for a multi-staged WordPress workflow with Vagrant", "main": "lib/yeoman/index.js", "engines": { From 73df0f43b05fe0df21c339ead5689a3383a71544 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sun, 30 Oct 2016 22:30:45 -0700 Subject: [PATCH 18/66] Fetch node apt key on control machine Fixes another SNI failure when the remote has an older python --- lib/ansible/roles/node/tasks/main.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/ansible/roles/node/tasks/main.yml b/lib/ansible/roles/node/tasks/main.yml index 7ddd1295..944b8faa 100644 --- a/lib/ansible/roles/node/tasks/main.yml +++ b/lib/ansible/roles/node/tasks/main.yml @@ -8,8 +8,11 @@ ignore_errors: true sudo: yes +- name: Fetch Nodesource apt key (from control) + local_action: get_url dest=/tmp/ns4x.gpg.key url=https://deb.nodesource.com/gpgkey/nodesource.gpg.key force=yes + - name: Add Nodesource apt key - apt_key: url=https://deb.nodesource.com/gpgkey/nodesource.gpg.key state=present + apt_key: data="{{ lookup('file', '/tmp/ns4x.gpg.key') }}" state=present sudo: yes - name: Add Nodesource 4.x repos From 1078c288e5c216e55578c02ee551f7c91ce4cea9 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sat, 12 Nov 2016 12:06:59 -0800 Subject: [PATCH 19/66] Replacing zombie with nightmare, working around electron dns/hostfile issues tl;dr: nightmare uses electron which makes direct dns queries instead of respecting hostfile entries. So the tests using it need to have a resolved ip ahead of time to make requests with a Host header --- bin/test | 19 ++++++++++++------- package.json | 2 +- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/bin/test b/bin/test index c29fb634..bb64f73d 100755 --- a/bin/test +++ b/bin/test @@ -2,6 +2,7 @@ 'use strict' +var dns = require('dns'); var glob = require('glob'); var Mocha = require('mocha'); var path = require('path'); @@ -16,10 +17,14 @@ glob.sync('**/*.js', { mocha.addFile(path.join(testDir, file)); }); -mocha - .bail(true) - .reporter('spec') - .timeout(0) - .ui('bdd') - .run(process.exit) -; +dns.lookup('example.com', function(err, address, family) { + process.env.EXAMPLE_COM = address; + + mocha + .bail(true) + .reporter('spec') + .timeout(0) + .ui('bdd') + .run(process.exit) + ; +}); diff --git a/package.json b/package.json index 6b616c88..00ab1dd1 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ }, "devDependencies": { "mocha": "^3.1.2", - "zombie": "^4.2.1" + "nightmare": "^2.8.1" }, "scripts": { "test": "./bin/test" From 09b0e126a8dbaa438dcb409fd108694475e15b09 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sat, 12 Nov 2016 18:01:40 -0800 Subject: [PATCH 20/66] Updated tests (more or less working locally!) * added nightmare wrapper, to ensure clean browser cache * updated zombie code to work with nightmare instead * updated provision/deploy calls to use spawn instead of exec, to avoid maxBuffer overflows --- lib/node/nightmare.js | 26 ++++++ test/functional/00-firewall.js | 19 ++-- test/functional/01-install.js | 60 ++++++------ test/functional/03-evolve.provision.js | 26 +++++- test/functional/04-deploy.js | 26 +++++- test/functional/05-evolve.db.up.js | 28 ++++-- test/functional/06-evolve.files.up.js | 20 ++-- test/functional/07-sni.js | 11 +-- test/functional/08-robots.js | 35 +++++-- test/functional/varnish/cache.js | 121 ++++++++++++++----------- test/functional/wordpress/redirect.js | 19 ++-- 11 files changed, 240 insertions(+), 151 deletions(-) create mode 100644 lib/node/nightmare.js diff --git a/lib/node/nightmare.js b/lib/node/nightmare.js new file mode 100644 index 00000000..fe434248 --- /dev/null +++ b/lib/node/nightmare.js @@ -0,0 +1,26 @@ +var fs = require('fs-extra'); +var Nightmare = require('nightmare'); + +module.exports = function (options) { + // define a data path and ensure an empty dir + var dataPath = `${process.cwd()}/.browserData/`; + fs.emptyDirSync(dataPath); + + // specify empty user data path, unless otherwise specified + if (!options) { + options = { + paths: { + userData: dataPath + } + }; + } else if (!options.hasOwnProperty('paths')) { + options.paths = { + userData: dataPath + }; + } else if (!options.paths.hasOwnProperty('userData')) { + options.paths.userData = dataPath; + } + + // instantiate and return with given options + return new Nightmare(options); +} diff --git a/test/functional/00-firewall.js b/test/functional/00-firewall.js index a57a38f5..2f029813 100644 --- a/test/functional/00-firewall.js +++ b/test/functional/00-firewall.js @@ -12,31 +12,28 @@ describe('firewall ports', function(done) { port_cmd = 'sudo iptables -L -n | grep :%d'; done(); } else { - exec('php -r "echo gethostbyname(\'local.example.com.\');"', { - cwd: process.cwd() + '/temp' - }, function(err, stdout, stderr) { - assert.ifError(err); - port_cmd = 'nc -z -w 1 ' + stdout.trim() + ' %d'; - done(); - }); + port_cmd = `nc -z -w 1 ${process.env.EXAMPLE_COM} %d`; + done(); } }); describe('should be closed', function(done) { it('mysql', function(done) { - exec(util.format(port_cmd, '3306'), { + var formatted_cmd = util.format(port_cmd, '3306'); + exec(formatted_cmd, { cwd: process.cwd() + '/temp' }, function(err, stdout, stderr) { - assert.ok(err); + assert.ok(err, formatted_cmd); done(); }); }); it('apache backend', function(done) { - exec(util.format(port_cmd, '8080'), { + var formatted_cmd = util.format(port_cmd, '8080'); + exec(formatted_cmd, { cwd: process.cwd() + '/temp' }, function(err, stdout, stderr) { - assert.ok(err); + assert.ok(err, formatted_cmd); done(); }); }); diff --git a/test/functional/01-install.js b/test/functional/01-install.js index 2391b352..8e4b79d9 100644 --- a/test/functional/01-install.js +++ b/test/functional/01-install.js @@ -1,7 +1,7 @@ 'use strict'; var assert = require('assert'); -var Browser = require('zombie'); +var Browser = require('../../lib/node/nightmare'); var fs = require('fs'); var path = require('path'); @@ -10,34 +10,24 @@ describe('Mock site', function() { var browser = new Browser(); browser - .visit('http://local.example.com/wp/wp-admin/install.php') - .then(function() { - if (browser.button('Continue')) { - browser.select('language', 'English (United States)'); - - return browser.pressButton('Continue'); - } - }) - .then(function() { - if (browser.button('Hide')) { - return browser.pressButton('Hide'); - } - }) - .then(function() { - if (browser.button('Install WordPress')) { - browser - .fill('Site Title', 'Evolution WordPress Test') - .fill('Username', 'test') - .fill('admin_password', 'test') - .fill('admin_password2', 'test') - .fill('admin_email', 'test@example.com') - .uncheck('blog_public') - ; - - return browser.pressButton('Install WordPress'); - } - }) - .then(done, done) + .goto(`http://${process.env.EXAMPLE_COM}/wp/wp-admin/install.php`, {'Host':'local.example.com'}) + .select('select[name=language]', '') + .click('form[action$="?step=1"] input[type=submit]') + .wait('form[action$="?step=2"]') + .click('button.wp-hide-pw') + .type('input[name=weblog_title]', 'Evolution WordPress Test') + .type('input[name=user_name]', 'test') + .type('input[name=admin_password]', 'test') + .check('input[name=pw_weak]') + .type('input[name=admin_email]', 'test@example.com') + .uncheck('input[name=blog_public]') + .click('form[action$="?step=2"] input[type=submit]') + .wait('a[href$="/wp-login.php"]') + .end() + .then(done) + .catch(function(error) { + done(); + }); ; }); @@ -45,11 +35,15 @@ describe('Mock site', function() { var browser = new Browser(); browser - .visit('http://local.example.com/wp/wp-admin/install.php') - .then(function() { - assert.equal('Log In', browser.text('a.button')); + .goto(`http://${process.env.EXAMPLE_COM}/wp/wp-admin/install.php`, {'Host':'local.example.com'}) + .evaluate(function() { + return document.querySelector('a[href$="/wp-login.php"]').href + }) + .end() + .then(function(link) { + assert.equal(link, 'http://local.example.com/wp/wp-login.php'); + done(); }) - .then(done, done) ; }) }); diff --git a/test/functional/03-evolve.provision.js b/test/functional/03-evolve.provision.js index 32aeb28c..052ec89e 100644 --- a/test/functional/03-evolve.provision.js +++ b/test/functional/03-evolve.provision.js @@ -1,15 +1,31 @@ 'use strict'; var assert = require('assert'); -var exec = require('child_process').exec; +var spawn = require('child_process').spawn; describe('cap production evolve:provision', function(done) { it('should not fail', function(done) { - exec('bundle exec cap production evolve:provision', { + var output = ''; + + var child = spawn('bundle', ['exec', 'cap', 'production', 'evolve:provision'], { cwd: process.cwd() + '/temp' - }, function(err, stdout, stderr) { - assert.ifError(err); - done(); + }); + + child.stdout.on('data', function (data) { + output += data.toString(); + }); + + child.stderr.on('data', function (data) { + output += data.toString(); + }); + + child.on('exit', function (code) { + if (code) { + console.error(output); + done(new Error('exited with ' + code)); + } else { + done(); + } }); }); }); diff --git a/test/functional/04-deploy.js b/test/functional/04-deploy.js index c6126296..7f7982f9 100644 --- a/test/functional/04-deploy.js +++ b/test/functional/04-deploy.js @@ -1,15 +1,31 @@ 'use strict'; var assert = require('assert'); -var exec = require('child_process').exec; +var spawn = require('child_process').spawn; describe('cap production deploy', function(done) { it('should not fail', function(done) { - exec('bundle exec cap production deploy', { + var output = ''; + + var child = spawn('bundle', ['exec', 'cap', 'production', 'deploy'], { cwd: process.cwd() + '/temp' - }, function(err, stdout, stderr) { - assert.ifError(err); - done(); + }); + + child.stdout.on('data', function (data) { + output += data.toString(); + }); + + child.stderr.on('data', function (data) { + output += data.toString(); + }); + + child.on('exit', function (code) { + if (code) { + console.error(output); + done(new Error('exited with ' + code)); + } else { + done(); + } }); }); }); diff --git a/test/functional/05-evolve.db.up.js b/test/functional/05-evolve.db.up.js index 4cd443ee..53f24e36 100644 --- a/test/functional/05-evolve.db.up.js +++ b/test/functional/05-evolve.db.up.js @@ -1,7 +1,7 @@ 'use strict'; var assert = require('assert'); -var Browser = require('zombie'); +var Browser = require('../../lib/node/nightmare'); var exec = require('child_process').exec; describe('cap production evolve:up:db', function(done) { @@ -18,11 +18,18 @@ describe('cap production evolve:up:db', function(done) { var browser = new Browser(); browser - .visit('http://example.com/') - .then(null, function() { - assert.equal('Evolution WordPress Test – Just another WordPress site', browser.text('title')); + .goto(`http://${process.env.EXAMPLE_COM}/`, {'Host':'example.com'}) + .evaluate(function() { + return document.title; + }) + .end() + .then(function(title) { + assert.equal(title, 'Evolution WordPress Test – Just another WordPress site'); + done() + }) + .catch(function(error) { + done(error) }) - .then(done, done) ; }); @@ -30,13 +37,14 @@ describe('cap production evolve:up:db', function(done) { var browser = new Browser(); browser - .visit('http://example.com/wp/wp-admin/install.php') - .then(function() { - assert(false, 'expected 403, got ' + browser.statusCode) + .goto(`http://${process.env.EXAMPLE_COM}/wp/wp-admin/install.php`, {'Host':'example.com'}) + .end() + .then(function(result) { + assert.equal(result.code, 403) + done() }) .catch(function(error) { - assert.equal(browser.statusCode, 403, "should be forbidden\n" + error); - done() + done(error) }) ; }); diff --git a/test/functional/06-evolve.files.up.js b/test/functional/06-evolve.files.up.js index 3d92648c..bef1df65 100644 --- a/test/functional/06-evolve.files.up.js +++ b/test/functional/06-evolve.files.up.js @@ -1,12 +1,12 @@ 'use strict'; var assert = require('assert'); -var Browser = require('zombie'); +var Browser = require('../../lib/node/nightmare'); var fs = require('fs'); var exec = require('child_process').exec; var testFile = '/vagrant/web/wp-content/uploads/uploads_sync_test.jpg'; -var testUrl = 'http://production.example.com/wp-content/uploads/uploads_sync_test.jpg'; +var testUrl = `http://${process.env.EXAMPLE_COM}/wp-content/uploads/uploads_sync_test.jpg`; describe('cap production evolve:files:up', function(done) { it('may need to remove uploads', function(done) { @@ -31,12 +31,14 @@ describe('cap production evolve:files:up', function(done) { var browser = new Browser(); browser - .visit(testUrl) - .then(function() { - assert(false, "Url unexpectedly exists") + .goto(testUrl, {'Host':'production.example.com'}) + .end() + .then(function(result) { + assert.equal(404, result.code) + done() }) .catch(function(error) { - done(); + done(error); }) ; }); @@ -63,8 +65,10 @@ describe('cap production evolve:files:up', function(done) { var browser = new Browser(); browser - .visit(testUrl) - .then(function() { + .goto(testUrl, {'Host':'production.example.com'}) + .end() + .then(function(result) { + assert.notEqual(404, result.code) done(); }) .catch(function(error) { diff --git a/test/functional/07-sni.js b/test/functional/07-sni.js index 84c3a727..c19fe1c5 100644 --- a/test/functional/07-sni.js +++ b/test/functional/07-sni.js @@ -2,11 +2,10 @@ var assert = require('assert'); var exec = require('child_process').exec; -var Browser = require('zombie'); describe('ssl server name indication', function(done) { it('local host should serve local cert', function(done) { - exec('openssl s_client -connect local.example.com:443 -servername local.example.com', { + exec(`openssl s_client -connect ${process.env.EXAMPLE_COM}:443 -servername local.example.com`, { cwd: process.cwd() + '/temp' }, function(err, stdout, stderr) { assert.ifError(! stdout.match('CN=local.example.com')); @@ -15,7 +14,7 @@ describe('ssl server name indication', function(done) { }); it('production.domain (1/3) should serve production cert', function(done) { - exec('openssl s_client -connect production.example.com:443 -servername production.example.com', { + exec(`openssl s_client -connect ${process.env.EXAMPLE_COM}:443 -servername production.example.com`, { cwd: process.cwd() + '/temp' }, function(err, stdout, stderr) { assert.ifError(! stdout.match('CN=example.com')); @@ -24,7 +23,7 @@ describe('ssl server name indication', function(done) { }); it('www.domain (2/3) should serve production cert', function(done) { - exec('openssl s_client -connect www.example.com:443 -servername www.example.com', { + exec(`openssl s_client -connect ${process.env.EXAMPLE_COM}:443 -servername www.example.com`, { cwd: process.cwd() + '/temp' }, function(err, stdout, stderr) { assert.ifError(! stdout.match('CN=example.com')); @@ -33,7 +32,7 @@ describe('ssl server name indication', function(done) { }); it('bare domain (3/3) should serve production cert', function(done) { - exec('openssl s_client -connect production.example.com:443 -servername production.example.com', { + exec(`openssl s_client -connect ${process.env.EXAMPLE_COM}:443 -servername production.example.com`, { cwd: process.cwd() + '/temp' }, function(err, stdout, stderr) { assert.ifError(! stdout.match('CN=example.com')); @@ -42,7 +41,7 @@ describe('ssl server name indication', function(done) { }); it('not vulnerable to CVE-2014-3566 (SSLv3 POODLE)', function(done) { - exec('openssl s_client -connect local.example.com:443 -ssl3', { + exec(`openssl s_client -connect ${process.env.EXAMPLE_COM}:443 -ssl3`, { cwd: process.cwd() + '/temp' }, function(err, stdout, stderr) { assert.ifError(! stderr.match('routines:SSL3_READ_BYTES:sslv3 alert handshake failure')); diff --git a/test/functional/08-robots.js b/test/functional/08-robots.js index d1362ff8..b15b51ad 100644 --- a/test/functional/08-robots.js +++ b/test/functional/08-robots.js @@ -1,18 +1,25 @@ 'use strict'; var assert = require('assert'); -var Browser = require('zombie'); +var Browser = require('../../lib/node/nightmare'); -describe('robots.txt', function(done) { +describe(`robots.txt`, function(done) { it('on local, should disallow all', function(done) { var browser = new Browser(); browser - .visit('http://local.example.com/robots.txt') - .then(function() { - assert(!!browser.text().match('# Block everything...')); + .goto(`http://${process.env.EXAMPLE_COM}/robots.txt`, {'Host':'local.example.com'}) + .evaluate(function() { + return document.body.innerText; + }) + .end() + .then(function(text) { + assert(!!text.match('# Block everything...'), text); + done() + }) + .catch(function(error) { + done(error) }) - .then(done, done) ; }); @@ -20,11 +27,19 @@ describe('robots.txt', function(done) { var browser = new Browser(); browser - .visit('http://example.com/robots.txt') - .then(function() { - assert(!!browser.text().match('# Sitemap: ')); + .goto(`http://${process.env.EXAMPLE_COM}/robots.txt`, {'Host':'example.com'}) + .evaluate(function() { + return document.body.innerText; + }) + .end() + .then(function(text, result) { + console.dir(result, {colors:true}); + assert(!!text.match('# Sitemap: '), text); + done() + }) + .catch(function(error) { + done(error) }) - .then(done, done) ; }); }); diff --git a/test/functional/varnish/cache.js b/test/functional/varnish/cache.js index 217c7686..c87ed93a 100644 --- a/test/functional/varnish/cache.js +++ b/test/functional/varnish/cache.js @@ -1,18 +1,25 @@ 'use strict'; var assert = require('assert'); -var Browser = require('zombie'); +var Browser = require('../../../lib/node/nightmare'); describe('Varnish', function() { it('should access backend', function(done) { var browser = new Browser(); browser - .visit('http://example.com/') - .then(null, function() { - assert.equal('Evolution WordPress Test – Just another WordPress site', browser.text('title')); + .goto(`http://${process.env.EXAMPLE_COM}/`, {'Host':'example.com'}) + .evaluate(function() { + return document.title; + }) + .end() + .then(function(title) { + assert.equal(title, 'Evolution WordPress Test – Just another WordPress site'); + done() + }) + .catch(function(error) { + done(error) }) - .then(done, done) ; }); @@ -21,11 +28,15 @@ describe('Varnish', function() { var browser = new Browser(); browser - .visit('http://example.com/') - .then(null, function() { - assert.equal('cached', browser.resources[0].response.headers['x-cache']); + .goto(`http://${process.env.EXAMPLE_COM}/`, {'Host':'example.com'}) + .end() + .then(function(result) { + assert.equal(result.headers['x-cache'], 'cached') + done() + }) + .catch(function(error) { + done(error) }) - .then(done, done) ; }); }); @@ -35,19 +46,19 @@ describe('Varnish', function() { var browser = new Browser(); browser - .visit('http://example.com/wp-admin') - .then(null, function() { - assert(browser.resources.browser.getCookie('wordpress_test_cookie')); + .goto(`http://${process.env.EXAMPLE_COM}/`, { + 'Host':'example.com', + 'Cookie':'wordpress_test_cookie=WP+Cookie+check', }) - .then(null, function() { - return browser.visit('http://example.com/'); + .end() + .then(function(result) { + assert.equal(result.headers['age'], '0') + assert.equal(result.headers['x-cache'], 'uncached') + done() }) - .then(null, function() { - assert.equal('Evolution WordPress Test – Just another WordPress site', browser.text('title')); - assert.equal(0, browser.resources[0].response.headers.age); - assert.equal('uncached', browser.resources[0].response.headers['x-cache']); + .catch(function(error) { + done(error) }) - .then(done, done) ; }); }); @@ -56,62 +67,64 @@ describe('Varnish', function() { it('should ignore tracking cookies for cache', function(done) { var browser = new Browser(); - browser.setCookie({ - name: '_test', - value: +new Date(), - domain: 'example.com', - path: '/', - }); - browser - .visit('http://example.com/') - .then(null, function() { - assert(browser.getCookie('_test')); - assert(browser.resources[0].response.headers.age); - assert.equal('cached', browser.resources[0].response.headers['x-cache']); + .goto(`http://${process.env.EXAMPLE_COM}/`, { + 'Host':'example.com', + 'Cookie':`_test=${new Date()}`, + }) + .end() + .then(function(result) { + assert(result.headers['age']) + assert.equal(result.headers['x-cache'], 'cached') + done() + }) + .catch(function(error) { + done(error) }) - .then(done, done) ; }); }); describe('with an application cookies', function() { - var cookie = { - name: 'test', - value: +new Date(), - domain: 'example.com', - path: '/', - }; + var cookie = `test=${new Date()}`; it('should not be cached initially', function(done) { var browser = new Browser(); - browser.setCookie(cookie); - browser - .visit('http://example.com/') - .then(null, function() { - assert(browser.getCookie('test')); - assert.equal(0, browser.resources[0].response.headers.age); - assert.equal('uncached', browser.resources[0].response.headers['x-cache']); + .goto(`http://${process.env.EXAMPLE_COM}/`, { + 'Host':'example.com', + 'Cookie':cookie, + }) + .end() + .then(function(result) { + assert.equal(result.headers['age'], '0') + assert.equal(result.headers['x-cache'], 'uncached') + done() + }) + .catch(function(error) { + done(error) }) - .then(done, done) ; }); it('should be subsequently cached', function(done) { var browser = new Browser(); - browser.setCookie(cookie); - browser - .visit('http://example.com/') - .then(null, function() { - assert(browser.getCookie('test')); - assert(browser.resources[0].response.headers.age); - assert.equal('cached', browser.resources[0].response.headers['x-cache']); + .goto(`http://${process.env.EXAMPLE_COM}/`, { + 'Host':'example.com', + 'Cookie':cookie, + }) + .end() + .then(function(result) { + assert(result.headers['age']) + assert.equal(result.headers['x-cache'], 'cached') + done() + }) + .catch(function(error) { + done(error) }) - .then(done, done) ; }); }); diff --git a/test/functional/wordpress/redirect.js b/test/functional/wordpress/redirect.js index 288a8d1e..9155652b 100644 --- a/test/functional/wordpress/redirect.js +++ b/test/functional/wordpress/redirect.js @@ -1,22 +1,23 @@ 'use strict'; var assert = require('assert'); -var Browser = require('zombie'); +var Browser = require('../../../lib/node/nightmare'); describe('WordPress', function() { it('should redirect /wp-admin to /wp/wp-admin', function(done) { var browser = new Browser(); browser - .visit('http://example.com/wp-admin') - .then(function() { - var location = browser.location.toString(); - - assert(browser.redirected); - assert.equal(200, browser.statusCode); - assert.equal(0, location.indexOf('http://example.com/wp/wp-login')); + .goto(`http://${process.env.EXAMPLE_COM}/wp-admin`, {'Host':'example.com'}) + .end() + .then(function(result) { + assert.equal(200, result.code); + assert.equal(0, result.url.indexOf('http://example.com/wp/wp-login')); + done() + }) + .catch(function(error) { + done(err) }) - .then(done, done) ; }); }); From 34f38caccc615c6cd538e4bec32bd01258217509 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sun, 13 Nov 2016 00:08:07 -0800 Subject: [PATCH 21/66] Couple minor changes * update to gitignore (see tests) * bin/mock should clone from https, so anyone can run tests --- .gitignore | 3 +-- bin/mock | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 4baeb3b6..8bb2ef85 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,5 @@ test/temp/ vendor/ composer.phar *.pyc - .vimrc - +.browserData diff --git a/bin/mock b/bin/mock index 45808f07..fa727518 100755 --- a/bin/mock +++ b/bin/mock @@ -32,7 +32,7 @@ helpers.testDirectory(outputDir, function(err) { } else { var prep = [ - 'git clone git@github.com:evolution/wordpress-example.git ' + outputDir, + 'git clone https://github.com/evolution/wordpress-example.git ' + outputDir, 'cd ' + outputDir, 'git rm -rf .', ]; From d87a6dde2d1e53d5a430f0e57551636ce87ac73a Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sun, 13 Nov 2016 00:36:40 -0800 Subject: [PATCH 22/66] Install several python packages, for SNI support in CI env --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index c3dc7094..8f4d6509 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,7 @@ before_install: - gem --version - bundle --version # python setup (for ansible) + - sudo pip install urllib3 pyopenssl ndg-httpsclient pyasn1 - sudo pip install ansible - python --version - pip --version From 66a63365b64772930475695055e60b8559afb42c Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sun, 13 Nov 2016 01:04:34 -0800 Subject: [PATCH 23/66] Updated node repo task for ansible 2.2 --- lib/ansible/roles/node/tasks/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ansible/roles/node/tasks/main.yml b/lib/ansible/roles/node/tasks/main.yml index 944b8faa..319d5e05 100644 --- a/lib/ansible/roles/node/tasks/main.yml +++ b/lib/ansible/roles/node/tasks/main.yml @@ -17,7 +17,7 @@ - name: Add Nodesource 4.x repos apt_repository: repo={{item}} state=present update_cache=yes - with_items: node_repos + with_items: "{{ node_repos }}" sudo: yes - name: Install node From 0a96c2fad6af1e12886f9c390087460fd540dc41 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sun, 13 Nov 2016 10:46:40 -0800 Subject: [PATCH 24/66] Tweak order of provision/install for CI --- .travis.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8f4d6509..b2709e6c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,11 +35,9 @@ before_install: # copy our local evolution-wordpress as npm dependency - mkdir -p /vagrant/node_modules - cp -RP $PWD /vagrant/node_modules/evolution-wordpress - # invoke local provision (as default user with elevated permissions) + # set up local provisioner - sudo cp $PWD/.travis.provision.bin $PWD/bin/provision - sudo chmod +x $PWD/bin/provision - - sudo $PWD/bin/provision - - sudo chown -Rf $USER:$USER $HOME/.ansible # mock vagrant binary (for parity with local/remote stages) - sudo cp $PWD/.travis.vagrant.bin /bin/vagrant - sudo chmod +x /bin/vagrant @@ -50,6 +48,9 @@ before_install: # install composer (for phpunit) - curl -sS https://getcomposer.org/installer | php install: + - echo "Provision locally and fix permissions afterward" + - sudo $PWD/bin/provision + - sudo chown -Rf $USER:$USER $HOME/.ansible - echo "Install Composer dependencies" - php composer.phar install --dev script: From 063773c83f1a2d5cc06e80e8b39d09a6dfcbc28b Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sun, 13 Nov 2016 10:57:31 -0800 Subject: [PATCH 25/66] Install composer after local provision (again for CI) --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b2709e6c..657d9d13 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,13 +45,12 @@ before_install: - ssh-keyscan -H production.example.com >> $HOME/.ssh/known_hosts - ssh-keyscan -H www.example.com >> $HOME/.ssh/known_hosts - ssh-keyscan -H example.com >> $HOME/.ssh/known_hosts - # install composer (for phpunit) - - curl -sS https://getcomposer.org/installer | php install: - echo "Provision locally and fix permissions afterward" - sudo $PWD/bin/provision - sudo chown -Rf $USER:$USER $HOME/.ansible - echo "Install Composer dependencies" + - curl -sS https://getcomposer.org/installer | php - php composer.phar install --dev script: - ./vendor/bin/phpunit From e3ca2e9ff235d5335af9cff91e0a3663bad448bc Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sun, 13 Nov 2016 11:15:23 -0800 Subject: [PATCH 26/66] Supress composer interaction (maybe whats timing out in CI?) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 657d9d13..3b1f184e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -51,7 +51,7 @@ install: - sudo chown -Rf $USER:$USER $HOME/.ansible - echo "Install Composer dependencies" - curl -sS https://getcomposer.org/installer | php - - php composer.phar install --dev + - php composer.phar install -n --dev script: - ./vendor/bin/phpunit - npm test From d9191b5467c17d568988b0ae3e3d53f3acb33769 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sun, 13 Nov 2016 11:27:34 -0800 Subject: [PATCH 27/66] Configured virtual display server for CI This is needed for headless browser tests with nightmare (via electon). See: * https://github.com/electron/electron/blob/master/docs/tutorial/testing-on-headless-ci.md#travis-ci * https://docs.travis-ci.com/user/gui-and-headless-browsers/#Using-xvfb-to-Run-Tests-That-Require-a-GUI --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index 3b1f184e..b921a122 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,9 @@ addons: - local.example.com - production.example.com - www.example.com + apt: + packages: + - xvfb before_install: # node setup (for yeoman) - nvm install 4.0 @@ -46,6 +49,9 @@ before_install: - ssh-keyscan -H www.example.com >> $HOME/.ssh/known_hosts - ssh-keyscan -H example.com >> $HOME/.ssh/known_hosts install: + - echo "Configure virtual display server (for headless tests)" + - export DISPLAY=':99.0' + - Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & - echo "Provision locally and fix permissions afterward" - sudo $PWD/bin/provision - sudo chown -Rf $USER:$USER $HOME/.ansible From 490e883d12c8ad504e47a87dabc30b8f106b5487 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sun, 13 Nov 2016 12:36:53 -0800 Subject: [PATCH 28/66] Increase composer verbosity Trying to figure out why it keeps stalling in CI --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b921a122..0aa7df9a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,7 +57,7 @@ install: - sudo chown -Rf $USER:$USER $HOME/.ansible - echo "Install Composer dependencies" - curl -sS https://getcomposer.org/installer | php - - php composer.phar install -n --dev + - php composer.phar install -n --dev -vv script: - ./vendor/bin/phpunit - npm test From 3f294320deb787dccf76fe3cccf00dcae3646181 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sun, 13 Nov 2016 12:52:45 -0800 Subject: [PATCH 29/66] Still trying to get headless tests working with nightmare on CI --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0aa7df9a..aace2cb5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,10 +48,10 @@ before_install: - ssh-keyscan -H production.example.com >> $HOME/.ssh/known_hosts - ssh-keyscan -H www.example.com >> $HOME/.ssh/known_hosts - ssh-keyscan -H example.com >> $HOME/.ssh/known_hosts + # configure virtual display server (for headless tests) + - "export DISPLAY=':99.0'" + - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1024x768x24" install: - - echo "Configure virtual display server (for headless tests)" - - export DISPLAY=':99.0' - - Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & - echo "Provision locally and fix permissions afterward" - sudo $PWD/bin/provision - sudo chown -Rf $USER:$USER $HOME/.ansible From f2027744c499837f81f55658c473fc30e110e246 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 15 Nov 2016 10:12:21 -0800 Subject: [PATCH 30/66] While tests are /mostly/ passing, headless tests are dropping out entirely --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index aace2cb5..09ebe50a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -50,7 +50,8 @@ before_install: - ssh-keyscan -H example.com >> $HOME/.ssh/known_hosts # configure virtual display server (for headless tests) - "export DISPLAY=':99.0'" - - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1024x768x24" + - "sh -e /etc/init.d/xvfb start" + - sleep 3 install: - echo "Provision locally and fix permissions afterward" - sudo $PWD/bin/provision From ed27585233d67c7f150b1a147e905cbad2a1d77d Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 15 Nov 2016 10:18:52 -0800 Subject: [PATCH 31/66] More headless test tweaks --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 09ebe50a..423a1ff8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -50,8 +50,7 @@ before_install: - ssh-keyscan -H example.com >> $HOME/.ssh/known_hosts # configure virtual display server (for headless tests) - "export DISPLAY=':99.0'" - - "sh -e /etc/init.d/xvfb start" - - sleep 3 + - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16" install: - echo "Provision locally and fix permissions afterward" - sudo $PWD/bin/provision From edb520d665ce7d6063f7f188dddf567b61cb8413 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 15 Nov 2016 10:33:04 -0800 Subject: [PATCH 32/66] One more try for headless tests --- .travis.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 423a1ff8..6e1cf1b1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,9 +48,6 @@ before_install: - ssh-keyscan -H production.example.com >> $HOME/.ssh/known_hosts - ssh-keyscan -H www.example.com >> $HOME/.ssh/known_hosts - ssh-keyscan -H example.com >> $HOME/.ssh/known_hosts - # configure virtual display server (for headless tests) - - "export DISPLAY=':99.0'" - - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16" install: - echo "Provision locally and fix permissions afterward" - sudo $PWD/bin/provision @@ -60,4 +57,4 @@ install: - php composer.phar install -n --dev -vv script: - ./vendor/bin/phpunit - - npm test + - DEBUG=nightmare xvfb-run --server-args="-screen 0 1024x768x24" npm test From 1ed989d0a8da87ff8280284352d628af7f0ab9b2 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 15 Nov 2016 11:10:49 -0800 Subject: [PATCH 33/66] Start caching composer deps, expand nightmare/electron debug messaging --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6e1cf1b1..2b8d3770 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,9 @@ sudo: required dist: trusty language: generic +cache: + directories: + - $TRAVIS_BUILD_DIR/vendor addons: hosts: - example.com @@ -57,4 +60,4 @@ install: - php composer.phar install -n --dev -vv script: - ./vendor/bin/phpunit - - DEBUG=nightmare xvfb-run --server-args="-screen 0 1024x768x24" npm test + - DEBUG=nightmare:*,electron:* xvfb-run --server-args="-screen 0 1024x768x24" npm test From bd3af6b7b954112dafeb69f6b4daa7eb6e9e03c3 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 15 Nov 2016 11:21:29 -0800 Subject: [PATCH 34/66] Adding electron deps --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 2b8d3770..d0c5020a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ addons: apt: packages: - xvfb + - libgconf2-dev before_install: # node setup (for yeoman) - nvm install 4.0 From a548aae50ca62158b287e091718f2f7c1e60feb3 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 15 Nov 2016 11:47:24 -0800 Subject: [PATCH 35/66] Wait longer for tests to run --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d0c5020a..354206a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -61,4 +61,4 @@ install: - php composer.phar install -n --dev -vv script: - ./vendor/bin/phpunit - - DEBUG=nightmare:*,electron:* xvfb-run --server-args="-screen 0 1024x768x24" npm test + - travis_wait DEBUG=nightmare:*,electron:* xvfb-run --server-args="-screen 0 1024x768x24" npm test From 8df75c1f80607086fe6d2a822f8a6b0153506d95 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 15 Nov 2016 11:55:48 -0800 Subject: [PATCH 36/66] Log provision/deploy output as we go in travis, so the build doesn't stall --- .travis.yml | 2 +- test/functional/03-evolve.provision.js | 16 +++++++++++++--- test/functional/04-deploy.js | 16 +++++++++++++--- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 354206a9..d0c5020a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -61,4 +61,4 @@ install: - php composer.phar install -n --dev -vv script: - ./vendor/bin/phpunit - - travis_wait DEBUG=nightmare:*,electron:* xvfb-run --server-args="-screen 0 1024x768x24" npm test + - DEBUG=nightmare:*,electron:* xvfb-run --server-args="-screen 0 1024x768x24" npm test diff --git a/test/functional/03-evolve.provision.js b/test/functional/03-evolve.provision.js index 052ec89e..17aa97ae 100644 --- a/test/functional/03-evolve.provision.js +++ b/test/functional/03-evolve.provision.js @@ -12,16 +12,26 @@ describe('cap production evolve:provision', function(done) { }); child.stdout.on('data', function (data) { - output += data.toString(); + if (process.env.TRAVIS) { + console.log(data.toString()); + } else { + output += data.toString(); + } }); child.stderr.on('data', function (data) { - output += data.toString(); + if (process.env.TRAVIS) { + console.log(data.toString()); + } else { + output += data.toString(); + } }); child.on('exit', function (code) { if (code) { - console.error(output); + if (!process.env.TRAVIS) { + console.error(output); + } done(new Error('exited with ' + code)); } else { done(); diff --git a/test/functional/04-deploy.js b/test/functional/04-deploy.js index 7f7982f9..ee81abea 100644 --- a/test/functional/04-deploy.js +++ b/test/functional/04-deploy.js @@ -12,16 +12,26 @@ describe('cap production deploy', function(done) { }); child.stdout.on('data', function (data) { - output += data.toString(); + if (process.env.TRAVIS) { + console.log(data.toString()); + } else { + output += data.toString(); + } }); child.stderr.on('data', function (data) { - output += data.toString(); + if (process.env.TRAVIS) { + console.log(data.toString()); + } else { + output += data.toString(); + } }); child.on('exit', function (code) { if (code) { - console.error(output); + if (!process.env.TRAVIS) { + console.error(output); + } done(new Error('exited with ' + code)); } else { done(); From f672d6744450fc46dee171609c153288025a2acc Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 15 Nov 2016 12:13:24 -0800 Subject: [PATCH 37/66] Skip local fetching of purge kernel script -- not necessary on CI anyway --- lib/ansible/roles/common/tasks/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/ansible/roles/common/tasks/main.yml b/lib/ansible/roles/common/tasks/main.yml index 06fe1bb2..205c8ee7 100644 --- a/lib/ansible/roles/common/tasks/main.yml +++ b/lib/ansible/roles/common/tasks/main.yml @@ -25,10 +25,12 @@ # see evolution/wordpress#126 - name: Fetch kernel purging script (on control machine) local_action: get_url dest=/tmp/purge-kernels.py url=https://raw.githubusercontent.com/EvanK/ubuntu-purge-kernels/master/purge-kernels.py force=yes + when: not lookup('env','CI') - name: Copy purging script to remote copy: src=/tmp/purge-kernels.py dest=/tmp/purge-kernels.py force=yes mode=0755 sudo: yes + when: not lookup('env','CI') - name: Purge kernels as necessary command: /tmp/purge-kernels.py From 987006189cfe551aa8377fb725e2157740adc5a4 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 15 Nov 2016 12:23:08 -0800 Subject: [PATCH 38/66] Work around SNI local_action, when in CI --- lib/ansible/roles/common/tasks/main.yml | 2 +- lib/ansible/roles/node/tasks/main.yml | 7 +++++++ lib/ansible/roles/wp-cli/tasks/main.yml | 9 ++++++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/ansible/roles/common/tasks/main.yml b/lib/ansible/roles/common/tasks/main.yml index 205c8ee7..394d7853 100644 --- a/lib/ansible/roles/common/tasks/main.yml +++ b/lib/ansible/roles/common/tasks/main.yml @@ -23,7 +23,7 @@ when: dynamic_resolv.stdout != "" # see evolution/wordpress#126 -- name: Fetch kernel purging script (on control machine) +- name: Fetch kernel purging script (from control) local_action: get_url dest=/tmp/purge-kernels.py url=https://raw.githubusercontent.com/EvanK/ubuntu-purge-kernels/master/purge-kernels.py force=yes when: not lookup('env','CI') diff --git a/lib/ansible/roles/node/tasks/main.yml b/lib/ansible/roles/node/tasks/main.yml index 319d5e05..1f88306f 100644 --- a/lib/ansible/roles/node/tasks/main.yml +++ b/lib/ansible/roles/node/tasks/main.yml @@ -10,10 +10,17 @@ - name: Fetch Nodesource apt key (from control) local_action: get_url dest=/tmp/ns4x.gpg.key url=https://deb.nodesource.com/gpgkey/nodesource.gpg.key force=yes + when: not lookup('env','CI') - name: Add Nodesource apt key apt_key: data="{{ lookup('file', '/tmp/ns4x.gpg.key') }}" state=present sudo: yes + when: not lookup('env','CI') + +- name: Add Nodesource apt key + apt_key: url=https://deb.nodesource.com/gpgkey/nodesource.gpg.key state=present + sudo: yes + when: lookup('env','CI') - name: Add Nodesource 4.x repos apt_repository: repo={{item}} state=present update_cache=yes diff --git a/lib/ansible/roles/wp-cli/tasks/main.yml b/lib/ansible/roles/wp-cli/tasks/main.yml index b120248b..14f8d5e1 100644 --- a/lib/ansible/roles/wp-cli/tasks/main.yml +++ b/lib/ansible/roles/wp-cli/tasks/main.yml @@ -1,7 +1,14 @@ # see evolution/wordpress#126 -- name: Fetch latest wp-cli (on control machine) +- name: Fetch latest wp-cli (from control) local_action: get_url dest=/tmp/wp-cli url=https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar force=yes + when: not lookup('env','CI') - name: Copy latest wp-cli to remote copy: src=/tmp/wp-cli dest=/usr/local/bin/wp force=yes mode=0755 sudo: yes + when: not lookup('env','CI') + +- name: Fetch latest wp-cli + get_url: dest=/usr/local/bin/wp url=https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar force=yes mode=0755 + sudo: yes + when: lookup('env','CI') From 42fa31a57650bc136538834cd2a8cc01e01b02af Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 15 Nov 2016 12:55:22 -0800 Subject: [PATCH 39/66] Fix local_action tmp file permissions (CI only) The rub here is, local provisioning runs as root and leaves tmp files sitting around, owned by root. Later prod provisioning then fails trying to overwrite said files as non-sudo local_actions. The fix is to clean up after ourselves during local provision, removing said tmp files after we're done with them --- lib/ansible/roles/common/tasks/main.yml | 5 +++-- lib/ansible/roles/node/tasks/main.yml | 8 ++------ lib/ansible/roles/wp-cli/tasks/main.yml | 8 ++------ 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/lib/ansible/roles/common/tasks/main.yml b/lib/ansible/roles/common/tasks/main.yml index 394d7853..6c47dcc0 100644 --- a/lib/ansible/roles/common/tasks/main.yml +++ b/lib/ansible/roles/common/tasks/main.yml @@ -25,12 +25,10 @@ # see evolution/wordpress#126 - name: Fetch kernel purging script (from control) local_action: get_url dest=/tmp/purge-kernels.py url=https://raw.githubusercontent.com/EvanK/ubuntu-purge-kernels/master/purge-kernels.py force=yes - when: not lookup('env','CI') - name: Copy purging script to remote copy: src=/tmp/purge-kernels.py dest=/tmp/purge-kernels.py force=yes mode=0755 sudo: yes - when: not lookup('env','CI') - name: Purge kernels as necessary command: /tmp/purge-kernels.py @@ -39,6 +37,9 @@ sudo: yes when: not lookup('env','CI') +- name: Remove kernel purging script in tmp (from control) + local_action: file dest=/tmp/purge-kernels.py state=absent + - name: Show purged kernels debug: var=purgekernels_result diff --git a/lib/ansible/roles/node/tasks/main.yml b/lib/ansible/roles/node/tasks/main.yml index 1f88306f..3b9c9e3a 100644 --- a/lib/ansible/roles/node/tasks/main.yml +++ b/lib/ansible/roles/node/tasks/main.yml @@ -10,17 +10,13 @@ - name: Fetch Nodesource apt key (from control) local_action: get_url dest=/tmp/ns4x.gpg.key url=https://deb.nodesource.com/gpgkey/nodesource.gpg.key force=yes - when: not lookup('env','CI') - name: Add Nodesource apt key apt_key: data="{{ lookup('file', '/tmp/ns4x.gpg.key') }}" state=present sudo: yes - when: not lookup('env','CI') -- name: Add Nodesource apt key - apt_key: url=https://deb.nodesource.com/gpgkey/nodesource.gpg.key state=present - sudo: yes - when: lookup('env','CI') +- name: Remove Nodesource apt key in tmp (from control) + local_action: file dest=/tmp/ns4x.gpg.key state=absent - name: Add Nodesource 4.x repos apt_repository: repo={{item}} state=present update_cache=yes diff --git a/lib/ansible/roles/wp-cli/tasks/main.yml b/lib/ansible/roles/wp-cli/tasks/main.yml index 14f8d5e1..e6d328c1 100644 --- a/lib/ansible/roles/wp-cli/tasks/main.yml +++ b/lib/ansible/roles/wp-cli/tasks/main.yml @@ -1,14 +1,10 @@ # see evolution/wordpress#126 - name: Fetch latest wp-cli (from control) local_action: get_url dest=/tmp/wp-cli url=https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar force=yes - when: not lookup('env','CI') - name: Copy latest wp-cli to remote copy: src=/tmp/wp-cli dest=/usr/local/bin/wp force=yes mode=0755 sudo: yes - when: not lookup('env','CI') -- name: Fetch latest wp-cli - get_url: dest=/usr/local/bin/wp url=https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar force=yes mode=0755 - sudo: yes - when: lookup('env','CI') +- name: Remove latest wp-cli in tmp (from control) + local_action: file dest=/tmp/wp-cli state=absent From 4761299b8d95cf40867069913cd09abb3aa77dba Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 15 Nov 2016 13:29:46 -0800 Subject: [PATCH 40/66] Use local abs path for npm install, just on CI --- bin/mock | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/bin/mock b/bin/mock index fa727518..52677bb5 100755 --- a/bin/mock +++ b/bin/mock @@ -7,7 +7,8 @@ var exec = require('child_process').exec; var helpers = require('yeoman-test'); var path = require('path'); -var outputDir = path.join(__dirname, '..', 'temp'); +var libDir = path.normalize(path.join(__dirname, '..')); +var outputDir = path.join(libDir, 'temp'); var privatePath = path.join(outputDir, '/lib/ansible/files/ssh/id_rsa'); var privateKey = fs.existsSync(privatePath) ? fs.readFileSync(privatePath) : null; var publicPath = path.join(outputDir, '/lib/ansible/files/ssh/id_rsa.pub'); @@ -113,6 +114,21 @@ helpers.testDirectory(outputDir, function(err) { fs.writeFileSync(outputDir + '/Vagrantfile', vagrantFile); + // use local path for evolution, instead of npm registry package + if (isCI) { + var packageJson = fs.readFileSync(outputDir + '/package.json', 'utf8') + .replace( + new RegExp('("evolution-wordpress":[ ]*)"[^"]+"'), + [ + '$1', + `"file:${libDir}"`, + ].join('') + ) + ; + + fs.writeFileSync(outputDir + '/package.json', packageJson); + } + var wrap = [ 'git add .', ]; From ab695e46d13a4eaab0b2d8dc9257c6fc5d48bda2 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 15 Nov 2016 13:49:19 -0800 Subject: [PATCH 41/66] Tweak permissions for npm install from local fs --- .travis.yml | 2 ++ bin/mock | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d0c5020a..2553c896 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,6 +52,8 @@ before_install: - ssh-keyscan -H production.example.com >> $HOME/.ssh/known_hosts - ssh-keyscan -H www.example.com >> $HOME/.ssh/known_hosts - ssh-keyscan -H example.com >> $HOME/.ssh/known_hosts + # ensure build dir is world readable (for npm install from abs path) + - sudo chmod -R a+r $TRAVIS_BUILD_DIR install: - echo "Provision locally and fix permissions afterward" - sudo $PWD/bin/provision diff --git a/bin/mock b/bin/mock index 52677bb5..1b0f5124 100755 --- a/bin/mock +++ b/bin/mock @@ -114,7 +114,7 @@ helpers.testDirectory(outputDir, function(err) { fs.writeFileSync(outputDir + '/Vagrantfile', vagrantFile); - // use local path for evolution, instead of npm registry package + // since we've yet to publish to npm, use local abs path for evolution if (isCI) { var packageJson = fs.readFileSync(outputDir + '/package.json', 'utf8') .replace( From 7a45163269716d629ed0f24af661d5e01a8b9579 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 15 Nov 2016 14:17:17 -0800 Subject: [PATCH 42/66] Use github committish for npm install, just on CI --- .travis.yml | 2 -- bin/mock | 5 ++--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2553c896..d0c5020a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,8 +52,6 @@ before_install: - ssh-keyscan -H production.example.com >> $HOME/.ssh/known_hosts - ssh-keyscan -H www.example.com >> $HOME/.ssh/known_hosts - ssh-keyscan -H example.com >> $HOME/.ssh/known_hosts - # ensure build dir is world readable (for npm install from abs path) - - sudo chmod -R a+r $TRAVIS_BUILD_DIR install: - echo "Provision locally and fix permissions afterward" - sudo $PWD/bin/provision diff --git a/bin/mock b/bin/mock index 1b0f5124..fe6f3aa0 100755 --- a/bin/mock +++ b/bin/mock @@ -7,8 +7,7 @@ var exec = require('child_process').exec; var helpers = require('yeoman-test'); var path = require('path'); -var libDir = path.normalize(path.join(__dirname, '..')); -var outputDir = path.join(libDir, 'temp'); +var outputDir = path.join(__dirname, '..', 'temp'); var privatePath = path.join(outputDir, '/lib/ansible/files/ssh/id_rsa'); var privateKey = fs.existsSync(privatePath) ? fs.readFileSync(privatePath) : null; var publicPath = path.join(outputDir, '/lib/ansible/files/ssh/id_rsa.pub'); @@ -121,7 +120,7 @@ helpers.testDirectory(outputDir, function(err) { new RegExp('("evolution-wordpress":[ ]*)"[^"]+"'), [ '$1', - `"file:${libDir}"`, + `"evolution/wordpress#${process.env.TRAVIS_COMMIT}"`, ].join('') ) ; From 267df05230d9a079423ca28bffbb4cdc1399aa4f Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 15 Nov 2016 15:02:02 -0800 Subject: [PATCH 43/66] More tweaks for nightmare --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d0c5020a..4e74f152 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,9 @@ addons: packages: - xvfb - libgconf2-dev +env: + global: + - DISPLAY: ":99.0" before_install: # node setup (for yeoman) - nvm install 4.0 @@ -61,4 +64,4 @@ install: - php composer.phar install -n --dev -vv script: - ./vendor/bin/phpunit - - DEBUG=nightmare:*,electron:* xvfb-run --server-args="-screen 0 1024x768x24" npm test + - DEBUG=nightmare:*,electron:* xvfb-run --server-args="-screen 0 1024x768x24" ./bin/test From 6c7dfbc8dfcc63b817c5876427db4cfc0a10f0d9 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 15 Nov 2016 15:41:09 -0800 Subject: [PATCH 44/66] Try running xvfb from background --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4e74f152..7374148a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,7 @@ addons: - libgconf2-dev env: global: + - DEBUG: "nightmare:*,electron:*" - DISPLAY: ":99.0" before_install: # node setup (for yeoman) @@ -55,6 +56,8 @@ before_install: - ssh-keyscan -H production.example.com >> $HOME/.ssh/known_hosts - ssh-keyscan -H www.example.com >> $HOME/.ssh/known_hosts - ssh-keyscan -H example.com >> $HOME/.ssh/known_hosts + # run xvfb as background service + - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1024x768x24" install: - echo "Provision locally and fix permissions afterward" - sudo $PWD/bin/provision @@ -64,4 +67,4 @@ install: - php composer.phar install -n --dev -vv script: - ./vendor/bin/phpunit - - DEBUG=nightmare:*,electron:* xvfb-run --server-args="-screen 0 1024x768x24" ./bin/test + - ./bin/test From e2d0c1a351730242760b0782d415c27bb4433a11 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 15 Nov 2016 16:01:05 -0800 Subject: [PATCH 45/66] Mock package.json to bypass npm registry for evo install --- bin/mock | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/bin/mock b/bin/mock index fe6f3aa0..c093846d 100755 --- a/bin/mock +++ b/bin/mock @@ -3,11 +3,12 @@ 'use strict' var fs = require('fs-extra'); -var exec = require('child_process').exec; +var cp = require('child_process'); var helpers = require('yeoman-test'); var path = require('path'); -var outputDir = path.join(__dirname, '..', 'temp'); +var libDir = path.normalize(path.join(__dirname, '..')); +var outputDir = path.join(libDir, 'temp'); var privatePath = path.join(outputDir, '/lib/ansible/files/ssh/id_rsa'); var privateKey = fs.existsSync(privatePath) ? fs.readFileSync(privatePath) : null; var publicPath = path.join(outputDir, '/lib/ansible/files/ssh/id_rsa.pub'); @@ -39,7 +40,7 @@ helpers.testDirectory(outputDir, function(err) { } console.log('Executing `%s`', prep.join(' && ')); - exec(prep.join(' && '), function(err, stdout, stderr) { + cp.exec(prep.join(' && '), function(err, stdout, stderr) { if (err) { throw err; } @@ -114,20 +115,26 @@ helpers.testDirectory(outputDir, function(err) { fs.writeFileSync(outputDir + '/Vagrantfile', vagrantFile); // since we've yet to publish to npm, use local abs path for evolution - if (isCI) { - var packageJson = fs.readFileSync(outputDir + '/package.json', 'utf8') - .replace( - new RegExp('("evolution-wordpress":[ ]*)"[^"]+"'), - [ - '$1', - `"evolution/wordpress#${process.env.TRAVIS_COMMIT}"`, - ].join('') - ) - ; - - fs.writeFileSync(outputDir + '/package.json', packageJson); + var committish; + if(isCI) { + committish = process.env.TRAVIS_COMMIT; + } else { + committish = cp.execSync('git rev-parse --verify HEAD', { cwd: libDir }) + .toString().trim(); } + var packageJson = fs.readFileSync(outputDir + '/package.json', 'utf8') + .replace( + new RegExp('("evolution-wordpress":[ ]*)"[^"]+"'), + [ + '$1', + `"evolution/wordpress#${committish}"`, + ].join('') + ) + ; + + fs.writeFileSync(outputDir + '/package.json', packageJson); + var wrap = [ 'git add .', ]; @@ -140,7 +147,7 @@ helpers.testDirectory(outputDir, function(err) { } console.log('Executing `%s`', wrap.join(' && ')); - exec(wrap.join(' && '), { cwd: outputDir }); + cp.exec(wrap.join(' && '), { cwd: outputDir }); }); }); }); From 85685554a0ba0ec3712bf2f853ee5aa1a4172316 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 15 Nov 2016 16:02:34 -0800 Subject: [PATCH 46/66] Removed nightmare debug, added test matrix for ansible and node versions --- .travis.yml | 12 +++++++++--- bin/mock | 3 +-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7374148a..2092ddee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,11 +16,17 @@ addons: - libgconf2-dev env: global: - - DEBUG: "nightmare:*,electron:*" - DISPLAY: ":99.0" + matrix: + - ANSIBLE_VERSION: "2.0.2" + - ANSIBLE_VERSION: "2.1.3" + - ANSIBLE_VERSION: "2.2.0" + - NODE_VERSION: "4.0" + - NODE_VERSION: "5.0" + - NODE_VERSION: "6.0" before_install: # node setup (for yeoman) - - nvm install 4.0 + - nvm install $NODE_VERSION - node --version - npm --version - nvm --version @@ -35,7 +41,7 @@ before_install: - bundle --version # python setup (for ansible) - sudo pip install urllib3 pyopenssl ndg-httpsclient pyasn1 - - sudo pip install ansible + - sudo pip install ansible==$ANSIBLE_VERSION - python --version - pip --version - ansible --version diff --git a/bin/mock b/bin/mock index c093846d..f2fce179 100755 --- a/bin/mock +++ b/bin/mock @@ -114,9 +114,8 @@ helpers.testDirectory(outputDir, function(err) { fs.writeFileSync(outputDir + '/Vagrantfile', vagrantFile); - // since we've yet to publish to npm, use local abs path for evolution var committish; - if(isCI) { + if (isCI) { committish = process.env.TRAVIS_COMMIT; } else { committish = cp.execSync('git rev-parse --verify HEAD', { cwd: libDir }) From 1ffa75c64d5411edc01bb3d83bf1ec91c30a859f Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 15 Nov 2016 16:54:16 -0800 Subject: [PATCH 47/66] =?UTF-8?q?Fixed=20build=20matrix=20=C2=AF\=5F(?= =?UTF-8?q?=E3=83=84)=5F/=C2=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .travis.yml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2092ddee..8e2b6e6d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,12 +18,15 @@ env: global: - DISPLAY: ":99.0" matrix: - - ANSIBLE_VERSION: "2.0.2" - - ANSIBLE_VERSION: "2.1.3" - - ANSIBLE_VERSION: "2.2.0" - - NODE_VERSION: "4.0" - - NODE_VERSION: "5.0" - - NODE_VERSION: "6.0" + - ANSIBLE_VERSION="2.0.2" NODE_VERSION="4.0" + - ANSIBLE_VERSION="2.0.2" NODE_VERSION="5.0" + - ANSIBLE_VERSION="2.0.2" NODE_VERSION="6.0" + - ANSIBLE_VERSION="2.1.3" NODE_VERSION="4.0" + - ANSIBLE_VERSION="2.1.3" NODE_VERSION="5.0" + - ANSIBLE_VERSION="2.1.3" NODE_VERSION="6.0" + - ANSIBLE_VERSION="2.2.0" NODE_VERSION="4.0" + - ANSIBLE_VERSION="2.2.0" NODE_VERSION="5.0" + - ANSIBLE_VERSION="2.2.0" NODE_VERSION="6.0" before_install: # node setup (for yeoman) - nvm install $NODE_VERSION From 03841c0e14f7d0e88e2443c1583983a20b4c2515 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 15 Nov 2016 18:02:09 -0800 Subject: [PATCH 48/66] Removed Ansible 2.0 from build matrix (SNI bug again), moved rvm cmds above nvm (see travis-ci/travis-ci#5092) --- .travis.yml | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8e2b6e6d..77040c2e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,9 +18,6 @@ env: global: - DISPLAY: ":99.0" matrix: - - ANSIBLE_VERSION="2.0.2" NODE_VERSION="4.0" - - ANSIBLE_VERSION="2.0.2" NODE_VERSION="5.0" - - ANSIBLE_VERSION="2.0.2" NODE_VERSION="6.0" - ANSIBLE_VERSION="2.1.3" NODE_VERSION="4.0" - ANSIBLE_VERSION="2.1.3" NODE_VERSION="5.0" - ANSIBLE_VERSION="2.1.3" NODE_VERSION="6.0" @@ -28,12 +25,6 @@ env: - ANSIBLE_VERSION="2.2.0" NODE_VERSION="5.0" - ANSIBLE_VERSION="2.2.0" NODE_VERSION="6.0" before_install: - # node setup (for yeoman) - - nvm install $NODE_VERSION - - node --version - - npm --version - - nvm --version - - npm install # ruby setup (for capistrano) - rvm install 1.9.3 - rvm use 1.9.3 @@ -42,6 +33,12 @@ before_install: - rvm --version - gem --version - bundle --version + # node setup (for yeoman) + - nvm install $NODE_VERSION + - node --version + - npm --version + - nvm --version + - npm install # python setup (for ansible) - sudo pip install urllib3 pyopenssl ndg-httpsclient pyasn1 - sudo pip install ansible==$ANSIBLE_VERSION From 37bbde0c07c4b98803c857a41b52c02bcc61845a Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Wed, 16 Nov 2016 08:20:06 -0800 Subject: [PATCH 49/66] Reduced build matrix to ansible 2.1-2.2, on node 4.0 --- .travis.yml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 77040c2e..63a75edc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,14 +16,11 @@ addons: - libgconf2-dev env: global: + # DEBUG: "nightmare:*,electron:*" - DISPLAY: ":99.0" matrix: - - ANSIBLE_VERSION="2.1.3" NODE_VERSION="4.0" - - ANSIBLE_VERSION="2.1.3" NODE_VERSION="5.0" - - ANSIBLE_VERSION="2.1.3" NODE_VERSION="6.0" - - ANSIBLE_VERSION="2.2.0" NODE_VERSION="4.0" - - ANSIBLE_VERSION="2.2.0" NODE_VERSION="5.0" - - ANSIBLE_VERSION="2.2.0" NODE_VERSION="6.0" + - ANSIBLE_VERSION: "2.1.3" + - ANSIBLE_VERSION: "2.2.0" before_install: # ruby setup (for capistrano) - rvm install 1.9.3 @@ -34,7 +31,7 @@ before_install: - gem --version - bundle --version # node setup (for yeoman) - - nvm install $NODE_VERSION + - nvm install 4.0 - node --version - npm --version - nvm --version From 87d155a18c924b2b6147a564ff9691837c95a0f2 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Wed, 16 Nov 2016 15:10:10 -0800 Subject: [PATCH 50/66] Cache more deps in Travis, to speed up CI builds --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 63a75edc..58f23709 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,10 @@ dist: trusty language: generic cache: directories: + - $HOME/.rvm + - $HOME/.nvm - $TRAVIS_BUILD_DIR/vendor + - $TRAVIS_BUILD_DIR/node_modules addons: hosts: - example.com From af8b8b707142e55095027655fc8131f828450a55 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sun, 20 Nov 2016 10:31:13 -0800 Subject: [PATCH 51/66] Gracefully clean up old bower files --- lib/yeoman/index.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/yeoman/index.js b/lib/yeoman/index.js index a8c83b05..820be019 100644 --- a/lib/yeoman/index.js +++ b/lib/yeoman/index.js @@ -598,7 +598,7 @@ var WordpressGenerator = yeoman.Base.extend({ } } catch (e) {}; - // remove old bower deps + // remove old bower deps for evolution try { var bowerfile = path.join(this.env.cwd, 'bower.json'); var bowerContents = this.fs.readJSON(bowerfile); @@ -616,6 +616,15 @@ var WordpressGenerator = yeoman.Base.extend({ } } catch (e) {}; + // remove old bower json, if no deps remain + try { + var bowerfile = path.join(this.env.cwd, 'bower.json'); + var bowerContents = this.fs.readJSON(bowerfile); + if (!bowerContents.hasOwnProperty('dependencies') || Object.keys(bowerContents.dependencies).length < 1) { + fs.unlinkSync(bowerfile); + } + } catch (e) {}; + // remove old bower components try { fs.removeSync(path.join(this.env.cwd, 'bower_components/evolution-wordpress')); From 37a1709e5e1516da3e2c2e0ce23dc6f6039d558d Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sun, 20 Nov 2016 10:39:46 -0800 Subject: [PATCH 52/66] Re-adding support for bower deps, when a bower.json is found This will globally install bower on the remote server, but only do a bower install on deploy _when a bower.json_ is found as part of the deploying project. --- lib/ansible/roles/node/tasks/main.yml | 5 +++++ lib/ansible/roles/node/vars/main.yml | 2 ++ lib/yeoman/templates/lib/capistrano/deploy.rb | 10 ++++++++++ 3 files changed, 17 insertions(+) diff --git a/lib/ansible/roles/node/tasks/main.yml b/lib/ansible/roles/node/tasks/main.yml index 3b9c9e3a..62482383 100644 --- a/lib/ansible/roles/node/tasks/main.yml +++ b/lib/ansible/roles/node/tasks/main.yml @@ -26,3 +26,8 @@ - name: Install node apt: pkg=nodejs state=present sudo: yes + +- name: Install global node modules + command: npm install -g {{ item }} + with_items: "{{ node_modules }}" + sudo: yes diff --git a/lib/ansible/roles/node/vars/main.yml b/lib/ansible/roles/node/vars/main.yml index d4d686ad..95713498 100644 --- a/lib/ansible/roles/node/vars/main.yml +++ b/lib/ansible/roles/node/vars/main.yml @@ -1,4 +1,6 @@ --- +node_modules: + - bower node_repos: - deb https://deb.nodesource.com/node_4.x trusty main - deb-src https://deb.nodesource.com/node_4.x trusty main diff --git a/lib/yeoman/templates/lib/capistrano/deploy.rb b/lib/yeoman/templates/lib/capistrano/deploy.rb index e2b4439b..149319a8 100644 --- a/lib/yeoman/templates/lib/capistrano/deploy.rb +++ b/lib/yeoman/templates/lib/capistrano/deploy.rb @@ -23,6 +23,16 @@ execute "cd #{release_path} && npm install --production" end end + after :updated, :bower_install do + on roles(:web) do + within release_path do + bower_exists = test "[ -f ./bower.json ]" + if bower_exists + execute "bower install" + end + end + end + end after :finished, :launch_browser do subdomain = fetch(:stage).to_s branch = fetch(:branch).to_s From 982b5e37682d04246e3db2b27cb73d3d6cc20c4f Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sun, 20 Nov 2016 13:57:23 -0800 Subject: [PATCH 53/66] Updated generator's dep checking to use semver for minimum versions --- lib/yeoman/index.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/yeoman/index.js b/lib/yeoman/index.js index 820be019..4e742c76 100644 --- a/lib/yeoman/index.js +++ b/lib/yeoman/index.js @@ -47,10 +47,11 @@ var WordpressGenerator = yeoman.Base.extend({ // binaries, args, and callbacks for determining dependencies var deps = [ - {bin: 'ansible', args: ['--version'], test: /ansible\s+2[.]/}, - {bin: 'bundler', args: ['--version']}, - {bin: 'npm', args: ['--version']}, - {bin: 'sshpass', args: ['-V']}, + { bin: 'ansible', args: ['--version'], test: function (out) { var ver = out.match(/ansible ((?:\d+[.]){2}\d+)/)[1]; return semver.satisfies(ver, '>=2.0'); } }, + { bin: 'bundler', args: ['--version'] }, + { bin: 'npm', args: ['--version'] }, + { bin: 'sshpass', args: ['-V'] }, + { bin: 'yo', args: ['--version'], test: function (out) { var ver = out.match(/((?:\d+[.]){2}\d+)/)[1]; return semver.satisfies(ver, '>=1.8'); } }, ]; var done = this.async(); @@ -69,7 +70,7 @@ var WordpressGenerator = yeoman.Base.extend({ output = output.replace(/\s+/g, ' '); // warn (rather than bail) on dep with insufficient version - if (!dependency.test.test(output)) { + if (!dependency.test(output)) { this.log.skip('Warning: found ' + chalk.green(dependency.bin) + ', with insufficient version: ' + chalk.red(output)); } } From a515243df2c3bd4d057a3d6b362eb9b6de70a14b Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sun, 20 Nov 2016 14:01:02 -0800 Subject: [PATCH 54/66] Globally install yeoman 1.8 (for CI) --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 58f23709..d44eb2e2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,6 +38,8 @@ before_install: - node --version - npm --version - nvm --version + - npm install -g yo@1.8.0 + - yo --version - npm install # python setup (for ansible) - sudo pip install urllib3 pyopenssl ndg-httpsclient pyasn1 From 8694e9615993b2ccbd2d5a1787f0ca4cfbe4270f Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sun, 20 Nov 2016 14:05:56 -0800 Subject: [PATCH 55/66] Test yeoman lowest possible version compatibility" --- .travis.yml | 2 +- lib/yeoman/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index d44eb2e2..0c55196d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,7 +38,7 @@ before_install: - node --version - npm --version - nvm --version - - npm install -g yo@1.8.0 + - npm install -g yo@1.7.1 - yo --version - npm install # python setup (for ansible) diff --git a/lib/yeoman/index.js b/lib/yeoman/index.js index 4e742c76..e7c46625 100644 --- a/lib/yeoman/index.js +++ b/lib/yeoman/index.js @@ -51,7 +51,7 @@ var WordpressGenerator = yeoman.Base.extend({ { bin: 'bundler', args: ['--version'] }, { bin: 'npm', args: ['--version'] }, { bin: 'sshpass', args: ['-V'] }, - { bin: 'yo', args: ['--version'], test: function (out) { var ver = out.match(/((?:\d+[.]){2}\d+)/)[1]; return semver.satisfies(ver, '>=1.8'); } }, + { bin: 'yo', args: ['--version'], test: function (out) { var ver = out.match(/((?:\d+[.]){2}\d+)/)[1]; return semver.satisfies(ver, '>=1.7.1'); } }, ]; var done = this.async(); From af252b54b8273cdd22cc195efa565ca91b7d31f5 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sun, 20 Nov 2016 14:23:08 -0800 Subject: [PATCH 56/66] Adding (commented out) build matrix entry for ansible 2.0 Note: we're skipping 2.0 in the CI environment because Travis' trusty image comes bundled with python 2.7.6, which lacks baked-in SNI support --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 0c55196d..46f9fca8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,6 +22,7 @@ env: # DEBUG: "nightmare:*,electron:*" - DISPLAY: ":99.0" matrix: + # ANSIBLE_VERSION: "2.0.2" - ANSIBLE_VERSION: "2.1.3" - ANSIBLE_VERSION: "2.2.0" before_install: From e4f64ab8522b11f3073c4034cc0ceb2d5b3c12cc Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sun, 20 Nov 2016 15:04:45 -0800 Subject: [PATCH 57/66] Parse existing playbooks and group vars as yaml, in the generator --- lib/yeoman/index.js | 42 +++++++++++++++++++------------ lib/yeoman/templates/package.json | 2 +- package.json | 3 ++- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/lib/yeoman/index.js b/lib/yeoman/index.js index e7c46625..4a00ddca 100644 --- a/lib/yeoman/index.js +++ b/lib/yeoman/index.js @@ -9,6 +9,7 @@ var path = require('path'); var request = require('request'); var semver = require('semver'); var util = require('util'); +var yaml = require('js-yaml'); var yeoman = require('yeoman-generator'); var WordpressGenerator = yeoman.Base.extend({ @@ -135,8 +136,12 @@ var WordpressGenerator = yeoman.Base.extend({ var defaultSsl = true; try { - var provisionYml = this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'provision.yml')); - defaultSsl = !!provisionYml.match(/^\s*-\s+pound/m); + var provisionYml = yaml.safeLoad(this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'provision.yml'))); + if (provisionYml[0].roles.indexOf('pound') == -1) { + if (!provisionYml[0].roles.find(function(el) { return el.hasOwnProperty('role') && el.role == 'pound'; })) { + defaultSsl = false; + } + } } catch(e) {}; var choices = [ @@ -267,10 +272,9 @@ var WordpressGenerator = yeoman.Base.extend({ ]; var existing = function() { try { - var match = this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'group_vars', 'all')) - .match(/www[ ]*:[ ]*(true)/i); + var groupVars = yaml.safeLoad(this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'group_vars', 'all'))); - return match[1]; + return groupVars.hasOwnProperty('www') && !!groupVars.www; } catch(e) {}; }.bind(this); @@ -290,10 +294,11 @@ var WordpressGenerator = yeoman.Base.extend({ promptForNewrelic: function() { var existing = function() { try { - var match = this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'group_vars', 'all')) - .match(/newrelic[ ]*:[ ]*(?:'|")?([^'"\s]+)/i); + var groupVars = yaml.safeLoad(this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'group_vars', 'all'))); - return match[1]; + if (groupVars.hasOwnProperty('monitoring') && groupVars.monitoring.hasOwnProperty('newrelic')) { + return groupVars.monitoring.newrelic; + } } catch(e) {}; }.bind(this); @@ -311,10 +316,10 @@ var WordpressGenerator = yeoman.Base.extend({ promptForDatadog: function() { var existing = function() { try { - var match = this.rs.read(path.join(this.env.cwd, 'lib', 'ansible', 'group_vars', 'all')) - .match(/datadog_api_key[ ]*:[ ]*(?:'|")?([^'"\s]+)/i); - - return match[1]; + var groupVars = yaml.safeLoad(this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'group_vars', 'all'))); + if (groupVars.hasOwnProperty('datadog_api_key')) { + return groupVars.datadog_api_key; + } } catch(e) {}; }.bind(this); @@ -331,12 +336,17 @@ var WordpressGenerator = yeoman.Base.extend({ promptForRoles: function() { try { - var provisionYml = this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'provision.yml')); + var provisionYml = yaml.safeLoad(this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'provision.yml'))); WordpressGenerator.roles.forEach(function (role, index) { - var regex = new RegExp('^\\s*-\\s+' + role.value.split(' ')[0], 'm'); - - if (!regex.exec(provisionYml)) { + var roleName = role.value.split(' ')[0]; + if (provisionYml[0].roles.indexOf(roleName) != -1) { + WordpressGenerator.roles[index].checked = true; + } + else if (provisionYml[0].roles.find(function(el) { return el.hasOwnProperty('role') && el.role == roleName; })) { + WordpressGenerator.roles[index].checked = true; + } + else { WordpressGenerator.roles[index].checked = false; } }); diff --git a/lib/yeoman/templates/package.json b/lib/yeoman/templates/package.json index ddd5f27e..6dbbd332 100644 --- a/lib/yeoman/templates/package.json +++ b/lib/yeoman/templates/package.json @@ -5,7 +5,7 @@ "node": ">=4" }, "dependencies": { - "evolution-wordpress": "~v2.0.0-alpha" + "evolution-wordpress": "~2.0.0-alpha" }, "scripts": { "postinstall": "node node_modules/evolution-wordpress/bin/postinstall" diff --git a/package.json b/package.json index 00ab1dd1..f2e474ed 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "private": false, "name": "evolution-wordpress", - "version": "v2.0.0-alpha", + "version": "2.0.0-alpha", "description": "Libraries for a multi-staged WordPress workflow with Vagrant", "main": "lib/yeoman/index.js", "engines": { @@ -20,6 +20,7 @@ "replace": "^0.3.0", "yauzl": "^2.6.0", "semver": "^5.1.0", + "js-yaml":"^3.7.0", "glob": "^7.1.1" }, "devDependencies": { From 860f3ccbf622cee294a99c42cec842135d206a65 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Sun, 20 Nov 2016 17:45:15 -0800 Subject: [PATCH 58/66] Added upgrade notice for 1.x sites --- lib/yeoman/index.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/lib/yeoman/index.js b/lib/yeoman/index.js index 4a00ddca..3921668a 100644 --- a/lib/yeoman/index.js +++ b/lib/yeoman/index.js @@ -41,6 +41,40 @@ var WordpressGenerator = yeoman.Base.extend({ this.log.writeln(message); }, + upgradeNotice: function() { + var upgradeVersion; + + // get existing version from group vars (if available) + try { + var groupVars = yaml.safeLoad(this.fs.read(path.join(this.env.cwd, 'lib', 'ansible', 'group_vars', 'all'))); + + if (groupVars.hasOwnProperty('evolve_version')) { + upgradeVersion = groupVars.evolve_version; + } + } catch(e) {}; + + // failing that, get existing version from bower json (if available) + if (!upgradeVersion) { + try { + var bowerJson = this.fs.readJSON(path.join(this.env.cwd, 'bower.json')); + + if (bowerJson.dependencies.hasOwnProperty('evolution-wordpress')) { + upgradeVersion = bowerContents.dependencies['evolution-wordpress']; + } + } catch (e) {}; + } + + // show upgrade notice for evolution 1.x sites + if (upgradeVersion && !semver.satisfies(upgradeVersion, '2.x')) { + this.log([ + chalk.bgRed.bold.underline('!!! Evolution 2.0 Upgrade Notice !!!'), + chalk.green('You are regenerating an Evolution 1.0 site with ' + chalk.bold('significant and potentially breaking changes') + '...'), + chalk.yellow.bold('After regenerating this site, ' + chalk.underline('you MUST re-provision any existing servers before deployment') + ' or they may not continue to function!'), + '', + ].join("\n")); + } + }, + checkDeps: function() { if(process.env.CI) { return true; From 0f50afaedd1f3fa58803b1f5be865802594b1858 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Mon, 21 Nov 2016 00:04:43 -0800 Subject: [PATCH 59/66] Changed newrelic groupvar name --- lib/ansible/roles/newrelic/tasks/main.yml | 4 ++-- lib/yeoman/index.js | 4 ++++ lib/yeoman/templates/lib/ansible/group_vars/all | 8 +++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/ansible/roles/newrelic/tasks/main.yml b/lib/ansible/roles/newrelic/tasks/main.yml index 4d936dfb..79511f80 100644 --- a/lib/ansible/roles/newrelic/tasks/main.yml +++ b/lib/ansible/roles/newrelic/tasks/main.yml @@ -19,10 +19,10 @@ sudo: yes with_dict: newrelic.appname: "{{ domain }} ({{ stage }})" - newrelic.license: "{{ monitoring.newrelic }}" + newrelic.license: "{{ newrelic_api_key }}" notify: restart apache - name: Configure and start sys monitor - command: nrsysmond-config --set license_key={{ monitoring.newrelic }} + command: nrsysmond-config --set license_key={{ newrelic_api_key }} sudo: yes notify: restart newrelic-sysmond diff --git a/lib/yeoman/index.js b/lib/yeoman/index.js index 3921668a..5a4dce32 100644 --- a/lib/yeoman/index.js +++ b/lib/yeoman/index.js @@ -333,6 +333,10 @@ var WordpressGenerator = yeoman.Base.extend({ if (groupVars.hasOwnProperty('monitoring') && groupVars.monitoring.hasOwnProperty('newrelic')) { return groupVars.monitoring.newrelic; } + + if (groupVars.hasOwnProperty('newrelic_api_key')) { + return groupVars.newrelic_api_key; + } } catch(e) {}; }.bind(this); diff --git a/lib/yeoman/templates/lib/ansible/group_vars/all b/lib/yeoman/templates/lib/ansible/group_vars/all index 81e566ae..33984638 100644 --- a/lib/yeoman/templates/lib/ansible/group_vars/all +++ b/lib/yeoman/templates/lib/ansible/group_vars/all @@ -4,17 +4,15 @@ wp_version: <%- props.wordpress %> domain: <%- props.domain %> www: <%- props.www %> -monitoring: - newrelic: '<%- props.newrelic %>' - mysql: name: <%- props.DB_NAME %> user: <%- props.DB_USER %> password: <%- props.DB_PASSWORD %> host: <%- props.DB_HOST %> -<% if (props.datadog) { %>datadog_api_key: '<%- props.datadog %>'<% } %> - +<% if (props.newrelic) { %>newrelic_api_key: '<%- props.newrelic %>' +<% } %><% if (props.datadog) { %>datadog_api_key: '<%- props.datadog %>' +<% } %> # php__memory_limit: # apache__start_servers: From 573866cbfae775e33e8e6fe3cf6da5a6c7acd930 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Mon, 21 Nov 2016 00:29:09 -0800 Subject: [PATCH 60/66] Replaced sudo with become, to address deprecation warnings --- .../roles/apache-prefork/tasks/main.yml | 2 +- lib/ansible/roles/apache/handlers/main.yml | 2 +- lib/ansible/roles/apache/tasks/main.yml | 28 +++++++++---------- lib/ansible/roles/awstats/tasks/vagrant.yml | 14 +++++----- lib/ansible/roles/cleanup/tasks/main.yml | 6 ++-- lib/ansible/roles/common/tasks/main.yml | 20 ++++++------- lib/ansible/roles/common/tasks/swap.yml | 16 +++++------ lib/ansible/roles/debug/tasks/main.yml | 2 +- lib/ansible/roles/firewall/handlers/main.yml | 2 +- lib/ansible/roles/firewall/tasks/main.yml | 12 ++++---- lib/ansible/roles/mail/tasks/main.yml | 6 ++-- lib/ansible/roles/mysql/tasks/main.yml | 10 +++---- lib/ansible/roles/newrelic/handlers/main.yml | 2 +- lib/ansible/roles/newrelic/tasks/main.yml | 10 +++---- lib/ansible/roles/node/tasks/main.yml | 12 ++++---- .../roles/php-hardened/tasks/build.yml | 12 ++++---- lib/ansible/roles/php-hardened/tasks/main.yml | 2 +- .../roles/php-hardened/tasks/suhosin.yml | 6 ++-- lib/ansible/roles/php/tasks/main.yml | 12 ++++---- lib/ansible/roles/pound/handlers/main.yml | 2 +- lib/ansible/roles/pound/tasks/main.yml | 16 +++++------ lib/ansible/roles/prepare/tasks/main.yml | 2 +- lib/ansible/roles/user/tasks/main.yml | 18 ++++++------ lib/ansible/roles/varnish/handlers/main.yml | 2 +- lib/ansible/roles/varnish/tasks/main.yml | 20 ++++++------- lib/ansible/roles/wp-cli/tasks/main.yml | 2 +- 26 files changed, 119 insertions(+), 119 deletions(-) diff --git a/lib/ansible/roles/apache-prefork/tasks/main.yml b/lib/ansible/roles/apache-prefork/tasks/main.yml index f7dcc845..c8fd2b98 100644 --- a/lib/ansible/roles/apache-prefork/tasks/main.yml +++ b/lib/ansible/roles/apache-prefork/tasks/main.yml @@ -2,4 +2,4 @@ - name: Override apache prefork module config template: src=prefork.conf dest=/etc/apache2/mods-available/mpm_prefork.conf backup=yes mode=0644 when: apache_version.stdout == '2.4' - sudo: yes + become: true diff --git a/lib/ansible/roles/apache/handlers/main.yml b/lib/ansible/roles/apache/handlers/main.yml index c30bee84..d5eef80f 100644 --- a/lib/ansible/roles/apache/handlers/main.yml +++ b/lib/ansible/roles/apache/handlers/main.yml @@ -1,4 +1,4 @@ --- - name: restart apache service: name=apache2 state=restarted - sudo: true + become: true diff --git a/lib/ansible/roles/apache/tasks/main.yml b/lib/ansible/roles/apache/tasks/main.yml index 12d250cd..904dd805 100644 --- a/lib/ansible/roles/apache/tasks/main.yml +++ b/lib/ansible/roles/apache/tasks/main.yml @@ -2,18 +2,18 @@ - name: Install Apache packages apt: pkg={{ item }} state=present with_items: "{{ apache_packages }}" - sudo: yes + become: true - name: Enable Apache modules apache2_module: name={{ item }} state=present with_items: "{{ apache_modules }}" - sudo: yes + become: true notify: restart apache - name: Disable Apache modules apache2_module: name={{ item }} state=absent with_items: "{{ apache_disabled_modules }}" - sudo: yes + become: true notify: restart apache - name: Register Apache major/minor version @@ -24,42 +24,42 @@ - name: Configure apache log rotation copy: src=logrotate-apache dest=/etc/logrotate.d/apache2 owner=root group=root mode=644 - sudo: yes + become: true - name: Configure Apache canonical server name template: src=canonical dest=/etc/apache2/conf-available/canonical-servername.conf mode=0644 when: apache_version.stdout == '2.4' - sudo: true + become: true - name: Enable canonical config command: a2enconf canonical-servername notify: restart apache when: apache_version.stdout == '2.4' - sudo: yes + become: true - name: Ensure Apache `Listen` is 80 lineinfile: regexp='^Listen' line='Listen 80' dest=/etc/apache2/ports.conf backup=yes notify: restart apache - sudo: yes + become: true - name: Ensure existing Varnish installs won't cause port conflict on boot lineinfile: regexp='^START=' line='START=no' dest=/etc/default/varnish backup=no ignore_errors: true - sudo: yes + become: true - name: Ensure pristine mpm_prefork directives restore: path=/etc/apache2/mods-available/mpm_prefork.conf which=oldest backup=no fail_on_missing=no when: apache_version.stdout == '2.4' - sudo: yes + become: true - name: Change ownership of /var/www to deploy file: path=/var/www state=directory owner=deploy group=deploy - sudo: yes + become: true - shell: (cd /etc/apache2/sites-enabled/ && ls -1 000-default*) register: apache_default_vhost ignore_errors: true - sudo: yes + become: true - set_fact: wordpress__xmlrpc_allow: false @@ -73,18 +73,18 @@ command: a2dissite {{ apache_default_vhost.stdout }} removes=/etc/apache2/sites-enabled/{{ apache_default_vhost.stdout }} notify: restart apache when: apache_default_vhost.stdout != '' - sudo: yes + become: true - name: Create apache vhosts template: src=virtualhost dest=/etc/apache2/sites-available/{{ "%03d" | format(item.key_1) }}-{{ item.value }}.{{ domain }}.conf mode=0644 with_nested_dict: "{{ apache_vhosts }}" # see ansible/ansible#9563 when: item.key_0 == stage notify: restart apache - sudo: true + become: true - name: Enable apache vhosts command: a2ensite {{ "%03d" | format(item.key_1) }}-{{ item.value }}.{{ domain }}.conf with_nested_dict: "{{ apache_vhosts }}" when: item.key_0 == stage notify: restart apache - sudo: true + become: true diff --git a/lib/ansible/roles/awstats/tasks/vagrant.yml b/lib/ansible/roles/awstats/tasks/vagrant.yml index 134801f5..018aa842 100644 --- a/lib/ansible/roles/awstats/tasks/vagrant.yml +++ b/lib/ansible/roles/awstats/tasks/vagrant.yml @@ -1,27 +1,27 @@ --- - name: Install awstats apt: pkg=awstats state=present - sudo: yes + become: true - name: Use logfile synced down from remote lineinfile: regexp='^LogFile=' line='LogFile="/tmp/apache2-remote-access.log"' dest=/etc/awstats/awstats.conf - sudo: yes + become: true - name: Use combined log format lineinfile: regexp='^LogFormat=' line='LogFormat=1' dest=/etc/awstats/awstats.conf - sudo: yes + become: true - name: Set primary site domain lineinfile: regexp='^SiteDomain=' line='SiteDomain="{{ domain }}"' dest=/etc/awstats/awstats.conf - sudo: yes + become: true - name: Set host aliases lineinfile: regexp='^HostAliases=' line='HostAliases="localhost 127.0.0.1 REGEX[^.*\.{{ domain | replace(".", "\\.") }}$]' dest=/etc/awstats/awstats.conf - sudo: yes + become: true - name: Enable Apache cgi module apache2_module: name=cgi state=present - sudo: yes + become: true notify: restart apache - name: Update vhosts for awstats web ui @@ -29,4 +29,4 @@ with_nested_dict: "{{ apache_vhosts }}" # see ansible/ansible#9563 when: item.key_0 == stage notify: restart apache - sudo: true + become: true diff --git a/lib/ansible/roles/cleanup/tasks/main.yml b/lib/ansible/roles/cleanup/tasks/main.yml index e04a00a5..114dc4a8 100644 --- a/lib/ansible/roles/cleanup/tasks/main.yml +++ b/lib/ansible/roles/cleanup/tasks/main.yml @@ -4,7 +4,7 @@ args: creates: /etc/cron.hourly/logrotate removes: /etc/cron.daily/logrotate - sudo: yes + become: true - name: Set up wpcron via user-level crontab cron: @@ -14,8 +14,8 @@ job: "cd {{item.value}} && /usr/local/bin/wp core is-installed --path=$PWD --url='http://{{stage}}.{{domain}}/' && /usr/local/bin/wp cron event run --all --quiet --path=$PWD --url='http://{{stage}}.{{domain}}/'" with_dict: "{{ wp_cron_path }}" when: item.key == stage - sudo: yes + become: true - name: Generate init.d for installed evolution services template: src=evolution-init-d dest=/etc/init.d/evolution-wordpress mode=0755 - sudo: yes + become: true diff --git a/lib/ansible/roles/common/tasks/main.yml b/lib/ansible/roles/common/tasks/main.yml index 6c47dcc0..bbef1c04 100644 --- a/lib/ansible/roles/common/tasks/main.yml +++ b/lib/ansible/roles/common/tasks/main.yml @@ -15,11 +15,11 @@ - name: Update nameservers in resolv.conf replace: dest=/etc/resolv.conf regexp="(nameserver [\w\d.:]+\n?)+" replace="nameserver 8.8.8.8\nnameserver 8.8.4.4\n\1" - sudo: yes + become: true - name: Update nameservers in dhclient.conf lineinfile: dest=/etc/dhcp/dhclient.conf regexp="^#?prepend domain-name-servers " line="prepend domain-name-servers 8.8.8.8, 8.8.4.4;" - sudo: yes + become: true when: dynamic_resolv.stdout != "" # see evolution/wordpress#126 @@ -28,13 +28,13 @@ - name: Copy purging script to remote copy: src=/tmp/purge-kernels.py dest=/tmp/purge-kernels.py force=yes mode=0755 - sudo: yes + become: true - name: Purge kernels as necessary command: /tmp/purge-kernels.py register: purgekernels_result ignore_errors: yes - sudo: yes + become: true when: not lookup('env','CI') - name: Remove kernel purging script in tmp (from control) @@ -45,30 +45,30 @@ - name: Update apt cache apt: update_cache=yes cache_valid_time="{{ 60 * 60 * 24 }}" - sudo: yes + become: true - name: Autoremove unused packages shell: DEBIAN_FRONTEND=noninteractive apt-get -y autoremove - sudo: yes + become: true - name: Install common packages apt: pkg={{ item }} state=present with_items: "{{ common_packages }}" - sudo: yes + become: true - name: Update `hostname` hostname: name="{{ new_hostname }}" - sudo: yes + become: true when: old_hostname != new_hostname - name: Update /etc/hosts replace: dest=/etc/hosts backup=yes regexp={{ old_hostname | replace(".", "[.]") }} replace={{ new_hostname }} - sudo: yes + become: true when: old_hostname != new_hostname - name: Configure logrotate for evolution logs copy: src=logrotate dest=/etc/logrotate.d/evolution mode=0644 - sudo: yes + become: true - name: Test for git protocol (git://) connectivity command: curl -v -m 10 http://github.com:9418/ diff --git a/lib/ansible/roles/common/tasks/swap.yml b/lib/ansible/roles/common/tasks/swap.yml index 77f2c8b2..d80b7d0b 100644 --- a/lib/ansible/roles/common/tasks/swap.yml +++ b/lib/ansible/roles/common/tasks/swap.yml @@ -18,32 +18,32 @@ - name: Write swapfile command: fallocate -l {{swapfile_size_mb.stdout}}M {{swap__path}} - sudo: yes + become: true - name: Set permissions file: path={{swap__path}} mode=600 owner=root group=root - sudo: yes + become: true - name: Create swapfile command: mkswap {{swap__path}} - sudo: yes + become: true - name: Enable swapfile command: swapon {{swap__path}} - sudo: yes + become: true - name: Add swapfile to /etc/fstab lineinfile: dest=/etc/fstab state=present line="{{ swap__path }} none swap sw 0 0" - sudo: yes + become: true - name: Configure vm.swappiness lineinfile: dest=/etc/sysctl.conf line="vm.swappiness = {{ swap__swappiness }}" regexp="^vm.swappiness\s*?=" state=present - sudo: yes + become: true - name: Configure vm.vfs_cache_pressure lineinfile: dest=/etc/sysctl.conf line="vm.vfs_cache_pressure = {{ swap__vfs_cache_pressure }}" regexp="^vm.vfs_cache_pressure\s*?=" state=present - sudo: yes + become: true - name: Reload sysctl command: sysctl -p - sudo: yes + become: true diff --git a/lib/ansible/roles/debug/tasks/main.yml b/lib/ansible/roles/debug/tasks/main.yml index a5befbc3..11c80eb1 100644 --- a/lib/ansible/roles/debug/tasks/main.yml +++ b/lib/ansible/roles/debug/tasks/main.yml @@ -2,4 +2,4 @@ - name: Install debug packages apt: pkg={{ item }} state=present with_items: "{{ debug_packages }}" - sudo: yes + become: true diff --git a/lib/ansible/roles/firewall/handlers/main.yml b/lib/ansible/roles/firewall/handlers/main.yml index 9402e4c0..ed1e597d 100644 --- a/lib/ansible/roles/firewall/handlers/main.yml +++ b/lib/ansible/roles/firewall/handlers/main.yml @@ -1,4 +1,4 @@ --- - name: restart firewall service: name=iptables-persistent state=restarted - sudo: yes + become: true diff --git a/lib/ansible/roles/firewall/tasks/main.yml b/lib/ansible/roles/firewall/tasks/main.yml index e1b1015b..9350bfca 100644 --- a/lib/ansible/roles/firewall/tasks/main.yml +++ b/lib/ansible/roles/firewall/tasks/main.yml @@ -3,22 +3,22 @@ apt: pkg=iptables-persistent state=latest update_cache=yes register: iptables_attempted ignore_errors: yes - sudo: yes + become: true # See https://forum.linode.com/viewtopic.php?t=9070&p=58732 - name: Postinst workaround for iptables-persistent replace: dest=/var/lib/dpkg/info/iptables-persistent.postinst regexp='^(\s*?modprobe -q ip6?table_filter\s*?)$' replace='\1 || true' when: iptables_attempted | failed - sudo: yes + become: true - name: Install firewall packages apt: pkg={{ item }} state=present with_items: "{{ firewall_packages }}" - sudo: yes + become: true - name: Install iptables init script + rulesets copy: src={{ item }} dest=/etc/{{ item }} mode=0644 backup=yes - sudo: yes + become: true with_items: - init.d/iptables-persistent - iptables/rules.v4 @@ -26,7 +26,7 @@ - name: Create iptables + fail2ban configs template: src={{ item }} dest=/etc/{{ item }} mode=0644 - sudo: yes + become: true with_items: - default/iptables-persistent.conf - fail2ban/jail.local @@ -34,4 +34,4 @@ - name: Ensure iptables init script is executable file: path=/etc/init.d/iptables-persistent mode=0755 notify: restart firewall - sudo: yes + become: true diff --git a/lib/ansible/roles/mail/tasks/main.yml b/lib/ansible/roles/mail/tasks/main.yml index 8b63ccfb..074bfa13 100644 --- a/lib/ansible/roles/mail/tasks/main.yml +++ b/lib/ansible/roles/mail/tasks/main.yml @@ -1,12 +1,12 @@ --- - name: Install mail package apt: pkg=postfix state=present - sudo: yes + become: true - name: Generate /etc/aliases template: src=aliases dest=/etc/aliases mode=0644 - sudo: yes + become: true - name: Update mail aliases command: newaliases - sudo: yes + become: true diff --git a/lib/ansible/roles/mysql/tasks/main.yml b/lib/ansible/roles/mysql/tasks/main.yml index 1b81d781..320297a0 100644 --- a/lib/ansible/roles/mysql/tasks/main.yml +++ b/lib/ansible/roles/mysql/tasks/main.yml @@ -2,20 +2,20 @@ - name: Install MySQL packages apt: pkg={{ item }} state=present with_items: "{{ mysql_packages }}" - sudo: yes + become: true - name: Update my.conf's bind-address lineinfile: dest=/etc/mysql/my.cnf backup=yes regexp=^bind-address line='bind-address = 0.0.0.0' - sudo: yes + become: true - name: Restart mysql service: name=mysql state=restarted - sudo: yes + become: true - name: Create MySQL database mysql_db: name="{{ mysql.name }}_{{ stage }}" - sudo: yes + become: true - name: Create MySQL user mysql_user: name={{ mysql.user }} host={{ mysql.host }} password={{ mysql.password }} priv="{{ mysql.name }}_{{ stage }}.*:GRANT,ALL" append_privs=yes - sudo: yes + become: true diff --git a/lib/ansible/roles/newrelic/handlers/main.yml b/lib/ansible/roles/newrelic/handlers/main.yml index d1bb76d9..714583fa 100644 --- a/lib/ansible/roles/newrelic/handlers/main.yml +++ b/lib/ansible/roles/newrelic/handlers/main.yml @@ -1,4 +1,4 @@ --- - name: restart newrelic-sysmond service: name=newrelic-sysmond state=restarted - sudo: true + become: true diff --git a/lib/ansible/roles/newrelic/tasks/main.yml b/lib/ansible/roles/newrelic/tasks/main.yml index 79511f80..8261be27 100644 --- a/lib/ansible/roles/newrelic/tasks/main.yml +++ b/lib/ansible/roles/newrelic/tasks/main.yml @@ -1,22 +1,22 @@ --- - name: Install repository key apt_key: url=https://download.newrelic.com/548C16BF.gpg state=present - sudo: yes + become: true - name: Configure repository source list apt_repository: repo='deb http://apt.newrelic.com/debian/ newrelic non-free' state=present - sudo: yes + become: true - name: Install PHP agent and sys monitor apt: name={{ item }} state=latest update_cache=yes - sudo: yes + become: true with_items: - newrelic-php5 - newrelic-sysmond - name: Configure PHP agent license key and app name lineinfile: dest={{ php_conf_path }}/newrelic.ini regexp="^{{ item.key }}" line="{{ item.key }} = '{{ item.value }}'" - sudo: yes + become: true with_dict: newrelic.appname: "{{ domain }} ({{ stage }})" newrelic.license: "{{ newrelic_api_key }}" @@ -24,5 +24,5 @@ - name: Configure and start sys monitor command: nrsysmond-config --set license_key={{ newrelic_api_key }} - sudo: yes + become: true notify: restart newrelic-sysmond diff --git a/lib/ansible/roles/node/tasks/main.yml b/lib/ansible/roles/node/tasks/main.yml index 62482383..a821d543 100644 --- a/lib/ansible/roles/node/tasks/main.yml +++ b/lib/ansible/roles/node/tasks/main.yml @@ -1,19 +1,19 @@ --- - name: Remove old node repository if necessary apt_repository: repo='ppa:chris-lea/node.js' state=absent - sudo: yes + become: true - name: Ensure removal of old node source lists shell: rm -f /etc/apt/sources.list.d/chris-lea-node_js-*.list ignore_errors: true - sudo: yes + become: true - name: Fetch Nodesource apt key (from control) local_action: get_url dest=/tmp/ns4x.gpg.key url=https://deb.nodesource.com/gpgkey/nodesource.gpg.key force=yes - name: Add Nodesource apt key apt_key: data="{{ lookup('file', '/tmp/ns4x.gpg.key') }}" state=present - sudo: yes + become: true - name: Remove Nodesource apt key in tmp (from control) local_action: file dest=/tmp/ns4x.gpg.key state=absent @@ -21,13 +21,13 @@ - name: Add Nodesource 4.x repos apt_repository: repo={{item}} state=present update_cache=yes with_items: "{{ node_repos }}" - sudo: yes + become: true - name: Install node apt: pkg=nodejs state=present - sudo: yes + become: true - name: Install global node modules command: npm install -g {{ item }} with_items: "{{ node_modules }}" - sudo: yes + become: true diff --git a/lib/ansible/roles/php-hardened/tasks/build.yml b/lib/ansible/roles/php-hardened/tasks/build.yml index 37e33755..d0727ff9 100644 --- a/lib/ansible/roles/php-hardened/tasks/build.yml +++ b/lib/ansible/roles/php-hardened/tasks/build.yml @@ -1,12 +1,12 @@ --- - name: Fetch stable source get_url: url={{ suhosin.url }} dest=/tmp/src-suhosin.tar.gz validate_certs=False - sudo: yes + become: true - name: Hash source for checksum shell: sha1sum /tmp/src-suhosin.tar.gz register: suhosin_shahash - sudo: yes + become: true - debug: var=suhosin_shahash.stdout @@ -15,17 +15,17 @@ - name: Expand source package unarchive: src=/tmp/src-suhosin.tar.gz dest=/tmp/ copy=no - sudo: yes + become: true - shell: ls -1d /tmp/suhosin* register: suhosin_srcdir - sudo: yes + become: true - debug: var=suhosin_srcdir.stdout - name: Compile and install extension command: "{{ item }} chdir={{ suhosin_srcdir.stdout }}" - sudo: yes + become: true with_items: - phpize - ./configure @@ -34,4 +34,4 @@ - name: Clean up after ourselves shell: rm -rf /tmp/*suhosin* - sudo: yes + become: true diff --git a/lib/ansible/roles/php-hardened/tasks/main.yml b/lib/ansible/roles/php-hardened/tasks/main.yml index e402abd6..e6b840f3 100644 --- a/lib/ansible/roles/php-hardened/tasks/main.yml +++ b/lib/ansible/roles/php-hardened/tasks/main.yml @@ -1,6 +1,6 @@ --- - name: Disable allow_url_fopen lineinfile: dest=/etc/php5/apache2/php.ini backup=yes regexp='^[;# ]*allow_url_fopen' line='allow_url_fopen = Off' - sudo: yes + become: true - include: suhosin.yml diff --git a/lib/ansible/roles/php-hardened/tasks/suhosin.yml b/lib/ansible/roles/php-hardened/tasks/suhosin.yml index e58fbe2a..0f6a6bf6 100644 --- a/lib/ansible/roles/php-hardened/tasks/suhosin.yml +++ b/lib/ansible/roles/php-hardened/tasks/suhosin.yml @@ -1,7 +1,7 @@ --- - name: Install apg (for cryptkeys) apt: name=apg state=present - sudo: yes + become: true - name: Generate session cryptkey shell: apg -m 32 | sed 's/[^a-zA-Z0-9]//g' @@ -26,9 +26,9 @@ - name: Generate ini config for extension template: src=suhosin.ini.j2 dest={{ suhosin.ini }} - sudo: yes + become: true - name: Enable extension command: php5enmod suhosin - sudo: yes + become: true notify: restart apache diff --git a/lib/ansible/roles/php/tasks/main.yml b/lib/ansible/roles/php/tasks/main.yml index 5903c062..f4457dff 100644 --- a/lib/ansible/roles/php/tasks/main.yml +++ b/lib/ansible/roles/php/tasks/main.yml @@ -2,19 +2,19 @@ - name: Install PHP packages apt: pkg={{ item }} with_items: "{{ php_packages }}" - sudo: yes + become: true - name: Install PECL packages command: pecl install {{ item if item is string else item.name + '-' + item.version }} creates={{ php_conf_path }}/{{ item if item is string else item.name }}.ini with_items: "{{ pecl_packages }}" - sudo: yes + become: true - name: Enable PECL packages lineinfile: line="extension={{ item if item is string else item.name }}.so" dest="{{ php_conf_path }}/{{ item if item is string else item.name }}.ini" create=yes with_items: "{{ pecl_packages }}" - sudo: yes + become: true - name: Calculate PHP memory_limit command: echo "{{ 256 if ansible_memtotal_mb > 2048 else 128 }}" @@ -24,12 +24,12 @@ - name: Update php.ini's date.timezone lineinfile: dest=/etc/php5/apache2/php.ini backup=yes regexp='^[;# ]*date\.timezone' line='date.timezone = "America/Chicago"' - sudo: yes + become: true - name: Update php.ini's memory_limit lineinfile: dest=/etc/php5/apache2/php.ini backup=yes regexp='^[;# ]*memory_limit' line='memory_limit = {{ calc_php_memory_limit.stdout if calc_php_memory_limit.stdout is defined else php__memory_limit }}M' - sudo: yes + become: true - name: Update php.ini's upload_max_filesize lineinfile: dest=/etc/php5/apache2/php.ini backup=yes regexp='^[;# ]*upload_max_filesize' line='upload_max_filesize = 16M' - sudo: yes + become: true diff --git a/lib/ansible/roles/pound/handlers/main.yml b/lib/ansible/roles/pound/handlers/main.yml index e1a41b2a..bbd62f03 100644 --- a/lib/ansible/roles/pound/handlers/main.yml +++ b/lib/ansible/roles/pound/handlers/main.yml @@ -1,4 +1,4 @@ --- - name: restart pound service: name=pound state=restarted - sudo: true + become: true diff --git a/lib/ansible/roles/pound/tasks/main.yml b/lib/ansible/roles/pound/tasks/main.yml index c2c79e3d..adae5c44 100644 --- a/lib/ansible/roles/pound/tasks/main.yml +++ b/lib/ansible/roles/pound/tasks/main.yml @@ -2,16 +2,16 @@ # https://launchpad.net/~unleashedtech/+archive/ubuntu/pound-2.7 - name: Register pound 2.7 ppa apt_repository: repo='ppa:unleashedtech/pound-2.7' - sudo: true + become: true - name: Install pound package apt: pkg=pound state=latest update_cache=yes - sudo: true + become: true - name: Copy pound configuration file template: src=pound.cfg dest=/etc/pound/pound.cfg mode=0644 notify: restart pound - sudo: true + become: true - name: Copy SSL certificates copy: src=./files/ssl/{{ item }}.{{ domain }}.pem dest=/etc/pound/{{ item }}.{{ domain }}.pem mode=0644 @@ -20,26 +20,26 @@ - staging - production notify: restart pound - sudo: true + become: true - name: Enable pound lineinfile: regexp='^startup=0' line='startup=1' dest=/etc/default/pound backup=yes notify: restart pound - sudo: yes + become: true - name: Configure HTTPS Forwarded Proto detection in Apache (2.2) copy: content="SetEnvIf X-Forwarded-Proto ^https$ HTTPS=on\n" dest=/etc/apache2/conf.d/https-forwarded-proto.conf mode=0644 notify: restart apache when: apache_version.stdout == '2.2' - sudo: true + become: true - name: Configure HTTPS Forwarded Proto detection in Apache (2.4) copy: content="SetEnvIf X-Forwarded-Proto ^https$ HTTPS=on\n" dest=/etc/apache2/conf-available/https-forwarded-proto.conf mode=0644 when: apache_version.stdout == '2.4' - sudo: true + become: true - name: Enable canonical config (2.4) command: a2enconf https-forwarded-proto notify: restart apache when: apache_version.stdout == '2.4' - sudo: yes + become: true diff --git a/lib/ansible/roles/prepare/tasks/main.yml b/lib/ansible/roles/prepare/tasks/main.yml index 5e4e53f4..54580811 100644 --- a/lib/ansible/roles/prepare/tasks/main.yml +++ b/lib/ansible/roles/prepare/tasks/main.yml @@ -9,5 +9,5 @@ - name: Stop any existing evolution services service: name=evolution-wordpress state=stopped - sudo: yes + become: true when: evo_init.stat.exists == True diff --git a/lib/ansible/roles/user/tasks/main.yml b/lib/ansible/roles/user/tasks/main.yml index d5d844e6..0f87022a 100644 --- a/lib/ansible/roles/user/tasks/main.yml +++ b/lib/ansible/roles/user/tasks/main.yml @@ -7,36 +7,36 @@ - name: Add vagrant user to www-data user: name=vagrant append=yes groups=www-data when: has_vagrant.stdout - sudo: yes + become: true - name: Create deploy group group: name=deploy state=present system=no - sudo: yes + become: true - name: Create deploy user user: name=deploy append=yes group=deploy groups=www-data shell=/bin/bash comment="Created by Evolution WordPress" - sudo: yes + become: true - name: Grant sudo access to deploy user copy: content="%deploy ALL=(ALL) NOPASSWD:ALL" dest=/etc/sudoers.d/deploy mode=0440 force=no - sudo: yes + become: true - name: Add www-data user to deploy user: name=www-data append=yes groups=deploy - sudo: yes + become: true - name: Create /home/deploy/.ssh file: path=/home/deploy/.ssh state=directory mode=0755 owner=deploy group=deploy - sudo: yes + become: true - name: Copy deploy private key copy: src=./files/ssh/id_rsa dest=/home/deploy/.ssh/id_rsa owner=deploy group=deploy mode=0600 - sudo: yes + become: true - name: Copy deploy public key copy: src=./files/ssh/id_rsa.pub dest=/home/deploy/.ssh/id_rsa.pub owner=deploy group=deploy mode=0600 - sudo: yes + become: true - name: Set deploy key as authorized key copy: src=./files/ssh/id_rsa.pub dest=/home/deploy/.ssh/authorized_keys owner=deploy group=deploy mode=0600 - sudo: yes + become: true diff --git a/lib/ansible/roles/varnish/handlers/main.yml b/lib/ansible/roles/varnish/handlers/main.yml index 441801a9..6e63676d 100644 --- a/lib/ansible/roles/varnish/handlers/main.yml +++ b/lib/ansible/roles/varnish/handlers/main.yml @@ -1,4 +1,4 @@ --- - name: restart varnish service: name=varnish state=restarted - sudo: true + become: true diff --git a/lib/ansible/roles/varnish/tasks/main.yml b/lib/ansible/roles/varnish/tasks/main.yml index 43f70487..f67b3ef2 100644 --- a/lib/ansible/roles/varnish/tasks/main.yml +++ b/lib/ansible/roles/varnish/tasks/main.yml @@ -2,11 +2,11 @@ - name: Install Varnish packages apt: pkg={{ item }} state=present with_items: "{{ varnish_packages }}" - sudo: yes + become: true - name: Create Varnish directory structure file: path={{ item }} state=directory mode=0644 - sudo: yes + become: true with_items: - /etc/varnish - /etc/varnish/conf.d @@ -15,7 +15,7 @@ - name: Copy Varnish configuration files copy: src=etc-varnish/{{ item }} dest=/etc/varnish/{{ item }} mode=0644 - sudo: yes + become: true with_items: - conf.d/fetch/wordpress.vcl - conf.d/receive/wordpress.vcl @@ -25,7 +25,7 @@ - name: Copy Varnish script copy: src=etc-default-varnish dest=/etc/default/varnish mode=0644 - sudo: yes + become: true notify: - restart apache - restart varnish @@ -36,16 +36,16 @@ - name: Disable apache module "rpaf" (if installed) command: a2dismod rpaf when: rpaf_load.stat.exists - sudo: yes + become: true notify: restart apache - name: Configure apache module "remoteip" copy: src=remoteip.conf dest=/etc/apache2/mods-available/remoteip.conf mode=0644 - sudo: yes + become: true - name: Enable apache module "remoteip" command: a2enmod remoteip - sudo: yes + become: true notify: restart apache - name: Change Apache NameVirtualHost 80 => 8080 (2.2) @@ -54,14 +54,14 @@ - restart apache - restart varnish when: apache_version.stdout == '2.2' - sudo: yes + become: true - name: Change Apache Listen 80 => 8080 lineinfile: regexp='^Listen' line='Listen 8080' dest=/etc/apache2/ports.conf backup=yes notify: - restart apache - restart varnish - sudo: yes + become: true - name: Change VirtualHosts from 80 => 8080 lineinfile: regexp='^' line='' dest=/etc/apache2/sites-available/{{ "%03d" | format(item.key_1) }}-{{ item.value }}.{{ domain }}.conf @@ -70,4 +70,4 @@ notify: - restart apache - restart varnish - sudo: true + become: true diff --git a/lib/ansible/roles/wp-cli/tasks/main.yml b/lib/ansible/roles/wp-cli/tasks/main.yml index e6d328c1..d6567a3a 100644 --- a/lib/ansible/roles/wp-cli/tasks/main.yml +++ b/lib/ansible/roles/wp-cli/tasks/main.yml @@ -4,7 +4,7 @@ - name: Copy latest wp-cli to remote copy: src=/tmp/wp-cli dest=/usr/local/bin/wp force=yes mode=0755 - sudo: yes + become: true - name: Remove latest wp-cli in tmp (from control) local_action: file dest=/tmp/wp-cli state=absent From 36e7a5591106877c2303858d4c079cb5ee6e69ed Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Mon, 21 Nov 2016 10:44:06 -0800 Subject: [PATCH 61/66] Dropped ansible 1.x version of nested_dict lookup --- .../lookup_plugins/ansible1_nested_dict.py | 47 --------- .../lookup_plugins/ansible2_nested_dict.py | 84 ---------------- lib/ansible/lookup_plugins/nested_dict.py | 95 ++++++++++++++++--- 3 files changed, 84 insertions(+), 142 deletions(-) delete mode 100644 lib/ansible/lookup_plugins/ansible1_nested_dict.py delete mode 100644 lib/ansible/lookup_plugins/ansible2_nested_dict.py diff --git a/lib/ansible/lookup_plugins/ansible1_nested_dict.py b/lib/ansible/lookup_plugins/ansible1_nested_dict.py deleted file mode 100644 index 8f15eae7..00000000 --- a/lib/ansible/lookup_plugins/ansible1_nested_dict.py +++ /dev/null @@ -1,47 +0,0 @@ -# (c) 2014, Evan Kaufman -# -# This file is part of Ansible -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see . - -from ansible.utils import safe_eval -import ansible.utils as utils -import ansible.errors as errors - -def flatten_nested_hash_to_list(terms, result=None, stack=None, level=None): - result = [] if result is None else result - stack = {} if stack is None else stack - level = 0 if level is None else level - - for key, val in terms.iteritems(): - stack['key_%s' % level] = key - if type(val) is dict: - flatten_nested_hash_to_list(terms=val, result=result, stack=stack.copy(), level=level+1) - else: - stack['value'] = val - result.append(stack.copy()) - return result - -class LookupModule(object): - - def __init__(self, basedir=None, **kwargs): - self.basedir = basedir - - def run(self, terms, inject=None, **kwargs): - terms = utils.listify_lookup_plugin_terms(terms, self.basedir, inject) - - if not isinstance(terms, dict): - raise errors.AnsibleError("with_nested_dict expects a dict") - - return flatten_nested_hash_to_list(terms) diff --git a/lib/ansible/lookup_plugins/ansible2_nested_dict.py b/lib/ansible/lookup_plugins/ansible2_nested_dict.py deleted file mode 100644 index af9d30ff..00000000 --- a/lib/ansible/lookup_plugins/ansible2_nested_dict.py +++ /dev/null @@ -1,84 +0,0 @@ -# (c) 2016, Evan Kaufman -# -# This file is part of Ansible -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see . -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -from ansible.errors import AnsibleError -from ansible.plugins.lookup import LookupBase - -""" -Lookup plugin to flatten nested dictionaries for linear iteration -================================================================= - -For example, a collection of holidays nested by year, month, and day: - - { - '2016': { - 'January': { - '1': 'New Years Day', - '19': 'Martin Luther King Day', - }, - 'February': { - '14': 'Valentines Day', - '16': 'Presidents Day', - }, - ... - }, - ... - } - -Would be flattened into an array of shallow dicts, with each original key denoted by its nesting level: - - [ - { 'key_0': '2016', 'key_1': 'January', 'key_2': '1', 'value': 'New Years Day' }, - { 'key_0': '2016', 'key_1': 'January', 'key_2': '19', 'value': 'Martin Luther King Day' }, - { 'key_0': '2016', 'key_1': 'February', 'key_2': '14', 'value': 'Valentines Day' }, - { 'key_0': '2016', 'key_1': 'February', 'key_2': '16', 'value': 'Presidents Day' }, - ... - ] - -The nested keys and value of each are then exposed to an iterative task: - - - name: "Remind us what holidays are this month" - debug: - msg: "Remember {{value}} on {{key_1}} {{'%02d'|format(key_2)}} in the year {{key_0}}" - when: key_1 == current_month - with_nested_dict: holidays_by_year_month_day - -""" -class LookupModule(LookupBase): - - @staticmethod - def _flatten_nested_hash_to_list(terms, result=None, stack=None, level=None): - result = [] if result is None else result - stack = {} if stack is None else stack - level = 0 if level is None else level - - for key, val in terms.iteritems(): - stack['key_%s' % level] = key - if type(val) is dict: - LookupModule._flatten_nested_hash_to_list(terms=val, result=result, stack=stack.copy(), level=level+1) - else: - stack['value'] = val - result.append(stack.copy()) - return result - - def run(self, terms, variables=None, **kwargs): - if not isinstance(terms, dict): - raise AnsibleError("with_nested_dict expects a dict") - - return self._flatten_nested_hash_to_list(terms) diff --git a/lib/ansible/lookup_plugins/nested_dict.py b/lib/ansible/lookup_plugins/nested_dict.py index 6a417e8c..af9d30ff 100644 --- a/lib/ansible/lookup_plugins/nested_dict.py +++ b/lib/ansible/lookup_plugins/nested_dict.py @@ -1,11 +1,84 @@ -# add current dir to import path -import sys -import os -sys.path.append(os.path.dirname(__file__)) - -# import the right plugin for the right ansible major version -from ansible import __version__ as ansible_version -if ansible_version.startswith('2.'): - from ansible2_nested_dict import LookupModule -elif ansible_version.startswith('1.'): - from ansible1_nested_dict import LookupModule +# (c) 2016, Evan Kaufman +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +from ansible.errors import AnsibleError +from ansible.plugins.lookup import LookupBase + +""" +Lookup plugin to flatten nested dictionaries for linear iteration +================================================================= + +For example, a collection of holidays nested by year, month, and day: + + { + '2016': { + 'January': { + '1': 'New Years Day', + '19': 'Martin Luther King Day', + }, + 'February': { + '14': 'Valentines Day', + '16': 'Presidents Day', + }, + ... + }, + ... + } + +Would be flattened into an array of shallow dicts, with each original key denoted by its nesting level: + + [ + { 'key_0': '2016', 'key_1': 'January', 'key_2': '1', 'value': 'New Years Day' }, + { 'key_0': '2016', 'key_1': 'January', 'key_2': '19', 'value': 'Martin Luther King Day' }, + { 'key_0': '2016', 'key_1': 'February', 'key_2': '14', 'value': 'Valentines Day' }, + { 'key_0': '2016', 'key_1': 'February', 'key_2': '16', 'value': 'Presidents Day' }, + ... + ] + +The nested keys and value of each are then exposed to an iterative task: + + - name: "Remind us what holidays are this month" + debug: + msg: "Remember {{value}} on {{key_1}} {{'%02d'|format(key_2)}} in the year {{key_0}}" + when: key_1 == current_month + with_nested_dict: holidays_by_year_month_day + +""" +class LookupModule(LookupBase): + + @staticmethod + def _flatten_nested_hash_to_list(terms, result=None, stack=None, level=None): + result = [] if result is None else result + stack = {} if stack is None else stack + level = 0 if level is None else level + + for key, val in terms.iteritems(): + stack['key_%s' % level] = key + if type(val) is dict: + LookupModule._flatten_nested_hash_to_list(terms=val, result=result, stack=stack.copy(), level=level+1) + else: + stack['value'] = val + result.append(stack.copy()) + return result + + def run(self, terms, variables=None, **kwargs): + if not isinstance(terms, dict): + raise AnsibleError("with_nested_dict expects a dict") + + return self._flatten_nested_hash_to_list(terms) From 112317cbd7d9a02c0721385df3ca768138738c10 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Tue, 22 Nov 2016 17:32:14 -0800 Subject: [PATCH 62/66] Rewrote ansible tasks in long form --- lib/ansible/lookup_plugins/nested_dict.py | 8 +- .../roles/apache-prefork/tasks/main.yml | 12 +- lib/ansible/roles/apache/handlers/main.yml | 8 +- lib/ansible/roles/apache/library/restore | 10 +- lib/ansible/roles/apache/tasks/main.yml | 190 ++++++++++------- lib/ansible/roles/awstats/tasks/main.yml | 4 +- lib/ansible/roles/awstats/tasks/vagrant.yml | 67 +++--- lib/ansible/roles/cleanup/tasks/main.yml | 33 +-- lib/ansible/roles/common/tasks/main.yml | 193 ++++++++++-------- lib/ansible/roles/common/tasks/swap.yml | 90 ++++---- lib/ansible/roles/debug/tasks/main.yml | 10 +- lib/ansible/roles/firewall/handlers/main.yml | 8 +- lib/ansible/roles/firewall/tasks/main.yml | 63 +++--- lib/ansible/roles/mail/tasks/main.yml | 23 ++- lib/ansible/roles/mysql/tasks/main.yml | 46 +++-- lib/ansible/roles/newrelic/handlers/main.yml | 8 +- lib/ansible/roles/newrelic/tasks/main.yml | 44 ++-- lib/ansible/roles/node/tasks/main.yml | 66 +++--- .../roles/php-hardened/tasks/build.yml | 71 ++++--- lib/ansible/roles/php-hardened/tasks/main.yml | 12 +- .../roles/php-hardened/tasks/suhosin.yml | 73 ++++--- lib/ansible/roles/php/tasks/main.yml | 72 ++++--- lib/ansible/roles/pound/handlers/main.yml | 8 +- lib/ansible/roles/pound/tasks/main.yml | 84 +++++--- lib/ansible/roles/prepare/tasks/main.yml | 24 ++- lib/ansible/roles/user/tasks/main.yml | 121 +++++++---- lib/ansible/roles/varnish/handlers/main.yml | 8 +- lib/ansible/roles/varnish/tasks/main.yml | 102 +++++---- lib/ansible/roles/wp-cli/tasks/main.yml | 25 ++- 29 files changed, 908 insertions(+), 575 deletions(-) diff --git a/lib/ansible/lookup_plugins/nested_dict.py b/lib/ansible/lookup_plugins/nested_dict.py index af9d30ff..40030189 100644 --- a/lib/ansible/lookup_plugins/nested_dict.py +++ b/lib/ansible/lookup_plugins/nested_dict.py @@ -53,11 +53,11 @@ The nested keys and value of each are then exposed to an iterative task: - - name: "Remind us what holidays are this month" + - name: "Remind us what holidays are this month" debug: - msg: "Remember {{value}} on {{key_1}} {{'%02d'|format(key_2)}} in the year {{key_0}}" - when: key_1 == current_month - with_nested_dict: holidays_by_year_month_day + msg: "Remember {{value}} on {{key_1}} {{'%02d'|format(key_2)}} in the year {{key_0}}" + when: key_1 == current_month + with_nested_dict: holidays_by_year_month_day """ class LookupModule(LookupBase): diff --git a/lib/ansible/roles/apache-prefork/tasks/main.yml b/lib/ansible/roles/apache-prefork/tasks/main.yml index c8fd2b98..b147d030 100644 --- a/lib/ansible/roles/apache-prefork/tasks/main.yml +++ b/lib/ansible/roles/apache-prefork/tasks/main.yml @@ -1,5 +1,9 @@ --- -- name: Override apache prefork module config - template: src=prefork.conf dest=/etc/apache2/mods-available/mpm_prefork.conf backup=yes mode=0644 - when: apache_version.stdout == '2.4' - become: true +- name: Override apache prefork module config + template: + src: prefork.conf + dest: /etc/apache2/mods-available/mpm_prefork.conf + backup: yes + mode: '0644' + when: apache_version.stdout == '2.4' + become: true diff --git a/lib/ansible/roles/apache/handlers/main.yml b/lib/ansible/roles/apache/handlers/main.yml index d5eef80f..bfc5e044 100644 --- a/lib/ansible/roles/apache/handlers/main.yml +++ b/lib/ansible/roles/apache/handlers/main.yml @@ -1,4 +1,6 @@ --- -- name: restart apache - service: name=apache2 state=restarted - become: true +- name: restart apache + service: + name: apache2 + state: restarted + become: true diff --git a/lib/ansible/roles/apache/library/restore b/lib/ansible/roles/apache/library/restore index 181f5dcf..e79dc182 100644 --- a/lib/ansible/roles/apache/library/restore +++ b/lib/ansible/roles/apache/library/restore @@ -56,10 +56,16 @@ options: EXAMPLES = """ # Restore oldest available backup of apache mod config -- restore: path=/etc/apache2/mods-available/mpm_prefork.conf backup=no which=oldest +- restore: + path: /etc/apache2/mods-available/mpm_prefork.conf + backup: no + which: oldest # Restore newest available backup of service config, whilst backing up current file -- restore: path=/etc/default/varnish backup=yes which=newest +- restore: + path: /etc/default/varnish + backup: yes + which: newest """ def main(): diff --git a/lib/ansible/roles/apache/tasks/main.yml b/lib/ansible/roles/apache/tasks/main.yml index 904dd805..45c58d86 100644 --- a/lib/ansible/roles/apache/tasks/main.yml +++ b/lib/ansible/roles/apache/tasks/main.yml @@ -1,65 +1,96 @@ --- -- name: Install Apache packages - apt: pkg={{ item }} state=present - with_items: "{{ apache_packages }}" - become: true - -- name: Enable Apache modules - apache2_module: name={{ item }} state=present - with_items: "{{ apache_modules }}" - become: true - notify: restart apache - -- name: Disable Apache modules - apache2_module: name={{ item }} state=absent - with_items: "{{ apache_disabled_modules }}" - become: true - notify: restart apache - -- name: Register Apache major/minor version - shell: "apache2 -v | grep -i apache | perl -pe 's|^.*apache/([0-9]+[.][0-9]+)[.].*$|$1|i'" - register: apache_version - -- debug: msg={{ apache_version.stdout }} - -- name: Configure apache log rotation - copy: src=logrotate-apache dest=/etc/logrotate.d/apache2 owner=root group=root mode=644 - become: true - -- name: Configure Apache canonical server name - template: src=canonical dest=/etc/apache2/conf-available/canonical-servername.conf mode=0644 - when: apache_version.stdout == '2.4' - become: true - -- name: Enable canonical config - command: a2enconf canonical-servername - notify: restart apache - when: apache_version.stdout == '2.4' - become: true - -- name: Ensure Apache `Listen` is 80 - lineinfile: regexp='^Listen' line='Listen 80' dest=/etc/apache2/ports.conf backup=yes - notify: restart apache - become: true - -- name: Ensure existing Varnish installs won't cause port conflict on boot - lineinfile: regexp='^START=' line='START=no' dest=/etc/default/varnish backup=no - ignore_errors: true - become: true - -- name: Ensure pristine mpm_prefork directives - restore: path=/etc/apache2/mods-available/mpm_prefork.conf which=oldest backup=no fail_on_missing=no - when: apache_version.stdout == '2.4' - become: true - -- name: Change ownership of /var/www to deploy - file: path=/var/www state=directory owner=deploy group=deploy - become: true - -- shell: (cd /etc/apache2/sites-enabled/ && ls -1 000-default*) - register: apache_default_vhost - ignore_errors: true - become: true +- name: Install Apache packages + apt: + pkg: "{{ item }}" + state: present + with_items: "{{ apache_packages }}" + become: true + +- name: Enable Apache modules + apache2_module: + name: "{{ item }}" + state: present + with_items: "{{ apache_modules }}" + become: true + notify: restart apache + +- name: Disable Apache modules + apache2_module: + name: "{{ item }}" + state: absent + with_items: "{{ apache_disabled_modules }}" + become: true + notify: restart apache + +- name: Register Apache major/minor version + shell: "apache2 -v | grep -i apache | perl -pe 's|^.*apache/([0-9]+[.][0-9]+)[.].*$|$1|i'" + register: apache_version + +- debug: + msg: "{{ apache_version.stdout }}" + +- name: Configure apache log rotation + copy: + src: logrotate-apache + dest: /etc/logrotate.d/apache2 + owner: root + group: root + mode: '0644' + become: true + +- name: Configure Apache canonical server name + template: + src: canonical + dest: /etc/apache2/conf-available/canonical-servername.conf + mode: '0644' + when: apache_version.stdout == '2.4' + become: true + +- name: Enable canonical config + command: a2enconf canonical-servername + notify: restart apache + when: apache_version.stdout == '2.4' + become: true + +- name: Ensure Apache `Listen` is 80 + lineinfile: + regexp: '^Listen' + line: 'Listen 80' + dest: /etc/apache2/ports.conf + backup: yes + notify: restart apache + become: true + +- name: Ensure existing Varnish installs won't cause port conflict on boot + lineinfile: + regexp: '^START=' + line: 'START=no' + dest: /etc/default/varnish + backup: no + ignore_errors: true + become: true + +- name: Ensure pristine mpm_prefork directives + restore: + path: /etc/apache2/mods-available/mpm_prefork.conf + which: oldest + backup: no + fail_on_missing: no + when: apache_version.stdout == '2.4' + become: true + +- name: Change ownership of /var/www to deploy + file: + path: /var/www + state: directory + owner: deploy + group: deploy + become: true + +- shell: (cd /etc/apache2/sites-enabled/ && ls -1 000-default*) + register: apache_default_vhost + ignore_errors: true + become: true - set_fact: wordpress__xmlrpc_allow: false @@ -69,22 +100,27 @@ wordpress__xmlrpc_whitelist: false when: wordpress__xmlrpc_whitelist is undefined -- name: Disable default apache site - command: a2dissite {{ apache_default_vhost.stdout }} removes=/etc/apache2/sites-enabled/{{ apache_default_vhost.stdout }} - notify: restart apache - when: apache_default_vhost.stdout != '' - become: true - -- name: Create apache vhosts - template: src=virtualhost dest=/etc/apache2/sites-available/{{ "%03d" | format(item.key_1) }}-{{ item.value }}.{{ domain }}.conf mode=0644 +- name: Disable default apache site + command: a2dissite {{ apache_default_vhost.stdout }} + args: + removes: /etc/apache2/sites-enabled/{{ apache_default_vhost.stdout }} + notify: restart apache + when: apache_default_vhost.stdout != '' + become: true + +- name: Create apache vhosts + template: + src: virtualhost + dest: /etc/apache2/sites-available/{{ "%03d" | format(item.key_1) }}-{{ item.value }}.{{ domain }}.conf + mode: '0644' with_nested_dict: "{{ apache_vhosts }}" # see ansible/ansible#9563 - when: item.key_0 == stage - notify: restart apache - become: true + when: item.key_0 == stage + notify: restart apache + become: true -- name: Enable apache vhosts - command: a2ensite {{ "%03d" | format(item.key_1) }}-{{ item.value }}.{{ domain }}.conf +- name: Enable apache vhosts + command: a2ensite {{ "%03d" | format(item.key_1) }}-{{ item.value }}.{{ domain }}.conf with_nested_dict: "{{ apache_vhosts }}" - when: item.key_0 == stage - notify: restart apache - become: true + when: item.key_0 == stage + notify: restart apache + become: true diff --git a/lib/ansible/roles/awstats/tasks/main.yml b/lib/ansible/roles/awstats/tasks/main.yml index 7acea934..31b77a9b 100644 --- a/lib/ansible/roles/awstats/tasks/main.yml +++ b/lib/ansible/roles/awstats/tasks/main.yml @@ -1,3 +1,3 @@ --- -- include: vagrant.yml - when: has_vagrant.stdout +- include: vagrant.yml + when: has_vagrant.stdout diff --git a/lib/ansible/roles/awstats/tasks/vagrant.yml b/lib/ansible/roles/awstats/tasks/vagrant.yml index 018aa842..975559e5 100644 --- a/lib/ansible/roles/awstats/tasks/vagrant.yml +++ b/lib/ansible/roles/awstats/tasks/vagrant.yml @@ -1,32 +1,51 @@ --- -- name: Install awstats - apt: pkg=awstats state=present - become: true +- name: Install awstats + apt: + pkg: awstats + state: present + become: true -- name: Use logfile synced down from remote - lineinfile: regexp='^LogFile=' line='LogFile="/tmp/apache2-remote-access.log"' dest=/etc/awstats/awstats.conf - become: true +- name: Use logfile synced down from remote + lineinfile: + regexp: '^LogFile=' + line: 'LogFile="/tmp/apache2-remote-access.log"' + dest: /etc/awstats/awstats.conf + become: true -- name: Use combined log format - lineinfile: regexp='^LogFormat=' line='LogFormat=1' dest=/etc/awstats/awstats.conf - become: true +- name: Use combined log format + lineinfile: + regexp: '^LogFormat=' + line: 'LogFormat=1' + dest: /etc/awstats/awstats.conf + become: true -- name: Set primary site domain - lineinfile: regexp='^SiteDomain=' line='SiteDomain="{{ domain }}"' dest=/etc/awstats/awstats.conf - become: true +- name: Set primary site domain + lineinfile: + regexp: '^SiteDomain=' + line: 'SiteDomain="{{ domain }}"' + dest: /etc/awstats/awstats.conf + become: true -- name: Set host aliases - lineinfile: regexp='^HostAliases=' line='HostAliases="localhost 127.0.0.1 REGEX[^.*\.{{ domain | replace(".", "\\.") }}$]' dest=/etc/awstats/awstats.conf - become: true +- name: Set host aliases + lineinfile: + regexp: '^HostAliases=' + line: 'HostAliases="localhost 127.0.0.1 REGEX[^.*\.{{ domain | replace(".", "\\.") }}$]' + dest: /etc/awstats/awstats.conf + become: true -- name: Enable Apache cgi module - apache2_module: name=cgi state=present - become: true - notify: restart apache +- name: Enable Apache cgi module + apache2_module: + name: cgi + state: present + become: true + notify: restart apache -- name: Update vhosts for awstats web ui - replace: dest=/etc/apache2/sites-available/{{ "%03d" | format(item.key_1) }}-{{ item.value }}.{{ domain }}.conf regexp='^([ \t]+)(LogLevel warn)' replace='\1\2\n\n\1Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch\n\1Alias /awstatsclasses "/usr/share/awstats/lib/"\n\1Alias /awstats-icon "/usr/share/awstats/icon/"\n\1Alias /awstatscss "/usr/share/doc/awstats/examples/css"\n\1ScriptAlias /awstats/ /usr/lib/cgi-bin/' +- name: Update vhosts for awstats web ui + replace: + dest: /etc/apache2/sites-available/{{ "%03d" | format(item.key_1) }}-{{ item.value }}.{{ domain }}.conf + regexp: '^([ \t]+)(LogLevel warn)' + replace: '\1\2\n\n\1Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch\n\1Alias /awstatsclasses "/usr/share/awstats/lib/"\n\1Alias /awstats-icon "/usr/share/awstats/icon/"\n\1Alias /awstatscss "/usr/share/doc/awstats/examples/css"\n\1ScriptAlias /awstats/ /usr/lib/cgi-bin/' with_nested_dict: "{{ apache_vhosts }}" # see ansible/ansible#9563 - when: item.key_0 == stage - notify: restart apache - become: true + when: item.key_0 == stage + notify: restart apache + become: true diff --git a/lib/ansible/roles/cleanup/tasks/main.yml b/lib/ansible/roles/cleanup/tasks/main.yml index 114dc4a8..8ce3d1a8 100644 --- a/lib/ansible/roles/cleanup/tasks/main.yml +++ b/lib/ansible/roles/cleanup/tasks/main.yml @@ -1,21 +1,24 @@ --- -- name: Ensure logrotate runs hourly - command: mv /etc/cron.daily/logrotate /etc/cron.hourly/logrotate +- name: Ensure logrotate runs hourly + command: mv /etc/cron.daily/logrotate /etc/cron.hourly/logrotate args: - creates: /etc/cron.hourly/logrotate - removes: /etc/cron.daily/logrotate - become: true + creates: /etc/cron.hourly/logrotate + removes: /etc/cron.daily/logrotate + become: true -- name: Set up wpcron via user-level crontab +- name: Set up wpcron via user-level crontab cron: args: - name: "wpcron for {{stage}}" - user: deploy - job: "cd {{item.value}} && /usr/local/bin/wp core is-installed --path=$PWD --url='http://{{stage}}.{{domain}}/' && /usr/local/bin/wp cron event run --all --quiet --path=$PWD --url='http://{{stage}}.{{domain}}/'" - with_dict: "{{ wp_cron_path }}" - when: item.key == stage - become: true + name: "wpcron for {{stage}}" + user: deploy + job: "cd {{item.value}} && /usr/local/bin/wp core is-installed --path=$PWD --url='http://{{stage}}.{{domain}}/' && /usr/local/bin/wp cron event run --all --quiet --path=$PWD --url='http://{{stage}}.{{domain}}/'" + with_dict: "{{ wp_cron_path }}" + when: item.key == stage + become: true -- name: Generate init.d for installed evolution services - template: src=evolution-init-d dest=/etc/init.d/evolution-wordpress mode=0755 - become: true +- name: Generate init.d for installed evolution services + template: + src: evolution-init-d + dest: /etc/init.d/evolution-wordpress + mode: '0755' + become: true diff --git a/lib/ansible/roles/common/tasks/main.yml b/lib/ansible/roles/common/tasks/main.yml index bbef1c04..2845ba0b 100644 --- a/lib/ansible/roles/common/tasks/main.yml +++ b/lib/ansible/roles/common/tasks/main.yml @@ -1,83 +1,116 @@ --- -- name: Domain - debug: var=domain - -- name: Stage - debug: var=stage - -- name: New Hostname - debug: var=new_hostname - -- name: Determine static or dynamic resolv.conf - shell: cat /etc/resolv.conf | grep "DO NOT EDIT THIS FILE BY HAND" - ignore_errors: yes - register: dynamic_resolv - -- name: Update nameservers in resolv.conf - replace: dest=/etc/resolv.conf regexp="(nameserver [\w\d.:]+\n?)+" replace="nameserver 8.8.8.8\nnameserver 8.8.4.4\n\1" - become: true - -- name: Update nameservers in dhclient.conf - lineinfile: dest=/etc/dhcp/dhclient.conf regexp="^#?prepend domain-name-servers " line="prepend domain-name-servers 8.8.8.8, 8.8.4.4;" - become: true - when: dynamic_resolv.stdout != "" +- name: Domain + debug: + var: domain + +- name: Stage + debug: + var: stage + +- name: New Hostname + debug: + var: new_hostname + +- name: Determine static or dynamic resolv.conf + shell: cat /etc/resolv.conf | grep "DO NOT EDIT THIS FILE BY HAND" + ignore_errors: yes + register: dynamic_resolv + +- name: Update nameservers in resolv.conf + replace: + dest: /etc/resolv.conf + regexp: '(nameserver [\w\d.:]+\n?)+' + replace: 'nameserver 8.8.8.8\nnameserver 8.8.4.4\n\1' + become: true + +- name: Update nameservers in dhclient.conf + lineinfile: + dest: /etc/dhcp/dhclient.conf + regexp: '^#?prepend domain-name-servers ' + line: 'prepend domain-name-servers 8.8.8.8, 8.8.4.4;' + become: true + when: dynamic_resolv.stdout != "" # see evolution/wordpress#126 -- name: Fetch kernel purging script (from control) - local_action: get_url dest=/tmp/purge-kernels.py url=https://raw.githubusercontent.com/EvanK/ubuntu-purge-kernels/master/purge-kernels.py force=yes - -- name: Copy purging script to remote - copy: src=/tmp/purge-kernels.py dest=/tmp/purge-kernels.py force=yes mode=0755 - become: true - -- name: Purge kernels as necessary - command: /tmp/purge-kernels.py - register: purgekernels_result - ignore_errors: yes - become: true - when: not lookup('env','CI') - -- name: Remove kernel purging script in tmp (from control) - local_action: file dest=/tmp/purge-kernels.py state=absent - -- name: Show purged kernels - debug: var=purgekernels_result - -- name: Update apt cache - apt: update_cache=yes cache_valid_time="{{ 60 * 60 * 24 }}" - become: true - -- name: Autoremove unused packages - shell: DEBIAN_FRONTEND=noninteractive apt-get -y autoremove - become: true - -- name: Install common packages - apt: pkg={{ item }} state=present - with_items: "{{ common_packages }}" - become: true - -- name: Update `hostname` - hostname: name="{{ new_hostname }}" - become: true - when: old_hostname != new_hostname - -- name: Update /etc/hosts - replace: dest=/etc/hosts backup=yes regexp={{ old_hostname | replace(".", "[.]") }} replace={{ new_hostname }} - become: true - when: old_hostname != new_hostname - -- name: Configure logrotate for evolution logs - copy: src=logrotate dest=/etc/logrotate.d/evolution mode=0644 - become: true - -- name: Test for git protocol (git://) connectivity - command: curl -v -m 10 http://github.com:9418/ - register: git_protocol_test - ignore_errors: true - -- name: Bypass git protocol if necessary - command: git config --global url."https://".insteadOf git:// - when: "'connect() timed out' in git_protocol_test.stderr" - -- include: swap.yml - when: ansible_swaptotal_mb == 0 +- name: Fetch kernel purging script (from control) + local_action: + module: get_url + dest: /tmp/purge-kernels.py + url: https://raw.githubusercontent.com/EvanK/ubuntu-purge-kernels/master/purge-kernels.py + force: yes + +- name: Copy purging script to remote + copy: + src: /tmp/purge-kernels.py + dest: /tmp/purge-kernels.py + force: yes + mode: '0755' + become: true + +- name: Purge kernels as necessary + command: /tmp/purge-kernels.py + register: purgekernels_result + ignore_errors: yes + become: true + when: not lookup('env','CI') + +- name: Remove kernel purging script in tmp (from control) + local_action: + module: file + dest: /tmp/purge-kernels.py + state: absent + +- name: Show purged kernels + debug: + var: purgekernels_result + +- name: Update apt cache + apt: + update_cache: yes + cache_valid_time: "{{ 60 * 60 * 24 }}" + become: true + +- name: Autoremove unused packages + shell: DEBIAN_FRONTEND=noninteractive apt-get -y autoremove + become: true + +- name: Install common packages + apt: + pkg: "{{ item }}" + state: present + with_items: "{{ common_packages }}" + become: true + +- name: Update `hostname` + hostname: + name: "{{ new_hostname }}" + become: true + when: old_hostname != new_hostname + +- name: Update /etc/hosts + replace: + dest: /etc/hosts + backup: yes + regexp: '{{ old_hostname | replace(".", "[.]") }}' + replace: '{{ new_hostname }}' + become: true + when: old_hostname != new_hostname + +- name: Configure logrotate for evolution logs + copy: + src: logrotate + dest: /etc/logrotate.d/evolution + mode: '0644' + become: true + +- name: Test for git protocol (git://) connectivity + command: curl -v -m 10 http://github.com:9418/ + register: git_protocol_test + ignore_errors: true + +- name: Bypass git protocol if necessary + command: git config --global url."https://".insteadOf git:// + when: "'connect() timed out' in git_protocol_test.stderr" + +- include: swap.yml + when: ansible_swaptotal_mb == 0 diff --git a/lib/ansible/roles/common/tasks/swap.yml b/lib/ansible/roles/common/tasks/swap.yml index d80b7d0b..2e77569c 100644 --- a/lib/ansible/roles/common/tasks/swap.yml +++ b/lib/ansible/roles/common/tasks/swap.yml @@ -1,49 +1,69 @@ --- -- shell: "df {{ swap__path | dirname }} | awk '!/^Filesystem/ {print $NF}'" - register: swapfile_mountpoint +- shell: "df {{ swap__path | dirname }} | awk '!/^Filesystem/ {print $NF}'" + register: swapfile_mountpoint -- debug: var=swapfile_mountpoint +- debug: + var: swapfile_mountpoint -- name: Calculate ideal swapfile size - template: src=swapsize.j2 dest=/tmp/swapsize +- name: Calculate ideal swapfile size + template: + src: swapsize.j2 + dest: /tmp/swapsize -- name: Fetch swapfile size - shell: "cat /tmp/swapsize | tr -d '[:space:]'" - register: swapfile_size_mb +- name: Fetch swapfile size + shell: "cat /tmp/swapsize | tr -d '[:space:]'" + register: swapfile_size_mb -- debug: var=swapfile_size_mb.stdout +- debug: + var: swapfile_size_mb.stdout -- fail: msg="Could not determine swapfile size with available diskspace" - when: swapfile_size_mb.stdout == '' +- fail: + msg: "Could not determine swapfile size with available diskspace" + when: swapfile_size_mb.stdout == '' -- name: Write swapfile - command: fallocate -l {{swapfile_size_mb.stdout}}M {{swap__path}} - become: true +- name: Write swapfile + command: fallocate -l {{swapfile_size_mb.stdout}}M {{swap__path}} + become: true -- name: Set permissions - file: path={{swap__path}} mode=600 owner=root group=root - become: true +- name: Set permissions + file: + path: "{{swap__path}}" + mode: '0600' + owner: root + group: root + become: true -- name: Create swapfile - command: mkswap {{swap__path}} - become: true +- name: Create swapfile + command: mkswap {{swap__path}} + become: true -- name: Enable swapfile - command: swapon {{swap__path}} - become: true +- name: Enable swapfile + command: swapon {{swap__path}} + become: true -- name: Add swapfile to /etc/fstab - lineinfile: dest=/etc/fstab state=present line="{{ swap__path }} none swap sw 0 0" - become: true +- name: Add swapfile to /etc/fstab + lineinfile: + dest: /etc/fstab + state: present + line: "{{ swap__path }} none swap sw 0 0" + become: true -- name: Configure vm.swappiness - lineinfile: dest=/etc/sysctl.conf line="vm.swappiness = {{ swap__swappiness }}" regexp="^vm.swappiness\s*?=" state=present - become: true +- name: Configure vm.swappiness + lineinfile: + dest: /etc/sysctl.conf + line: 'vm.swappiness = {{ swap__swappiness }}' + regexp: '^vm.swappiness\s*?=' + state: present + become: true -- name: Configure vm.vfs_cache_pressure - lineinfile: dest=/etc/sysctl.conf line="vm.vfs_cache_pressure = {{ swap__vfs_cache_pressure }}" regexp="^vm.vfs_cache_pressure\s*?=" state=present - become: true +- name: Configure vm.vfs_cache_pressure + lineinfile: + dest: /etc/sysctl.conf + line: 'vm.vfs_cache_pressure = {{ swap__vfs_cache_pressure }}' + regexp: '^vm.vfs_cache_pressure\s*?=' + state: present + become: true -- name: Reload sysctl - command: sysctl -p - become: true +- name: Reload sysctl + command: sysctl -p + become: true diff --git a/lib/ansible/roles/debug/tasks/main.yml b/lib/ansible/roles/debug/tasks/main.yml index 11c80eb1..db2eb70f 100644 --- a/lib/ansible/roles/debug/tasks/main.yml +++ b/lib/ansible/roles/debug/tasks/main.yml @@ -1,5 +1,7 @@ --- -- name: Install debug packages - apt: pkg={{ item }} state=present - with_items: "{{ debug_packages }}" - become: true +- name: Install debug packages + apt: + pkg: "{{ item }}" + state: present + with_items: "{{ debug_packages }}" + become: true diff --git a/lib/ansible/roles/firewall/handlers/main.yml b/lib/ansible/roles/firewall/handlers/main.yml index ed1e597d..0cde7661 100644 --- a/lib/ansible/roles/firewall/handlers/main.yml +++ b/lib/ansible/roles/firewall/handlers/main.yml @@ -1,4 +1,6 @@ --- -- name: restart firewall - service: name=iptables-persistent state=restarted - become: true +- name: restart firewall + service: + name: iptables-persistent + state: restarted + become: true diff --git a/lib/ansible/roles/firewall/tasks/main.yml b/lib/ansible/roles/firewall/tasks/main.yml index 9350bfca..5ec578f7 100644 --- a/lib/ansible/roles/firewall/tasks/main.yml +++ b/lib/ansible/roles/firewall/tasks/main.yml @@ -1,37 +1,54 @@ --- -- name: Attempt to install vanilla iptables-persistent - apt: pkg=iptables-persistent state=latest update_cache=yes - register: iptables_attempted - ignore_errors: yes - become: true +- name: Attempt to install vanilla iptables-persistent + apt: + pkg: iptables-persistent + state: latest + update_cache: yes + register: iptables_attempted + ignore_errors: yes + become: true # See https://forum.linode.com/viewtopic.php?t=9070&p=58732 -- name: Postinst workaround for iptables-persistent - replace: dest=/var/lib/dpkg/info/iptables-persistent.postinst regexp='^(\s*?modprobe -q ip6?table_filter\s*?)$' replace='\1 || true' - when: iptables_attempted | failed - become: true +- name: Postinst workaround for iptables-persistent + replace: + dest: /var/lib/dpkg/info/iptables-persistent.postinst + regexp: '^(\s*?modprobe -q ip6?table_filter\s*?)$' + replace: '\1 || true' + when: iptables_attempted | failed + become: true -- name: Install firewall packages - apt: pkg={{ item }} state=present - with_items: "{{ firewall_packages }}" - become: true +- name: Install firewall packages + apt: + pkg: "{{ item }}" + state: present + with_items: "{{ firewall_packages }}" + become: true -- name: Install iptables init script + rulesets - copy: src={{ item }} dest=/etc/{{ item }} mode=0644 backup=yes - become: true +- name: Install iptables init script + rulesets + copy: + src: "{{ item }}" + dest: /etc/{{ item }} + mode: '0644' + backup: yes + become: true with_items: - init.d/iptables-persistent - iptables/rules.v4 - iptables/rules.v6 -- name: Create iptables + fail2ban configs - template: src={{ item }} dest=/etc/{{ item }} mode=0644 - become: true +- name: Create iptables + fail2ban configs + template: + src: "{{ item }}" + dest: /etc/{{ item }} + mode: '0644' + become: true with_items: - default/iptables-persistent.conf - fail2ban/jail.local -- name: Ensure iptables init script is executable - file: path=/etc/init.d/iptables-persistent mode=0755 - notify: restart firewall - become: true +- name: Ensure iptables init script is executable + file: + path: /etc/init.d/iptables-persistent + mode: '0755' + notify: restart firewall + become: true diff --git a/lib/ansible/roles/mail/tasks/main.yml b/lib/ansible/roles/mail/tasks/main.yml index 074bfa13..be9d09f0 100644 --- a/lib/ansible/roles/mail/tasks/main.yml +++ b/lib/ansible/roles/mail/tasks/main.yml @@ -1,12 +1,17 @@ --- -- name: Install mail package - apt: pkg=postfix state=present - become: true +- name: Install mail package + apt: + pkg: postfix + state: present + become: true -- name: Generate /etc/aliases - template: src=aliases dest=/etc/aliases mode=0644 - become: true +- name: Generate /etc/aliases + template: + src: aliases + dest: /etc/aliases + mode: '0644' + become: true -- name: Update mail aliases - command: newaliases - become: true +- name: Update mail aliases + command: newaliases + become: true diff --git a/lib/ansible/roles/mysql/tasks/main.yml b/lib/ansible/roles/mysql/tasks/main.yml index 320297a0..cd39e379 100644 --- a/lib/ansible/roles/mysql/tasks/main.yml +++ b/lib/ansible/roles/mysql/tasks/main.yml @@ -1,21 +1,35 @@ --- -- name: Install MySQL packages - apt: pkg={{ item }} state=present - with_items: "{{ mysql_packages }}" - become: true +- name: Install MySQL packages + apt: + pkg: "{{ item }}" + state: present + with_items: "{{ mysql_packages }}" + become: true -- name: Update my.conf's bind-address - lineinfile: dest=/etc/mysql/my.cnf backup=yes regexp=^bind-address line='bind-address = 0.0.0.0' - become: true +- name: Update my.conf's bind-address + lineinfile: + dest: /etc/mysql/my.cnf + backup: yes + regexp: '^bind-address' + line: 'bind-address = 0.0.0.0' + become: true -- name: Restart mysql - service: name=mysql state=restarted - become: true +- name: Restart mysql + service: + name: mysql + state: restarted + become: true -- name: Create MySQL database - mysql_db: name="{{ mysql.name }}_{{ stage }}" - become: true +- name: Create MySQL database + mysql_db: + name: "{{ mysql.name }}_{{ stage }}" + become: true -- name: Create MySQL user - mysql_user: name={{ mysql.user }} host={{ mysql.host }} password={{ mysql.password }} priv="{{ mysql.name }}_{{ stage }}.*:GRANT,ALL" append_privs=yes - become: true +- name: Create MySQL user + mysql_user: + name: "{{ mysql.user }}" + host: "{{ mysql.host }}" + password: "{{ mysql.password }}" + priv: "{{ mysql.name }}_{{ stage }}.*:GRANT,ALL" + append_privs: yes + become: true diff --git a/lib/ansible/roles/newrelic/handlers/main.yml b/lib/ansible/roles/newrelic/handlers/main.yml index 714583fa..203a7db0 100644 --- a/lib/ansible/roles/newrelic/handlers/main.yml +++ b/lib/ansible/roles/newrelic/handlers/main.yml @@ -1,4 +1,6 @@ --- -- name: restart newrelic-sysmond - service: name=newrelic-sysmond state=restarted - become: true +- name: restart newrelic-sysmond + service: + name: newrelic-sysmond + state: restarted + become: true diff --git a/lib/ansible/roles/newrelic/tasks/main.yml b/lib/ansible/roles/newrelic/tasks/main.yml index 8261be27..7d9ed6eb 100644 --- a/lib/ansible/roles/newrelic/tasks/main.yml +++ b/lib/ansible/roles/newrelic/tasks/main.yml @@ -1,28 +1,38 @@ --- -- name: Install repository key - apt_key: url=https://download.newrelic.com/548C16BF.gpg state=present - become: true +- name: Install repository key + apt_key: + url: https://download.newrelic.com/548C16BF.gpg + state: present + become: true -- name: Configure repository source list - apt_repository: repo='deb http://apt.newrelic.com/debian/ newrelic non-free' state=present - become: true +- name: Configure repository source list + apt_repository: + repo: 'deb http://apt.newrelic.com/debian/ newrelic non-free' + state: present + become: true -- name: Install PHP agent and sys monitor - apt: name={{ item }} state=latest update_cache=yes - become: true +- name: Install PHP agent and sys monitor + apt: + name: "{{ item }}" + state: latest + update_cache: yes + become: true with_items: - newrelic-php5 - newrelic-sysmond -- name: Configure PHP agent license key and app name - lineinfile: dest={{ php_conf_path }}/newrelic.ini regexp="^{{ item.key }}" line="{{ item.key }} = '{{ item.value }}'" - become: true +- name: Configure PHP agent license key and app name + lineinfile: + dest: "{{ php_conf_path }}/newrelic.ini" + regexp: '^{{ item.key }}' + line: '{{ item.key }} = ''{{ item.value }}''' + become: true with_dict: newrelic.appname: "{{ domain }} ({{ stage }})" newrelic.license: "{{ newrelic_api_key }}" - notify: restart apache + notify: restart apache -- name: Configure and start sys monitor - command: nrsysmond-config --set license_key={{ newrelic_api_key }} - become: true - notify: restart newrelic-sysmond +- name: Configure and start sys monitor + command: nrsysmond-config --set license_key={{ newrelic_api_key }} + become: true + notify: restart newrelic-sysmond diff --git a/lib/ansible/roles/node/tasks/main.yml b/lib/ansible/roles/node/tasks/main.yml index a821d543..b2ce5a02 100644 --- a/lib/ansible/roles/node/tasks/main.yml +++ b/lib/ansible/roles/node/tasks/main.yml @@ -1,33 +1,49 @@ --- -- name: Remove old node repository if necessary - apt_repository: repo='ppa:chris-lea/node.js' state=absent - become: true +- name: Remove old node repository if necessary + apt_repository: + repo: 'ppa:chris-lea/node.js' + state: absent + become: true -- name: Ensure removal of old node source lists - shell: rm -f /etc/apt/sources.list.d/chris-lea-node_js-*.list - ignore_errors: true - become: true +- name: Ensure removal of old node source lists + shell: rm -f /etc/apt/sources.list.d/chris-lea-node_js-*.list + ignore_errors: true + become: true -- name: Fetch Nodesource apt key (from control) - local_action: get_url dest=/tmp/ns4x.gpg.key url=https://deb.nodesource.com/gpgkey/nodesource.gpg.key force=yes +- name: Fetch Nodesource apt key (from control) + local_action: + module: get_url + dest: /tmp/ns4x.gpg.key + url: https://deb.nodesource.com/gpgkey/nodesource.gpg.key + force: yes -- name: Add Nodesource apt key - apt_key: data="{{ lookup('file', '/tmp/ns4x.gpg.key') }}" state=present - become: true +- name: Add Nodesource apt key + apt_key: + data: "{{ lookup('file', '/tmp/ns4x.gpg.key') }}" + state: present + become: true -- name: Remove Nodesource apt key in tmp (from control) - local_action: file dest=/tmp/ns4x.gpg.key state=absent +- name: Remove Nodesource apt key in tmp (from control) + local_action: + module: file + dest: /tmp/ns4x.gpg.key + state: absent -- name: Add Nodesource 4.x repos - apt_repository: repo={{item}} state=present update_cache=yes - with_items: "{{ node_repos }}" - become: true +- name: Add Nodesource 4.x repos + apt_repository: + repo: "{{item}}" + state: present + update_cache: yes + with_items: "{{ node_repos }}" + become: true -- name: Install node - apt: pkg=nodejs state=present - become: true +- name: Install node + apt: + pkg: nodejs + state: present + become: true -- name: Install global node modules - command: npm install -g {{ item }} - with_items: "{{ node_modules }}" - become: true +- name: Install global node modules + command: npm install -g {{ item }} + with_items: "{{ node_modules }}" + become: true diff --git a/lib/ansible/roles/php-hardened/tasks/build.yml b/lib/ansible/roles/php-hardened/tasks/build.yml index d0727ff9..0877931b 100644 --- a/lib/ansible/roles/php-hardened/tasks/build.yml +++ b/lib/ansible/roles/php-hardened/tasks/build.yml @@ -1,37 +1,48 @@ --- -- name: Fetch stable source - get_url: url={{ suhosin.url }} dest=/tmp/src-suhosin.tar.gz validate_certs=False - become: true - -- name: Hash source for checksum - shell: sha1sum /tmp/src-suhosin.tar.gz - register: suhosin_shahash - become: true - -- debug: var=suhosin_shahash.stdout - -- fail: msg="Suhosin source failed SHA1 hash" - when: suhosin_shahash.stdout.find('{{ suhosin.sha }}') == -1 - -- name: Expand source package - unarchive: src=/tmp/src-suhosin.tar.gz dest=/tmp/ copy=no - become: true - -- shell: ls -1d /tmp/suhosin* - register: suhosin_srcdir - become: true - -- debug: var=suhosin_srcdir.stdout - -- name: Compile and install extension - command: "{{ item }} chdir={{ suhosin_srcdir.stdout }}" - become: true +- name: Fetch stable source + get_url: + url: "{{ suhosin.url }}" + dest: /tmp/src-suhosin.tar.gz + validate_certs: False + become: true + +- name: Hash source for checksum + shell: sha1sum /tmp/src-suhosin.tar.gz + register: suhosin_shahash + become: true + +- debug: + var: suhosin_shahash.stdout + +- fail: + msg: "Suhosin source failed SHA1 hash" + when: suhosin_shahash.stdout.find('{{ suhosin.sha }}') == -1 + +- name: Expand source package + unarchive: + src: /tmp/src-suhosin.tar.gz + dest: /tmp/ + copy: no + become: true + +- shell: ls -1d /tmp/suhosin* + register: suhosin_srcdir + become: true + +- debug: + var: suhosin_srcdir.stdout + +- name: Compile and install extension + command: "{{ item }}" + args: + chdir: "{{ suhosin_srcdir.stdout }}" + become: true with_items: - phpize - ./configure - make - make install -- name: Clean up after ourselves - shell: rm -rf /tmp/*suhosin* - become: true +- name: Clean up after ourselves + shell: rm -rf /tmp/*suhosin* + become: true diff --git a/lib/ansible/roles/php-hardened/tasks/main.yml b/lib/ansible/roles/php-hardened/tasks/main.yml index e6b840f3..d7ecab7e 100644 --- a/lib/ansible/roles/php-hardened/tasks/main.yml +++ b/lib/ansible/roles/php-hardened/tasks/main.yml @@ -1,6 +1,10 @@ --- -- name: Disable allow_url_fopen - lineinfile: dest=/etc/php5/apache2/php.ini backup=yes regexp='^[;# ]*allow_url_fopen' line='allow_url_fopen = Off' - become: true +- name: Disable allow_url_fopen + lineinfile: + dest: /etc/php5/apache2/php.ini + backup: yes + regexp: '^[;# ]*allow_url_fopen' + line: 'allow_url_fopen = Off' + become: true -- include: suhosin.yml +- include: suhosin.yml diff --git a/lib/ansible/roles/php-hardened/tasks/suhosin.yml b/lib/ansible/roles/php-hardened/tasks/suhosin.yml index 0f6a6bf6..e3e65494 100644 --- a/lib/ansible/roles/php-hardened/tasks/suhosin.yml +++ b/lib/ansible/roles/php-hardened/tasks/suhosin.yml @@ -1,34 +1,41 @@ --- -- name: Install apg (for cryptkeys) - apt: name=apg state=present - become: true - -- name: Generate session cryptkey - shell: apg -m 32 | sed 's/[^a-zA-Z0-9]//g' - register: generated_session_cryptkey - -- debug: var=generated_session_cryptkey - -- name: Is suhosin already installed? - stat: path={{ suhosin.ini }} - register: suhosin_installed - -- name: Find existing session cryptkey - shell: cat {{ suhosin.ini }} | sed -n -e 's/^suhosin\.session\.cryptkey = //p' - register: existing_session_cryptkey - when: suhosin_installed.stat.exists == True - -- debug: var=existing_session_cryptkey - when: suhosin_installed.stat.exists == True - -- include: build.yml - when: suhosin_installed.stat.exists == False - -- name: Generate ini config for extension - template: src=suhosin.ini.j2 dest={{ suhosin.ini }} - become: true - -- name: Enable extension - command: php5enmod suhosin - become: true - notify: restart apache +- name: Install apg (for cryptkeys) + apt: + name: apg + state: present + become: true + +- name: Generate session cryptkey + shell: apg -m 32 | sed 's/[^a-zA-Z0-9]//g' + register: generated_session_cryptkey + +- debug: + var: generated_session_cryptkey + +- name: Is suhosin already installed? + stat: + path: "{{ suhosin.ini }}" + register: suhosin_installed + +- name: Find existing session cryptkey + shell: cat {{ suhosin.ini }} | sed -n -e 's/^suhosin\.session\.cryptkey = //p' + register: existing_session_cryptkey + when: suhosin_installed.stat.exists == True + +- debug: + var: existing_session_cryptkey + when: suhosin_installed.stat.exists == True + +- include: build.yml + when: suhosin_installed.stat.exists == False + +- name: Generate ini config for extension + template: + src: suhosin.ini.j2 + dest: "{{ suhosin.ini }}" + become: true + +- name: Enable extension + command: php5enmod suhosin + become: true + notify: restart apache diff --git a/lib/ansible/roles/php/tasks/main.yml b/lib/ansible/roles/php/tasks/main.yml index f4457dff..fecae4d9 100644 --- a/lib/ansible/roles/php/tasks/main.yml +++ b/lib/ansible/roles/php/tasks/main.yml @@ -1,35 +1,51 @@ --- -- name: Install PHP packages - apt: pkg={{ item }} - with_items: "{{ php_packages }}" - become: true +- name: Install PHP packages + apt: + pkg: "{{ item }}" + with_items: "{{ php_packages }}" + become: true -- name: Install PECL packages - command: pecl install {{ item if item is string else item.name + '-' + item.version }} creates={{ php_conf_path }}/{{ item if item is string else item.name }}.ini - with_items: "{{ pecl_packages }}" - become: true +- name: Install PECL packages + command: pecl install {{ item if item is string else item.name + '-' + item.version }} + args: + creates: "{{ php_conf_path }}/{{ item if item is string else item.name }}.ini" + with_items: "{{ pecl_packages }}" + become: true -- name: Enable PECL packages - lineinfile: line="extension={{ item if item is string else item.name }}.so" - dest="{{ php_conf_path }}/{{ item if item is string else item.name }}.ini" - create=yes - with_items: "{{ pecl_packages }}" - become: true +- name: Enable PECL packages + lineinfile: + line: "extension={{ item if item is string else item.name }}.so" + dest: "{{ php_conf_path }}/{{ item if item is string else item.name }}.ini" + create: yes + with_items: "{{ pecl_packages }}" + become: true -- name: Calculate PHP memory_limit - command: echo "{{ 256 if ansible_memtotal_mb > 2048 else 128 }}" - register: calc_php_memory_limit - ignore_errors: true - when: php__memory_limit is undefined +- name: Calculate PHP memory_limit + command: echo "{{ 256 if ansible_memtotal_mb > 2048 else 128 }}" + register: calc_php_memory_limit + ignore_errors: true + when: php__memory_limit is undefined -- name: Update php.ini's date.timezone - lineinfile: dest=/etc/php5/apache2/php.ini backup=yes regexp='^[;# ]*date\.timezone' line='date.timezone = "America/Chicago"' - become: true +- name: Update php.ini's date.timezone + lineinfile: + dest: /etc/php5/apache2/php.ini + backup: yes + regexp: '^[;# ]*date\.timezone' + line: 'date.timezone = "America/Chicago"' + become: true -- name: Update php.ini's memory_limit - lineinfile: dest=/etc/php5/apache2/php.ini backup=yes regexp='^[;# ]*memory_limit' line='memory_limit = {{ calc_php_memory_limit.stdout if calc_php_memory_limit.stdout is defined else php__memory_limit }}M' - become: true +- name: Update php.ini's memory_limit + lineinfile: + dest: /etc/php5/apache2/php.ini + backup: yes + regexp: '^[;# ]*memory_limit' + line: 'memory_limit = {{ calc_php_memory_limit.stdout if calc_php_memory_limit.stdout is defined else php__memory_limit }}M' + become: true -- name: Update php.ini's upload_max_filesize - lineinfile: dest=/etc/php5/apache2/php.ini backup=yes regexp='^[;# ]*upload_max_filesize' line='upload_max_filesize = 16M' - become: true +- name: Update php.ini's upload_max_filesize + lineinfile: + dest: /etc/php5/apache2/php.ini + backup: yes + regexp: '^[;# ]*upload_max_filesize' + line: 'upload_max_filesize = 16M' + become: true diff --git a/lib/ansible/roles/pound/handlers/main.yml b/lib/ansible/roles/pound/handlers/main.yml index bbd62f03..1238de9a 100644 --- a/lib/ansible/roles/pound/handlers/main.yml +++ b/lib/ansible/roles/pound/handlers/main.yml @@ -1,4 +1,6 @@ --- -- name: restart pound - service: name=pound state=restarted - become: true +- name: restart pound + service: + name: pound + state: restarted + become: true diff --git a/lib/ansible/roles/pound/tasks/main.yml b/lib/ansible/roles/pound/tasks/main.yml index adae5c44..6c38d154 100644 --- a/lib/ansible/roles/pound/tasks/main.yml +++ b/lib/ansible/roles/pound/tasks/main.yml @@ -1,45 +1,65 @@ --- # https://launchpad.net/~unleashedtech/+archive/ubuntu/pound-2.7 -- name: Register pound 2.7 ppa - apt_repository: repo='ppa:unleashedtech/pound-2.7' - become: true +- name: Register pound 2.7 ppa + apt_repository: + repo: 'ppa:unleashedtech/pound-2.7' + become: true -- name: Install pound package - apt: pkg=pound state=latest update_cache=yes - become: true +- name: Install pound package + apt: + pkg: pound + state: latest + update_cache: yes + become: true -- name: Copy pound configuration file - template: src=pound.cfg dest=/etc/pound/pound.cfg mode=0644 - notify: restart pound - become: true +- name: Copy pound configuration file + template: + src: pound.cfg + dest: /etc/pound/pound.cfg + mode: '0644' + notify: restart pound + become: true -- name: Copy SSL certificates - copy: src=./files/ssl/{{ item }}.{{ domain }}.pem dest=/etc/pound/{{ item }}.{{ domain }}.pem mode=0644 +- name: Copy SSL certificates + copy: + src: ./files/ssl/{{ item }}.{{ domain }}.pem + dest: /etc/pound/{{ item }}.{{ domain }}.pem + mode: '0644' with_items: - local - staging - production - notify: restart pound - become: true + notify: restart pound + become: true -- name: Enable pound - lineinfile: regexp='^startup=0' line='startup=1' dest=/etc/default/pound backup=yes - notify: restart pound - become: true +- name: Enable pound + lineinfile: + regexp: '^startup=0' + line: 'startup=1' + dest: /etc/default/pound + backup: yes + notify: restart pound + become: true -- name: Configure HTTPS Forwarded Proto detection in Apache (2.2) - copy: content="SetEnvIf X-Forwarded-Proto ^https$ HTTPS=on\n" dest=/etc/apache2/conf.d/https-forwarded-proto.conf mode=0644 - notify: restart apache - when: apache_version.stdout == '2.2' - become: true +- name: Configure HTTPS Forwarded Proto detection in Apache (2.2) + copy: + content: "SetEnvIf X-Forwarded-Proto ^https$ HTTPS=on\n" + dest: /etc/apache2/conf.d/https-forwarded-proto.conf + mode: '0644' + notify: restart apache + when: apache_version.stdout == '2.2' + become: true -- name: Configure HTTPS Forwarded Proto detection in Apache (2.4) - copy: content="SetEnvIf X-Forwarded-Proto ^https$ HTTPS=on\n" dest=/etc/apache2/conf-available/https-forwarded-proto.conf mode=0644 - when: apache_version.stdout == '2.4' - become: true +- name: Configure HTTPS Forwarded Proto detection in Apache (2.4) + copy: + content: "SetEnvIf X-Forwarded-Proto ^https$ HTTPS=on\n" + dest: /etc/apache2/conf-available/https-forwarded-proto.conf + mode: '0644' + when: apache_version.stdout == '2.4' + become: true -- name: Enable canonical config (2.4) - command: a2enconf https-forwarded-proto - notify: restart apache - when: apache_version.stdout == '2.4' - become: true +- name: Enable canonical config (2.4) + command: a2enconf https-forwarded-proto + notify: restart apache + when: apache_version.stdout == '2.4' + become: true diff --git a/lib/ansible/roles/prepare/tasks/main.yml b/lib/ansible/roles/prepare/tasks/main.yml index 54580811..71a48309 100644 --- a/lib/ansible/roles/prepare/tasks/main.yml +++ b/lib/ansible/roles/prepare/tasks/main.yml @@ -1,13 +1,17 @@ --- -- name: Test distro and version, as we only support specifically Ubuntu 14 - fail: msg="{{ansible_distribution}} {{ansible_distribution_version}} is not supported" - when: ansible_distribution != "Ubuntu" or ansible_distribution_major_version != "14" +- name: Test distro and version, as we only support specifically Ubuntu 14 + fail: + msg: "{{ansible_distribution}} {{ansible_distribution_version}} is not supported" + when: ansible_distribution != "Ubuntu" or ansible_distribution_major_version != "14" -- name: Test existance of evolution init script - stat: path=/etc/init.d/evolution-wordpress - register: evo_init +- name: Test existance of evolution init script + stat: + path: /etc/init.d/evolution-wordpress + register: evo_init -- name: Stop any existing evolution services - service: name=evolution-wordpress state=stopped - become: true - when: evo_init.stat.exists == True +- name: Stop any existing evolution services + service: + name: evolution-wordpress + state: stopped + become: true + when: evo_init.stat.exists == True diff --git a/lib/ansible/roles/user/tasks/main.yml b/lib/ansible/roles/user/tasks/main.yml index 0f87022a..bac97265 100644 --- a/lib/ansible/roles/user/tasks/main.yml +++ b/lib/ansible/roles/user/tasks/main.yml @@ -1,42 +1,81 @@ --- -- name: Check for vagrant user - command: id -u vagrant - register: has_vagrant - ignore_errors: true - -- name: Add vagrant user to www-data - user: name=vagrant append=yes groups=www-data - when: has_vagrant.stdout - become: true - -- name: Create deploy group - group: name=deploy state=present system=no - become: true - -- name: Create deploy user - user: name=deploy append=yes group=deploy groups=www-data shell=/bin/bash comment="Created by Evolution WordPress" - become: true - -- name: Grant sudo access to deploy user - copy: content="%deploy ALL=(ALL) NOPASSWD:ALL" dest=/etc/sudoers.d/deploy mode=0440 force=no - become: true - -- name: Add www-data user to deploy - user: name=www-data append=yes groups=deploy - become: true - -- name: Create /home/deploy/.ssh - file: path=/home/deploy/.ssh state=directory mode=0755 owner=deploy group=deploy - become: true - -- name: Copy deploy private key - copy: src=./files/ssh/id_rsa dest=/home/deploy/.ssh/id_rsa owner=deploy group=deploy mode=0600 - become: true - -- name: Copy deploy public key - copy: src=./files/ssh/id_rsa.pub dest=/home/deploy/.ssh/id_rsa.pub owner=deploy group=deploy mode=0600 - become: true - -- name: Set deploy key as authorized key - copy: src=./files/ssh/id_rsa.pub dest=/home/deploy/.ssh/authorized_keys owner=deploy group=deploy mode=0600 - become: true +- name: Check for vagrant user + command: id -u vagrant + register: has_vagrant + ignore_errors: true + +- name: Add vagrant user to www-data + user: + name: vagrant + append: yes + groups: www-data + when: has_vagrant.stdout + become: true + +- name: Create deploy group + group: + name: deploy + state: present + system: no + become: true + +- name: Create deploy user + user: + name: deploy + append: yes + group: deploy + groups: www-data + shell: /bin/bash + comment: "Created by Evolution WordPress" + become: true + +- name: Grant sudo access to deploy user + copy: + content: "%deploy ALL=(ALL) NOPASSWD:ALL" + dest: /etc/sudoers.d/deploy + mode: '0440' + force: no + become: true + +- name: Add www-data user to deploy + user: + name: www-data + append: yes + groups: deploy + become: true + +- name: Create /home/deploy/.ssh + file: + path: /home/deploy/.ssh + state: directory + mode: '0755' + owner: deploy + group: deploy + become: true + +- name: Copy deploy private key + copy: + src: ./files/ssh/id_rsa + dest: /home/deploy/.ssh/id_rsa + owner: deploy + group: deploy + mode: '0600' + become: true + +- name: Copy deploy public key + copy: + src: ./files/ssh/id_rsa.pub + dest: /home/deploy/.ssh/id_rsa.pub + owner: deploy + group: deploy + mode: '0600' + become: true + +- name: Set deploy key as authorized key + copy: + src: ./files/ssh/id_rsa.pub + dest: /home/deploy/.ssh/authorized_keys + owner: deploy + group: deploy + mode: '0600' + become: true diff --git a/lib/ansible/roles/varnish/handlers/main.yml b/lib/ansible/roles/varnish/handlers/main.yml index 6e63676d..03535a55 100644 --- a/lib/ansible/roles/varnish/handlers/main.yml +++ b/lib/ansible/roles/varnish/handlers/main.yml @@ -1,4 +1,6 @@ --- -- name: restart varnish - service: name=varnish state=restarted - become: true +- name: restart varnish + service: + name: varnish + state: restarted + become: true diff --git a/lib/ansible/roles/varnish/tasks/main.yml b/lib/ansible/roles/varnish/tasks/main.yml index f67b3ef2..00445398 100644 --- a/lib/ansible/roles/varnish/tasks/main.yml +++ b/lib/ansible/roles/varnish/tasks/main.yml @@ -1,21 +1,29 @@ --- -- name: Install Varnish packages - apt: pkg={{ item }} state=present - with_items: "{{ varnish_packages }}" - become: true +- name: Install Varnish packages + apt: + pkg: "{{ item }}" + state: present + with_items: "{{ varnish_packages }}" + become: true -- name: Create Varnish directory structure - file: path={{ item }} state=directory mode=0644 - become: true +- name: Create Varnish directory structure + file: + path: "{{ item }}" + state: directory + mode: '0644' + become: true with_items: - /etc/varnish - /etc/varnish/conf.d - /etc/varnish/conf.d/fetch - /etc/varnish/conf.d/receive -- name: Copy Varnish configuration files - copy: src=etc-varnish/{{ item }} dest=/etc/varnish/{{ item }} mode=0644 - become: true +- name: Copy Varnish configuration files + copy: + src: etc-varnish/{{ item }} + dest: /etc/varnish/{{ item }} + mode: '0644' + become: true with_items: - conf.d/fetch/wordpress.vcl - conf.d/receive/wordpress.vcl @@ -23,51 +31,69 @@ - custom.backend.vcl - production.vcl -- name: Copy Varnish script - copy: src=etc-default-varnish dest=/etc/default/varnish mode=0644 - become: true +- name: Copy Varnish script + copy: + src: etc-default-varnish + dest: /etc/default/varnish + mode: '0644' + become: true notify: - restart apache - restart varnish -- stat: path=/etc/apache2/mods-enabled/rpaf.load - register: rpaf_load +- stat: + path: /etc/apache2/mods-enabled/rpaf.load + register: rpaf_load -- name: Disable apache module "rpaf" (if installed) - command: a2dismod rpaf - when: rpaf_load.stat.exists - become: true - notify: restart apache +- name: Disable apache module "rpaf" (if installed) + command: a2dismod rpaf + when: rpaf_load.stat.exists + become: true + notify: restart apache -- name: Configure apache module "remoteip" - copy: src=remoteip.conf dest=/etc/apache2/mods-available/remoteip.conf mode=0644 - become: true +- name: Configure apache module "remoteip" + copy: + src: remoteip.conf + dest: /etc/apache2/mods-available/remoteip.conf + mode: '0644' + become: true -- name: Enable apache module "remoteip" - command: a2enmod remoteip - become: true - notify: restart apache +- name: Enable apache module "remoteip" + command: a2enmod remoteip + become: true + notify: restart apache -- name: Change Apache NameVirtualHost 80 => 8080 (2.2) - lineinfile: regexp='^NameVirtualHost' line='NameVirtualHost *:8080' dest=/etc/apache2/ports.conf backup=yes +- name: Change Apache NameVirtualHost 80 => 8080 (2.2) + lineinfile: + regexp: '^NameVirtualHost' + line: 'NameVirtualHost *:8080' + dest: /etc/apache2/ports.conf + backup: yes notify: - restart apache - restart varnish - when: apache_version.stdout == '2.2' - become: true + when: apache_version.stdout == '2.2' + become: true -- name: Change Apache Listen 80 => 8080 - lineinfile: regexp='^Listen' line='Listen 8080' dest=/etc/apache2/ports.conf backup=yes +- name: Change Apache Listen 80 => 8080 + lineinfile: + regexp: '^Listen' + line: 'Listen 8080' + dest: /etc/apache2/ports.conf + backup: yes notify: - restart apache - restart varnish - become: true + become: true -- name: Change VirtualHosts from 80 => 8080 - lineinfile: regexp='^' line='' dest=/etc/apache2/sites-available/{{ "%03d" | format(item.key_1) }}-{{ item.value }}.{{ domain }}.conf +- name: Change VirtualHosts from 80 => 8080 + lineinfile: + regexp: '^' + line: '' + dest: /etc/apache2/sites-available/{{ "%03d" | format(item.key_1) }}-{{ item.value }}.{{ domain }}.conf with_nested_dict: "{{ apache_vhosts }}" - when: item.key_0 == stage + when: item.key_0 == stage notify: - restart apache - restart varnish - become: true + become: true diff --git a/lib/ansible/roles/wp-cli/tasks/main.yml b/lib/ansible/roles/wp-cli/tasks/main.yml index d6567a3a..40dff16f 100644 --- a/lib/ansible/roles/wp-cli/tasks/main.yml +++ b/lib/ansible/roles/wp-cli/tasks/main.yml @@ -1,10 +1,21 @@ # see evolution/wordpress#126 -- name: Fetch latest wp-cli (from control) - local_action: get_url dest=/tmp/wp-cli url=https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar force=yes +- name: Fetch latest wp-cli (from control) + local_action: + module: get_url + dest: /tmp/wp-cli + url: https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar + force: yes -- name: Copy latest wp-cli to remote - copy: src=/tmp/wp-cli dest=/usr/local/bin/wp force=yes mode=0755 - become: true +- name: Copy latest wp-cli to remote + copy: + src: /tmp/wp-cli + dest: /usr/local/bin/wp + force: yes + mode: '0755' + become: true -- name: Remove latest wp-cli in tmp (from control) - local_action: file dest=/tmp/wp-cli state=absent +- name: Remove latest wp-cli in tmp (from control) + local_action: + module: file + dest: /tmp/wp-cli + state: absent From 173ae1605355f7c8aa709b886976fa941bd7532b Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Wed, 23 Nov 2016 12:12:31 -0800 Subject: [PATCH 63/66] Ensure outdated node package is removed, along with any source lists --- lib/ansible/roles/node/tasks/main.yml | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/ansible/roles/node/tasks/main.yml b/lib/ansible/roles/node/tasks/main.yml index b2ce5a02..fb9ece8b 100644 --- a/lib/ansible/roles/node/tasks/main.yml +++ b/lib/ansible/roles/node/tasks/main.yml @@ -3,11 +3,28 @@ apt_repository: repo: 'ppa:chris-lea/node.js' state: absent + register: old_node become: true +- name: Uninstall old node if necessary + apt: + pkg: nodejs + state: absent + become: true + when: old_node.changed + +- name: Find old node source lists to remove + shell: ls -1 /etc/apt/sources.list.d/*chris?lea?node_js*.list + register: old_source_lists + ignore_errors: yes + become: true + when: old_node.changed + - name: Ensure removal of old node source lists - shell: rm -f /etc/apt/sources.list.d/chris-lea-node_js-*.list - ignore_errors: true + file: + path: "{{ item }}" + state: absent + with_items: "{{ old_source_lists.stdout_lines | default([]) }}" become: true - name: Fetch Nodesource apt key (from control) From d609acb3789e862be562307699f5b5f6a7e58086 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Wed, 23 Nov 2016 12:13:55 -0800 Subject: [PATCH 64/66] Output unescaped values in provision playbook template --- lib/yeoman/templates/lib/ansible/provision.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/yeoman/templates/lib/ansible/provision.yml b/lib/yeoman/templates/lib/ansible/provision.yml index c3e13ea6..58e4442a 100644 --- a/lib/yeoman/templates/lib/ansible/provision.yml +++ b/lib/yeoman/templates/lib/ansible/provision.yml @@ -15,9 +15,9 @@ # Optional Features <% if (props.ssl) { %>- pound # (Optional) SSL support & decryption<% } %><% props.roles.map(function(role) { %> - <%= role.checked ? '-' : '#' %> <%= role.value %><% }) %> -<% if (props.newrelic) { %> - { role: newrelic, sudo: yes, when: stage == 'production' } # (Optional) New Relic application/server monitoring -<% } %><% if (props.datadog) { %> - { role: Datadog.datadog, sudo: yes, when: stage == 'production' } # (Optional) Datadog monitoring support + <%- role.checked ? '-' : '#' %> <%- role.value %><% }) %> +<% if (props.newrelic) { %> - { role: newrelic, become: true, when: stage == 'production' } # (Optional) New Relic application/server monitoring +<% } %><% if (props.datadog) { %> - { role: Datadog.datadog, become: true, when: stage == 'production' } # (Optional) Datadog monitoring support <% } %> # /Optional Features - cleanup # (Required) Generate init.d for installed evolution services From db6b394a3d94e8e48513c5d51275a99dce94cf8d Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Wed, 23 Nov 2016 13:11:34 -0800 Subject: [PATCH 65/66] Use absolute paths in post-deploy bower install Effectively the same as the `within` notation, but this is more explicit and easier to understand, IMHO --- lib/yeoman/templates/lib/capistrano/deploy.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/yeoman/templates/lib/capistrano/deploy.rb b/lib/yeoman/templates/lib/capistrano/deploy.rb index 149319a8..e2128f31 100644 --- a/lib/yeoman/templates/lib/capistrano/deploy.rb +++ b/lib/yeoman/templates/lib/capistrano/deploy.rb @@ -25,11 +25,9 @@ end after :updated, :bower_install do on roles(:web) do - within release_path do - bower_exists = test "[ -f ./bower.json ]" - if bower_exists - execute "bower install" - end + bower_exists = test "[ -f #{release_path}/bower.json ]" + if bower_exists + execute "cd #{release_path} && bower install" end end end From 0406d77a0c959965b9fec78adcfa3a33f294d613 Mon Sep 17 00:00:00 2001 From: Evan Kaufman Date: Wed, 23 Nov 2016 13:24:07 -0800 Subject: [PATCH 66/66] Detect and remove otherwise empty bowerrc file, after removing postinstall --- lib/yeoman/index.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/yeoman/index.js b/lib/yeoman/index.js index 5a4dce32..69ab6a3c 100644 --- a/lib/yeoman/index.js +++ b/lib/yeoman/index.js @@ -643,7 +643,17 @@ var WordpressGenerator = yeoman.Base.extend({ var rcContents = this.fs.readJSON(rcfile); if (rcContents.scripts.postinstall == './bower_components/evolution-wordpress/lib/yeoman/bin/postinstall') { delete rcContents.scripts.postinstall; - fs.writeFileSync(rcfile, JSON.stringify(rcContents, null, 2)); + + if (!Object.keys(rcContents.scripts).length) { + delete rcContents.scripts; + } + + if (!Object.keys(rcContents).length) { + fs.unlinkSync(rcfile); + } + else { + fs.writeFileSync(rcfile, JSON.stringify(rcContents, null, 2)); + } } } catch (e) {};