Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

General deploy #64

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e9aa744
feat: add deploy to live for general
generalredneck Dec 1, 2023
23b4411
fix: fix generic deploy branch name
generalredneck Dec 1, 2023
97a536e
fix: updating workflow and fixing deploy script
generalredneck Dec 1, 2023
365a6f6
remove .gitignore files
generalredneck Dec 1, 2023
3c73fc3
fix: fixing ifstatement
generalredneck Dec 1, 2023
514af1d
fix: fixing backup script
generalredneck Dec 1, 2023
81a0a4c
fix: fixing drush scripts
generalredneck Dec 1, 2023
612e979
feat: symlinking to newest for simplicity in scripting
generalredneck Jan 29, 2024
2348608
fix passing arguments
generalredneck Jun 30, 2024
e426ff3
fixing variable typo
generalredneck Jun 30, 2024
2486abe
Merge branch 'main' into general-deploy
generalredneck Oct 11, 2024
4df8e24
fix: allow ssh key forwarding
generalredneck Oct 11, 2024
5fb1ea8
Merge branch 'main' of https://github.com/fourkitchens/pots into gene…
generalredneck Oct 11, 2024
4894615
fix: fixing backups
generalredneck Oct 11, 2024
d9c2f9b
fix: switching to drushcmd for backup and double checking for it
generalredneck Oct 11, 2024
4014780
chore: fix markdown lint errors
generalredneck Oct 11, 2024
a42e66f
feat: allow use of alias file to store info
generalredneck Oct 11, 2024
00aadc2
fix: assign value of drush to REMOTE_PROJECT_ROOT
generalredneck Oct 11, 2024
3b03078
fix: various quoting issues and script updates
generalredneck Oct 11, 2024
f837105
fix: forcing strict hostkeychecking off
generalredneck Oct 16, 2024
a506378
fix: fix deploy branch reference
generalredneck Oct 16, 2024
a9374a4
chore: remove debugging
generalredneck Oct 16, 2024
043f303
doc: added some docs
generalredneck Oct 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
280 changes: 191 additions & 89 deletions README.MD

Large diffs are not rendered by default.

68 changes: 61 additions & 7 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,26 @@ jobs:
- deploy-to-pantheon-env:
environment: 'live'

deploy_to_live_general:
<<: *defaults
steps:
- checkout
- run:
name: setup-environment-vars
command: |
if [ -f "./.circleci/scripts/set-environment" ]; then
./.circleci/scripts/set-environment
else
./vendor/fourkitchens/pots/scripts/set-environment
fi
- run:
name: Deploy to live
command: |
if [ -f "./.circleci/scripts/deploy-to-live" ]; then
./.circleci/scripts/deploy-to-live
else
./vendor/fourkitchens/pots/scripts/general/deploy-to-live
fi

