Static Site Deployment

Author Message

Russell Michell

Tuesday 06 January 2009 2:01:36 pm

This subject has been touched upon before, and at least once by myself. I'd like to ask for feedback relating to my successful efforts at 'deploying' an eZ site to flat HTML files:

The current version of ez publish contains a very simple script for creating an 'offline' version of an ezpublish website. It is also quite limited, as are many such systems in other CMS's.

We needed a much more advanced method of doing this to provide an identical off-line version of our ezpublish site and so our solution also grabs background-images used in CSS and fetches RSS files.

In order to achieve this we've created 2 new, and modified 3 existing files:

<b>New Files:</b>

* <b>ez-deploy.sh</b>

This is a bash script that invokes <b>wget</b> and if necessary - <b>sed</b> - to fetch and post-process an ez website from a pre-specified URL.

#!/bin/bash
# Shell script to deploy an eZ Publish website invoked from ezpublish interface
# Russell Michell May/Nov 2008

date1=`date +%s`

#-----------------
# Sanity checking:
#-----------------

if [ ! $1 -a ! $2 ]
then
        echo "Error: Incorrect arguments passed to script: $0"
        echo "Arg 1: <url-to-fetch>"
        echo "Arg 2: <local-dir-to-stuff-things-into>"
	exit
else
	URL=$1 #The URL to fetch
	DIR=$2 #The dir to pile everything into locally
fi

#-----------------------------------------
# Define array of virtual-dirs to exclude:
#-----------------------------------------

EXCDir[0]="/duty/user"
EXCDir[1]="/duty/ezinfo"

for exclusion in "${EXCDir[@]}"
	do
	NoDirLIST+="$exclusion,"
done

# Remove trailing comma: ("%%" means "delete FROM the RIGHT, TO the LAST instance of what follows")
NoDirLIST=${NoDirLIST%,*}

#------------------------
# Build the wget command:
#------------------------

CMD="wget -Emp" 			# -m recursion, time-stamping. -E converts pages .* to .html. -p download all inline files (imgs, css etc)
CMD="$CMD -l 10" 			# -l recursion depth (5 is default)
CMD="$CMD -nH"				# -nH disables host-prefixed directories upon download	
CMD="$CMD -k"				# -k Convert the links in the document to make them suitable for local viewing (inc images, styles, js etc)
CMD="$CMD -P$DIR" 			# The path to the local directory to save stuff to
CMD="$CMD -X $NoDirLIST"  			# Exclude predefined dirs in $NoDirLIST from the download
CMD="$CMD -np"				# -np Contents below a certain hierarchy will be downloaded only
CMD="$CMD --follow-ftp"			# --follow-ftp Follows ftp:// protocol hyperlinks in webpages
CMD="$CMD --no-cache" 			# --no-cache ensure latest page/file-versions are always requested

# To log or not to log?
if [ $3 ]
then
	LOG=" -a $3"
	CMD="$CMD $LOG"
else
	LOG=""
fi

# Appends an extra slash if one not passed in $URL
lastchar=`expr substr $URL ${#URL} 1`
if [ $lastchar != '/' ]
then
	CMD="$CMD -q $URL/"
	IMGURL=$URL
