Skip to content

Commit

Permalink
improved init and build systems
Browse files Browse the repository at this point in the history
  • Loading branch information
dustinrue committed Jul 5, 2024
1 parent cb6d5c9 commit 80092f3
Show file tree
Hide file tree
Showing 12 changed files with 230 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ deploy_production:
MULTI_DEV_ENVIRONMENT: "{{branch}}"
WORDPRESS_VERSION: {{wordpress_version}}
GIT_URL: {{deploy_to}}
EXCLUDES: {{deploy_file_excludes}}
EXCLUDES: {{rsync_file_excludes}}
allow_failure: false
only:
refs:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ deploy_{{branch}}:
MULTI_DEV_ENVIRONMENT: "{{branch}}"
WORDPRESS_VERSION: {{wordpress_version}}
GIT_URL: {{deploy_to}}
EXCLUDES: {{deploy_file_excludes}}
EXCLUDES: {{rsync_file_excludes}}
allow_failure: false
only:
refs:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ deploy_production:
variables:
DESTINATION: {{deploy_to}}
SUBDIR: {{deploy_to_subdir}}
EXCLUDES: {{deploy_file_excludes}}
EXCLUDES: {{rsync_file_excludes}}
only:
refs:
- {{branch}}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ deploy_{{branch}}:
variables:
DESTINATION: {{deploy_to}}
SUBDIR: {{deploy_to_subdir}}
EXCLUDES: {{deploy_file_excludes}}
EXCLUDES: {{rsync_file_excludes}}
only:
refs:
- {{branch}}
21 changes: 17 additions & 4 deletions packages/toolkit/project/local/scripts/build.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Add builds scripts here. This script will be run from the root of your project (same directory as .tenup.yml).
#!/usr/bin/env bash -l
# NOTE: you should keep the above line, at line 1. Only modify if you know what you are doing.

nvm install
node -v
npm install
# You should use npx 10up-toolkit build to build your project. When you do, there are a number of things
# you get "for free" including nvm handling and the basics of building are handled automatically. You
# only need to provide additional build routines if the default build system doesn't quite get things
# right. Adding build scripts is easy. Create as many .sh files as you need in this scripts directory.

# Here is an example script you can use to get you started It assumes you are using a "modern" layout.

# change directories to your theme or plugin
pushd .

# run your build commands
echo "Hello World!"

# return to where we were so the next build script starts off from the same place
popd
179 changes: 173 additions & 6 deletions packages/toolkit/scripts/project/bash/build-setup.sh
Original file line number Diff line number Diff line change
@@ -1,13 +1,180 @@
#!/bin/bash
#!/usr/bin/env bash -l