security_updates_check:
<<: *defaults
Expand All @@ -332,6 +352,7 @@ jobs:
- checkout
- php/install-composer
- php/install-packages
- add_ssh_keys
- run:
name: setup-environment-vars
command: |
Expand All @@ -340,7 +361,6 @@ jobs:
else
./vendor/fourkitchens/pots/scripts/set-environment
fi
- add_ssh_keys
- run: composer audit --format=json > /tmp/projects_to_update.json 2>/dev/null || true
- run:
name: Check security updates
Expand Down Expand Up @@ -444,22 +464,56 @@ workflows:
- 'master'
build-deploy-acquia:
when:
not:
equal: [ pantheon, << pipeline.parameters.host-variant >> ]
equal: [ acquia, << pipeline.parameters.host-variant >> ]
jobs:
- static_tests
- build
- deploy:
requires:
- static_tests
- build
- release:
requires:
- deploy
filters:
branches:
only:
- 'main'
- 'master'
build-deploy-general:
when:
equal: [ general, << pipeline.parameters.host-variant >> ]
jobs:
- static_tests:
filters:
branches:
ignore: /^deploy-.*$/
- build:
filters:
branches:
ignore: /^deploy-.*$/
- deploy:
requires:
- static_tests
- build
filters:
branches:
ignore: /^deploy-.*$/
- approve_deploy_to_live:
type: approval
filters:
branches:
only:
- 'deploy-main'
- 'deploy-master'
- deploy_to_live_general:
requires:
- approve_deploy_to_live
filters:
branches:
only:
- main
- master
- develop
- /release-.*/
- 'deploy-main'
- 'deploy-master'
- release:
requires:
- deploy
Expand Down
4 changes: 3 additions & 1 deletion scripts/general/deploy
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ sed -i '1,/# :::::::::::::::::::::: cut ::::::::::::::::::::::/d' .gitignore
# returns all files/dirs that are NOT dot (hidden). This protects our repos'
# .git folder from being blown away.
find ./* -type d | grep .git | xargs rm -rf
find ./* -type f | grep .gitignore | xargs rm -rf

# Remove unwanted gitignores here. Follow the example below.
# Remove simplesamlphp .gitignore which would cause our config and metadata
Expand All @@ -20,5 +21,6 @@ find ./* -type d | grep .git | xargs rm -rf
# Commit and push to a "deploy" branch.
git add .
git commit -am "Built assets."
git push origin $CIRCLE_BRANCH:$CIRCLE_BRANCH-deploy -f --tags
DEPLOY_BRANCH=deploy-$CIRCLE_BRANCH
git push origin $CIRCLE_BRANCH:$DEPLOY_BRANCH -f --tags
echo "If deployment was successful, an artifact should be availible in the origin repo at $CIRCLE_BRANCH-deploy".
129 changes: 129 additions & 0 deletions scripts/general/deploy-to-live
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#!/bin/bash

set -eo pipefail

# Allow CircleCI to forward any SSH Keys so the remote server can pull from git.
mkdir -p ~/.ssh
printf "Host *\nForwardAgent yes\nStrictHostKeyChecking no" >> ~/.ssh/config

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
if [[ -z "$DOCROOT" ]]; then
DOCROOT=web
fi
if [[ -z "$DRUSH_CMD" ]]; then
DRUSH_CMD='./vendor/bin/drush'
fi
if [[ -z "$SYNC_CONFIG" ]]; then
SYNC_CONFIG="YES"
fi
if [[ -z "$CANONICAL_ENV" ]]; then
CANONICAL_ENV=live
fi

# Check for an SSH command to see if we need to scavange for a aliases file.
if [[ -z "$SSH_COMMAND_LIVE" ]]; then
# Default to using `drush @self.$REMOTE_ENV_NAME`
if [ -n "$REMOTE_ENV_NAME" ] && $DRUSH_CMD sa "@self.$REMOTE_ENV_NAME"; then
DRUSH_SITE_ALIAS=$REMOTE_ENV_NAME;
# Default to using `drush @self.live`
elif $DRUSH_CMD sa @self.live; then
DRUSH_SITE_ALIAS="live";
REMOTE_ENV_NAME="live"
# Default to using `drush @self.prod`
elif $DRUSH_CMD sa @self.prod; then
DRUSH_SITE_ALIAS="prod";
REMOTE_ENV_NAME="prod"
fi
# Install JQ so we can parse json from drush to get information about the
# alias.
if ! command -v jq &> /dev/null; then
sudo apt-get update -y
sudo apt-get install jq
fi
# Rebuilds the SSH command and gets reasonable defaults from the drush alias.
DRUSH_SSH_OPTIONS="$( $DRUSH_CMD sa "@self.$DRUSH_SITE_ALIAS" --format=json | jq -r ".[\"@self.$DRUSH_SITE_ALIAS\"].ssh.options" )"
if [[ "$DRUSH_SSH_OPTIONS" == "null" ]]; then
DRUSH_SSH_OPTIONS="-o 'StrictHostKeyChecking no'"
fi

# The SSH User in the alias file.
DRUSH_USER="$( $DRUSH_CMD sa "@self.$DRUSH_SITE_ALIAS" --format=json | jq -r ".[\"@self.$DRUSH_SITE_ALIAS\"].user" )"
if [[ "$DRUSH_USER" == "null" ]]; then
echo "You must specify a user in your site alias yaml or set \$SSH_COMMAND_LIVE"
exit 1
fi

# The Host we need to connect to from the alias file.
DRUSH_HOST="$( $DRUSH_CMD sa "@self.$DRUSH_SITE_ALIAS" --format=json | jq -r ".[\"@self.$DRUSH_SITE_ALIAS\"].host" )"
if [[ "$DRUSH_HOST" == "null" ]]; then
echo "You must specify a host in your site alias yaml or set \$SSH_COMMAND_LIVE"
exit 1
fi

# Lets grab the remote drush command if it's specified. If it's not, this
# falls through and makes the remote drush path `./vendor/bin/drush` down
# at the bottom of this script.
if [[ -z "$REMOTE_DRUSH_CMD" ]]; then
REMOTE_DRUSH_CMD="$( $DRUSH_CMD sa "@self.$DRUSH_SITE_ALIAS" --format=json | jq -r ".[\"@self.$DRUSH_SITE_ALIAS\"].paths.\"drush-script\"" )"
if [[ "$REMOTE_DRUSH_CMD" == "null" ]]; then
unset REMOTE_DRUSH_CMD;
else
# If we find the path, we need to make sure it's an absolute path so we
# know where it is because otherwise, it comes from a directory relative
# to what ever the root for the ssh user is set to.
case $REMOTE_DRUSH_CMD in
/*) echo "absolute path" ;;
*) echo "The remote drush script is realitive in the site alias. This likely means it's from the home directory. I have no idea how to convert that to be from the project directory. Use an absolute path."; exit 1 ;;
esac
fi
fi

# In some cases the webroot provided by drush is a symlink in a totally
# different folder, so lets not clobber what ever someone set.
if [ -n "$DRUSH_SITE_ALIAS" ] && [ -z "$REMOTE_PROJECT_ROOT" ]; then
REMOTE_PROJECT_ROOT="$( $DRUSH_CMD sa "@self.$DRUSH_SITE_ALIAS" --fields root | grep "root:.*\$" | sed "s/[[:space:]]*root\: \(.*\)\/$DOCROOT/\1/g" )"
echo "REMOTE_PROJECT_ROOT set to $REMOTE_PROJECT_ROOT"
fi

# We have to break this out instead of using `drush ssh` because drush ssh
# won't let us inject a local script remotely. like we do at the bottom of
# this script. This may not be an exact replica of how Drush gets their
# ssh command. 🛑 There be 🐉 here.
SSH_COMMAND_LIVE="ssh -t $DRUSH_SSH_OPTIONS $DRUSH_USER@$DRUSH_HOST"

fi
if [[ -z "$REMOTE_PROJECT_ROOT" ]]; then
echo "You must define \$REMOTE_PROJECT_ROOT as an environment variable or provide a drush site alias for @self.live with ssh information."
exit 1;
fi
if [[ -z "$REMOTE_ENV_NAME" ]]; then
REMOTE_ENV_NAME="live"
fi

if [[ -z "$DEPLOY_BRANCH" ]]; then
DEPLOY_BRANCH="$CIRCLE_BRANCH"
fi

if [[ -z "$BACKUP_SCRIPT_PATH" ]]; then
BACKUP_SCRIPT_PATH="$SCRIPT_DIR/remote/backup"
fi
if [[ -z "$DEPLOY_SCRIPT_PATH" ]]; then
DEPLOY_SCRIPT_PATH="$SCRIPT_DIR/remote/remote_deploy"
fi
if [[ -z "$REMOTE_BACKUP_DIRECTORY" ]]; then
REMOTE_BACKUP_DIRECTORY="$REMOTE_PROJECT_ROOT/backups"
fi
if [[ -z "$REMOTE_DRUSH_CMD" ]]; then
REMOTE_DRUSH_CMD="./vendor/bin/drush"
fi

if [[ $REMOTE_ENV_NAME == "prod" ]] || [[ $REMOTE_ENV_NAME == "live" ]]; then
$SSH_COMMAND_LIVE "bash -s " < "$BACKUP_SCRIPT_PATH" "$REMOTE_ENV_NAME" "$REMOTE_PROJECT_ROOT" "$REMOTE_BACKUP_DIRECTORY" "$REMOTE_DRUSH_CMD";
else
#TODO Add ELSE logic here to pull backup from production to another enviornment
echo "Creating a backup from $CANONICAL_ENV to import into $REMOTE_ENV_NAME."
#Might be able to do s a drush-sync here. consider that the other env may not be on the same server.
#ssh $SSH_COMMAND_DEV "bash -s " < "$BACKUP_SCRIPT_PATH" "$CANONICAL_ENV" "$CANONICAL_REMOTE_PROJECT_ROOT" "$REMOTE_BACKUP_DIRECTORY" "$REMOTE_DRUSH_CMD";;
echo "Importing a backup from the canonical environment to $REMOTE_ENV_NAME"
fi
$SSH_COMMAND_LIVE "bash -s " < "$DEPLOY_SCRIPT_PATH" "$REMOTE_ENV_NAME" "$REMOTE_PROJECT_ROOT" "$DEPLOY_BRANCH" "$DOCROOT" "$REMOTE_DRUSH_CMD" "$SYNC_CONFIG";
58 changes: 58 additions & 0 deletions scripts/general/remote/backup
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/bin/bash

set -eo pipefail

REMOTE_ENV_NAME="$1"
HOSTING_PATH="$2"
BACKUP_DIRECTORY="$3"
DRUSH_CMD="$4"

if [[ -z "$REMOTE_ENV_NAME" ]]; then
echo "Argument 1: Remote Env Name is missing."
exit 1
fi
if [[ -z "$HOSTING_PATH" ]]; then
echo "Argument 2: Hosting Path is missing."
exit 1
fi
if [[ -z "$BACKUP_DIRECTORY" ]]; then
BACKUP_DIRECTORY="$HOME/backups"
fi
if [[ -z "$DRUSH_CMD" ]]; then
DRUSH_CMD='./vendor/bin/drush'
fi

echo "Moving to $HOSTING_PATH"
cd "$HOSTING_PATH"


if $DRUSH_CMD status | grep "Drupal version"; then
echo "Drush will be run as '$DRUSH_CMD'"
else
echo "$DRUSH_CMD is failing to bootstrap drupal. The build may not be complete. Aborting."
exit 1;
fi

if [[ -f ./vendor/bin/drush ]]; then
if [[ ! -d "$BACKUP_DIRECTORY" ]]; then
echo "BACKUP DIRECTORY $BACKUP_DIRECTORY doesn't exit. Attempting to create it."
mkdir -p "$BACKUP_DIRECTORY"
else
echo "BACKUP DIRECTORY $BACKUP_DIRECTORY does exit. Moving on."
fi
BACKUP_FILE="$BACKUP_DIRECTORY/$REMOTE_ENV_NAME-$( date +"%F_%T" ).sql.gz"
echo "Backing up DB for $HOSTING_PATH at $BACKUP_FILE"

if [ -d "$BACKUP_DIRECTORY" ] && $DRUSH_CMD sql:dump --structure-tables-list=cache,cache_* --extra-dump=--no-tablespaces | gzip > "$BACKUP_FILE" && [ -s "$BACKUP_FILE" ]; then
echo "Backup successful"
else
echo "A backup was not successfully made."
exit 1;
fi
if [ -f "$BACKUP_DIRECTORY/newest.sql.gz" ]; then
rm "$BACKUP_DIRECTORY/newest.sql.gz"
fi
ln -s "$BACKUP_FILE" "$BACKUP_DIRECTORY/newest.sql.gz"
else
echo "./vendor/bin/drush doesn't exist. Must be the first time a deployment has ever happened."
fi
31 changes: 31 additions & 0 deletions scripts/general/remote/drush-commands
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash

set -eo pipefail
HOSTING_PATH=$1
DRUSH_CMD=$2
SYNC_CONFIG=$3

if [[ -z "$DRUSH_CMD" ]]; then
DRUSH_CMD='./vendor/bin/drush'
fi

echo "Starting environment deploy commmands."
$DRUSH_CMD updb -y
echo "Clearing Drupal cache."
$DRUSH_CMD cr
# If exported configuration is available, then import it.
if [[ "$SYNC_CONFIG" != "NO" ]]; then
if [ -f "./.circleci/scripts/drush-config-import" ]; then
./.circleci/scripts/drush-config-import
else
"$( dirname $0 )/drush-config-import"
fi
else
echo "SYNC_CONFIG is set to 'NO'. Leaving configuration alone."
fi

# We make the assummption that this script is being run from the project root.
# Allow for post deployment hooks.
if [ -f "./.circleci/scripts/post-drush-commands" ]; then
./.circleci/scripts/post-drush-commands
fi
19 changes: 19 additions & 0 deletions scripts/general/remote/drush-config-import
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash

set -eo pipefail

if [[ -z "$DRUSH_CMD" ]]; then
DRUSH_CMD='./vendor/bin/drush'
fi

# Check for a system.site.yml file somewhere in the config directory.
if find ./config -name "system.site.yml" | grep "./config" -q ; then
echo "Importing Configuration"
$DRUSH_CMD config-import --yes
else
echo "We didn't import any configuration."
fi

# Clear Drupal cache
echo "Clearing Drupal cache again."
$DRUSH_CMD cr
Loading