else
	CMD="$CMD -q $URL"
	IMGURL=${URL:0: (${#URL} -1)} # equiv to substr($URL,0,strlen($URL)-1) in PHP
fi

# Do it, do it:
$CMD

#----------------------------------------------------------------
# WGET won't parse .css files for background images - get manually:
#----------------------------------------------------------------

IMGURL="${IMGURL/\/duty//}" #Lose my siteaccess from the URL to get images
wget -m -nH -P$DIR $IMGURL/extension/duty/design/ezwebin/images/$LOG
wget -m -nH -P$DIR $IMGURL/var/ezwebin_site/storage/images/media/images/$LOG

#-----------------
# Post Processing:
#-----------------

# For some reason wget won't create 'index.html' in directories, artifically create the homepage at least:
if [ -f "$DIR/duty.html" ] # 'duty' is the name of my siteaccess
then
	/bin/mv "$DIR/duty.html" "$DIR/index.html"
fi

# WGET won't parse RSS for URLs - process these manually:
/bin/find $DIR -type f -name '*.rss' -execdir /home/russellm/sbin/ezpublish/ez-deploy-sed.sh {} \;
# Using the wget -E flag has the side-effect of renaming text/plain pages to .txt.html, let's lose a few:
/bin/find $DIR -type f -name '*.txt*' -exec rm {} \;

date2=`date +%s`
TIME=$[ $date2-$date1 ]
echo Deployment process completed in: ${TIME}s

* <b>ez-deploy-sed.sh</b>

#!/bin/bash
# wget won't parse RSS files. Post-process for static deployment:
# Russell Michell November 2008

if [ ! $1 ];
then
	exit 65
else
	/bin/sed '/:808[0-9]\/duty\/\?/s//\/cms-deploy\/ezpublish\/duty\//g' $1 > "$1.tmp"
	mv "$1.tmp" $1
fi

<b>Existing Files:</b>

* <b>settings/siteaccess/<my-access>/site.ini.append.php </b>

Added a new section: [DeploySettings] and 3 settings for it:

1: ShellScript=/path/to/sbin/ez-deploy.sh
2: ShellScriptArgTargetDir=/var/www/htdocs/cms-deploy/ezpublish/
# Keep the output from wget's "-a" flag
3: DeployLog=enabled

* <b>kernel/content/action.php</b>

Added an extra elseif clause on line 200 that invokes the shell script using exec():

// Invoke a shell-script to deploy a static version of an ezpublish website:
else if ( $http->hasPostVariable( 'SetDeploy' ) &&
$http->hasPostVariable( 'ContentObjectID' ) && $http->hasPostVariable( 'ContentNodeID' ) )
{
  $nodeID          = $http->postVariable( 'ContentNodeID' );
  $siteINI = eZINI::instance( 'site.ini' );
  $deployScript = $siteINI->variable( 'DeploymentSettings', 'ShellScript' );
  $deployScriptArgTargetDir = $siteINI->variable( 'DeploymentSettings', 'ShellScriptArgTargetDir' );
  $deployLogEnabled = $siteINI->variable( 'DeploymentSettings', 'DeployLog' );
  $deployScriptArgFetchURL = 'http://'.$siteINI->variable( 'SiteSettings', 'SiteURL' );

  // To log, or not to log:
  $logFile = '';
  if($deployLogEnabled == 'enabled')
  {
  // Pass optional 3rd argument (Path to log-dir) to shell script to tell wget to use the -a flag
  // This is hard-coded for now - how do you get the ez working dir??
  $logFile = '/var/www/htdocs/ez-DEV/var/log/deploy.log';
  }

  // the command to invoke wget via our shell script:
  $exec = "{$deployScript} {$deployScriptArgFetchURL} {$deployScriptArgTargetDir} {$logFile}";

  if(!exec($exec))
  {
    // Need a better error - get one...
    return $module->handleError( eZError::EZ_ERROR_KERNEL_ACCESS_DENIED, 'kernel' );
  }
  return $module->redirectToView( 'view', array( 'full', $nodeID, $languageCode ) );
}

* <b>design/<my-design>/override/templates/website_toolbar.tpl</b>

Added an extra <div> to the ezwebin toolbar in an override for website_toolbar.tpl so a button is displayed and editors can login, press it on any page
and the whole site is re-crawled and deployed:


<!-- Begin Static Deployment Button -->
<div id="ezwt-deploy">
  <form method="post" action={"content/action"|ezurl} class="right">
    <input type="hidden" name="HasMainAssignment" value="1" />
    <input type="hidden" name="ContentObjectID" value="{$content_object.id}" />
    <input type="hidden" name="NodeID" value="{$current_node.node_id}" />
    <input type="hidden" name="ContentNodeID" value="{$current_node.node_id}" />
    <input type="submit" name="SetDeploy" value="Deploy Me" />
  </form>
</div>
<!-- End Static Deployment Button -->

If anyone thinks this might be useful and would like to try this out on their ez installs, the code and modifications are all here. Maybe the ez Crew might consider improving eZ's core-code to incorporate this or simialr functionality in some future release?

Of course suggestions for improvement are always welcome, I imply no guarantee that this will work for everyone and it has not undergone any of the unit tests that a completed ez product or eZ code should always undergo.

<b>Questions/Possible Improvements</b>

* Restrict the display/action of the "Deploy Me" button in the toolbar to users with specific permissions
* Selectively deploy parts of the site at a time
* Transfer the array of exclusions from the shell-script to site.ini
* Report the time taken to deploy to the screen. At present, this is restricted to invoking ez-deploy.sh from the CLI
* Is there a way to do something like this without having to modify any files in 'kernel'? As maintaining something like this begins to get hard, even in SVN when you have to modify core-code.

Thanks a lot folks, keen to get feedback :-)
Russ

Russell Michell, Wellington, New Zealand.
We're building! http://www.theruss.com/blog/
I'm on Twitter: http://twitter.com/therussdotcom

Believe nothing, consider everything.

kracker (the)

Tuesday 06 January 2009 6:03:21 pm

Great Job!

Cheers,
<i>//kracker

Tim & Eric Awesome Show</i>

Member since: 2001.07.13 || http://ezpedia.se7enx.com/

Sébastien Antoniotti

Wednesday 07 January 2009 12:36:28 am

Hi !

<i>* Is there a way to do something like this without having to modify any files in 'kernel'? As maintaining something like this begins to get hard, even in SVN when you have to modify core-code.</i>

Maybe you can run your kernel/content/action.php specific lines into a custom module dedicated for the static export.

Like this, the php part of your improvment can be put on a SVN.

Seb

eZ Publish Freelance
web : http://www.webaxis.fr

Heath

Wednesday 07 January 2009 5:17:30 am

<i>@Russ Michell</i>

Thank you for your contribution.

Please create a project on http://projects.ez.no
and publish your files through subversion.

I would like to test the solution without
having to create it from the text of your
forum post.

Cheers,
Heath

Brookins Consulting | http://brookinsconsulting.com/
Certified | http://auth.ez.no/certification/verify/380350
Solutions | http://projects.ez.no/users/community/brookins_consulting
eZpedia community documentation project | http://ezpedia.org

Russell Michell

Wednesday 07 January 2009 12:08:59 pm

@Heath,

Thanks for your suggestion. The project 'ez-deploy' now awaits approval by the ez crew. I will keep the thread posted.

Many thanks for everyone;s suggestions. If any other's turn up, I'd be glad to hear them and there is heaps of room for improvement! :-)

Cheers,
Russ

Russell Michell, Wellington, New Zealand.
We're building! http://www.theruss.com/blog/
I'm on Twitter: http://twitter.com/therussdotcom

Believe nothing, consider everything.

Heath

Wednesday 07 January 2009 1:31:50 pm

<i>@Russ</i>

Congratulations! I (and surely others) look forward to checking out a copy of ez-deploy from svn.projects.ez.no :)

Another suggestion. Consider publishing howto documentation like the contents of this forum thread on http://eZpedia.org/wiki/en as a new article. Simply register an account and create a new wiki page in the 'ez' folder.

Cheers,
Heath

Brookins Consulting | http://brookinsconsulting.com/
Certified | http://auth.ez.no/certification/verify/380350
Solutions | http://projects.ez.no/users/community/brookins_consulting
eZpedia community documentation project | http://ezpedia.org

Powered by eZ Publish™ CMS Open Source Web Content Management. Copyright © 1999-2014 eZ Systems AS (except where otherwise noted). All rights reserved.