maybe_init_nvm() {
# Various tasks to determine some things like what kind of project is this
# such as standard, wp-content rooted...something else?
function build:preflight {
# Check for a default, standard layout that has a wordpress directory
if [ -d wordpress ] && [ -d build ]; then # this is probably a standard setup
echo "Detected standard WordPress repository layout"
PROJECT_TYPE="standard"
WORDPRESS_BUILD_ROOT="wordpress/wp-content"
return
fi

# Check for a wp-content rooted style repository
if [ -d plugins ] || [ -d themes ]; then # this is probably a wp-root repo
echo "Detected wp-content rooted WordPress repository layout"
PROJECT_TYPE="wpcontent"
WORDPRESS_BUILD_ROOT="."
return
fi

}


# Routine to determine what version of WordPress to install
function build:version {

WORDPRESS_VERSION="latest"
if [ ${CI:-false} = "true" ]; then
if [ -z ${WORDPRESS_VERSION} ]; then
WORDPRESS_VERSION="latest"
fi
else
GIT_BRANCH=$(git branch --format='%(refname:short)' --show-current)
GIT_BRANCH_SLUG=$(utilities:create-gitlab-slug ${GIT_BRANCH})
ENVIRONMENT=$(yq eval '.environments | to_entries[] | select(.value.branch == "'${GIT_BRANCH_SLUG}'") | .key' ${TENUP_CI_FILE})

if [ ${ENVIRONMENT:-null} != "null" ]; then
WORDPRESS_VERSION=$(yq '.environments.'${ENVIRONMENT}'.wordpress_version' ${TENUP_CI_FILE})
fi
fi

if [ "${WORDPRESS_VERSION}" == "latest" ]; then
WORDPRESS_VERSION=$(curl -s https://api.wordpress.org/core/version-check/1.7/ | jq '.offers[0].current' | tr -d '"')
fi

echo ${WORDPRESS_VERSION}
}

function build:install {
build:preflight

# we use command in case wp-cli is installed as an alias
if [[ -z $(command -v wp) ]]; then
echo "wp-cli is not installed or in your path but it is required"
exit 1
fi

local WORDPRESS_VERSION=$(build:version)
echo "Installing WordPress version: ${WORDPRESS_VERSION}"

if [ ${PROJECT_TYPE} = "standard" ]; then
mkdir -p wordpress/wp-content
pushd wordpress
else
mkdir -p payload/wp-content
pushd payload
fi
wp core download --version=${WORDPRESS_VERSION} --skip-content --force
popd

}

function build:main {
set -eo pipefail

build:preflight

if [ $(find . -name .nvmrc | wc -l) -gt 0 ] && [ ! -f $NVM_DIR/nvm.sh ]; then
echo "This project requires nvm. Please install nvm and try again"
# don't call this script directly
if [ $(shopt -q login_shell) ]; then
echo "Please call this using build/local.sh rather than directly"
exit 1
fi

. $NVM_DIR/nvm.sh
# This is your "main" build file. By default, it builds a 10up/wp-scaffold style project
# but you are free to modify it as required for your project. Remember, you can also
# drop in any number of scripts and they will be run in alphabetical order AFTER main.sh

# detect if this is a standard layout or not

if [ -d wordpress/wp-content ]; then
pushd wordpress/wp-content
elif [ -d plugins ]; then
pushd . # go no where, we are already in the right spot
fi
if [ "${CI:-false}" = "true" ] && [ -f composer.json ]; then
if [ ! -f composer.lock ] && [ -f composer.json ]; then
echo "No composer.lock file detected. You should create/commit an up to date composer.lock file!"
exit 1
else
composer install --no-dev
fi
elif [ -f composer.json ]; then
composer install
fi


if [ -f package.json ]; then
# Ensure we have the correct node version installed
nvm install
nvm use

if [ "${CI:-false}" = "true" ] && [ -f package.json ]; then
if [ -f package-lock.json ]; then
npm ci
else
echo "No package-lock.json file detected. You should create/commit an up to date package-lock.json file!"
exit 1
fi
else
npm install
fi

npm run build
fi
popd
}

function build:local {
set -eo pipefail
# Create additional build scripts in the build directory with a .sh
# extension. They should do their work inside the wordpress directory.

# We always call main.sh first
build:main

# Then call any other drop in scripts next
for I in $(ls scripts/*sh)
do
. $I
done
}

# Perform a CI like build
function build:full {
set -eo pipefail

build:preflight
build:install
build:local

# This rsync will typically work but if you have integrated the CI Library
# into a non project template based project you should adjust it

# First determine if we are using a project rsync-exclude or the included one
if [ -f scripts/rsync-excludes.txt ]; then
RSYNC_EXCLUDES="scripts/rsync-excludes.txt"
fi

if [ ${PROJECT_TYPE} == "standard" ]; then
rsync -a --exclude-from=${RSYNC_EXCLUDES} wordpress/ payload/
else
for I in themes mu-plugins plugins
do
if [ -d $I ]; then
rsync -a --exclude-from=${RSYNC_EXCLUDES} $I/ payload/wp-content/$I
fi
done
fi

}

# Converts a git branch to a gitlab compatible slug
function utilities:create-gitlab-slug {
local VALUE=$(echo $1 | sed 's/[^a-zA-Z0-9]/-/g' | awk '{print tolower($0)}')

echo ${VALUE}
}

maybe_init_nvm
eval build:$@
2 changes: 1 addition & 1 deletion packages/toolkit/scripts/project/bash/create-payload.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ download https://wordpress.org/wordpress-${WORDPRESS_VERSION}.tar.gz wordpress.t
tar --strip-components=1 -zxmf wordpress.tar.gz -C .
rm wordpress.tar.gz

rsync -avz --exclude-from=$deploy_file_excludes_absolute $project_root/$deploy_from $deploy_to_subdir
rsync -avz --exclude-from=$rsync_file_excludes_absolute $project_root/$deploy_from $deploy_to_subdir
5 changes: 3 additions & 2 deletions packages/toolkit/scripts/project/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ const run = async () => {
process.exit(1);
}

const variables = getProjectVariables();
// combine project variables with actual environment variables
const variables = { ...getProjectVariables(), ...process.env };

if (!variables) {
log(chalk.red('No .tenup.yml found.'));
Expand All @@ -26,7 +27,7 @@ const run = async () => {
setEnvVariables(variables);

if (fs.existsSync(variables.build_script_path)) {
execSync(`. ${__dirname}/bash/build-setup.sh; . ${variables.build_script_path}`, {
execSync(`bash -l ${__dirname}/bash/build-setup.sh local`, {

Check warning

Code scanning / CodeQL

Shell command built from environment values Medium

This shell command depends on an uncontrolled
absolute path
.
stdio: 'inherit',
});
} else {
Expand Down
48 changes: 15 additions & 33 deletions packages/toolkit/scripts/project/create-payload.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,59 +4,41 @@ const chalk = require('chalk');
const { log } = console;

const fs = require('fs');
const {
getProjectRoot,
getProjectVariables,
setEnvVariables,
getEnvironmentFromBranch,
} = require('../../utils');
const { getProjectRoot, getProjectVariables, setEnvVariables } = require('../../utils');

const description = '10up-toolkit project create-payload <branch>';
const description = '10up-toolkit project build';

const run = async () => {
const branch = process.argv.slice(3)[0];

if (!branch || branch.match(/--/)) {
log(description);
log(chalk.red('No branch specified.'));
process.exit(1);
}

const root = getProjectRoot();

if (!root) {
log(chalk.red('This is not a project.'));
process.exit(1);
}

let variables = getProjectVariables();
// combine project variables with actual environment variables
const variables = { ...getProjectVariables(), ...process.env };

// FIXME: This is a hack to force "create-payload" to behave like ci
variables.CI = true;

if (!variables) {
log(chalk.red('No .tenup.yml found.'));
process.exit(1);
}

const matchedEnvironment = getEnvironmentFromBranch(branch, variables.environments);

if (!matchedEnvironment) {
log(chalk.red(`No environment found matching branch \`${branch}\`.`));
process.exit(0);
}

variables = { ...variables, ...matchedEnvironment };

log(`Creating payload for environment ${matchedEnvironment.environment}.`);

setEnvVariables(variables);

// First run build
await require('./build').run();

if (fs.existsSync(variables.create_payload_script_path)) {
execSync(`bash ${variables.create_payload_script_path}`, { stdio: 'inherit' });
if (fs.existsSync(variables.build_script_path)) {
execSync(`bash -l ${__dirname}/bash/build-setup.sh full`, {

Check warning

Code scanning / CodeQL

Shell command built from environment values Medium

This shell command depends on an uncontrolled
absolute path
.
stdio: 'inherit',
});
} else {
log(chalk.red('No build script found.'));
process.exit(1);
}

log(chalk.green('Payload created.'));
log(chalk.green('Build complete.'));
};

module.exports = { run, description };
22 changes: 15 additions & 7 deletions packages/toolkit/scripts/project/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,9 @@ const run = async () => {

const toolkitPath = resolve(`${__dirname}/../../`);
const initPath =
projectLayout === 'modern' ? `${resolve(cliPath)}${path.sep}wordpress` : resolve(cliPath);
projectLayout === 'modern'
? `${resolve(cliPath)}${path.sep}wordpress${path.sep}wp-content`
: resolve(cliPath);
template = results.template || template;

const projectName = results.name || name;
Expand Down Expand Up @@ -205,14 +207,20 @@ const run = async () => {
const pluginPath = `${initPath}/plugins/${projectNameLowercaseHypen}-plugin`;
const muPluginPath = `${initPath}/mu-plugins/${projectNameLowercaseHypen}-plugin`;

// Copy contents of toolkitPath/project/local into initPath
// Copy contents of toolkitPath/project/local into cliPath
execSync(`rsync -rc "${toolkitPath}/project/local/" "${cliPath}"`);

Check warning

Code scanning / CodeQL

Shell command built from environment values Medium

This shell command depends on an uncontrolled
absolute path
.
This shell command depends on an uncontrolled
absolute path
.
tenupComposerFiles.forEach((file) => {
const command = `composer install --working-dir=${path
.dirname(file)
.replace(`${initPath}`, './')
.replace('//', '/')}\n`;
fs.appendFileSync(`${cliPath}/scripts/build.sh`, command);
// skip wp-content building, that's free in the build scripts already
if (path.basename(path.dirname(file)) !== 'wp-content') {
const workingDir = path.dirname(file).slice(resolve(cliPath).length).replace('//', '/');
const command = `composer install --working-dir=.${workingDir}\n`;

Check failure on line 216 in packages/toolkit/scripts/project/init.js

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, 20)

'command' is assigned a value but never used

// FIXME: don't actually output the file, it results in brokeness
// fs.appendFileSync(
// `${cliPath}/scripts/build-${path.basename(path.dirname(file))}.sh`,
// command,
// );
}
});

if (!skipComposer) {
Expand Down
4 changes: 2 additions & 2 deletions packages/toolkit/utils/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ const getProjectVariables = (path = '.') => {
data.build_script_path = `${projectRoot}/scripts/build.sh`;
}

data.deploy_file_excludes = `./scripts/deploy-excludes.txt`;
data.deploy_file_excludes_absolute = `${projectRoot}/scripts/deploy-excludes.txt`;
data.rsync_file_excludes = `./scripts/rsync-excludess.txt`;
data.rsync_file_excludes_absolute = `${projectRoot}/scripts/rsync-excludess.txt`;

data.toolkit_path = resolve(`${__dirname}/../`);

Expand Down

0 comments on commit 80092f3

Please sign in to comment.