blob: 3036e58917528b5a6dbf4e37162338e7bd112f9c [file] [log] [blame]
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.2//EN"
"http://forrest.apache.org/dtd/document-v12.dtd">
<document>
<header>
<title>Forrestbot - automated building and deploying</title>
</header>
<body>
<section>
<title>Overview</title>
<p>
Forrestbot lets you automate building and deploying websites. The whole
process gets the source docs, builds the site, then deploys it where you
want it to go. Forrestbot can also notify you afterwards, and it keeps a
log of the build process. To accomplish these tasks, Forrestbot uses
four "workstages" (getsrc, build, deploy, notify). Each workstage has
various implementations (e.g., getsrc has getsrc.cvs or getsrc.svn or
getsrc.local implementations), which have various properties that may be
set, depending upon the implementations chosen.
</p>
</section>
<section>
<title>Using Forrestbot</title>
<p>
You need to create a customized buildfile directing Forrestbot's work
and then simply execute:
</p>
<source>forrest -f mybuildfile.xml</source>
<p>
This project buildfile is simply an Ant buildfile with specific targets
that control Forrestbot's operation. The next section explains how to
create such a buildfile. For details on the syntax of Ant buildfiles and
the operation of Ant itself consult the <link
href="ext:ant">Ant
documentation</link>.
</p>
</section>
<section>
<title>Creating a Forrestbot Project Buildfile</title>
<p>
Within the new buildfile, you need to first set properties needed by the
workstages you are going to use and then specify which implementations
will be used by each workstage. Note that the properties need to be set
at the global scope (as children of <code>&lt;project&gt;</code>, i.e.,
outside of <code>&lt;target&gt;</code> elements) in order for your
settings to override the defaults in the Forrestbot implementation.
Other than that, the property definitions can appear anywhere before the
<code>&lt;import&gt;</code> task.
</p>
<p>
This sample buildfile can be used as a base from which to customize your
own buildfile. The file starts with the project name and default target,
then sets the specific properties we need to get the source, indicate
the deployment location, and set up notification. It then specifies
which implementations we will use and finishes up with importing the
<code>forrestbot.xml</code> file. The 'main' target, which is specified
as the default here, is a convenience target (defined in
<code>forrestbot.xml</code>) that executes the four workstages (getsrc,
build, deploy, notify) sequentially.
</p>
<source>
<![CDATA[
<project name="mysampleproject" default="main">
<property name="notify.email.host" value="smtp.myhost.com"/>
<property name="notify.email.to" value="me@domain.com"/>
<property name="notify.administrator" value="Your Name"/>
<property name="getsrc.cvs.user" value="anoncvs"/>
<property name="getsrc.cvs.password" value="anoncvs"/>
<property name="getsrc.cvs.root" value="/home/cvspublic"/>
<property name="getsrc.cvs.host" value="cvs.myhost.com"/>
<property name="getsrc.cvs.module" value="myproject"/>
<property name="deploy.scp.dest"
value="username@myhost.com:/var/www/mydomain/htdocs"/>
<!-- here we declare the ssh keyfile and passphrase in an external file -->
<import file="../deploy-settings.xml" optional="true"/>
<!-- here we specify to use two notification implementations -->
<target name="notify" depends="notify.local, notify.email"/>
<!-- here we specify to deploy with the scp implementation -->
<target name="deploy" depends="deploy.scp"/>
<!-- the default implementation for getsrc is getsrc.cvs,
which is what we want -->
<!-- assumes FORREST_HOME has been set as an environment variable -->
<property environment="env"/>
<import file="${env.FORREST_HOME}/tools/forrestbot/core/forrestbot.xml"/>
</project>
]]>
</source>
<section>
<title>Workstages</title>
<p>
It is only necessary to include specific target implementations in the
buildfile if we want to override the default implementations. The
following table shows the various workstages, which implementations
may be used for each, and which one is the default.
</p>
<table>
<tr>
<th>Workstage</th>
<th>Implementations</th>
</tr>
<tr>
<td>getsrc</td>
<td>
<ul>
<li><link href="#getsrc.local">getsrc.local</link></li>
<li><link href="#getsrc.cvs">getsrc.cvs</link> (default)</li>
<li><link href="#getsrc.svn">getsrc.svn</link></li>
</ul>
</td>
</tr>
<tr>
<td>build</td>
<td>
<ul>
<li><link href="#build.forrest">build.forrest</link></li>
</ul>
</td>
</tr>
<tr>
<td>deploy</td>
<td>
<ul>
<li><link href="#deploy.local">deploy.local</link>
(default)</li>
<li><link href="#deploy.scp">deploy.scp</link></li>
<li><link href="#deploy.cvs">deploy.cvs</link></li>
<li><link href="#deploy.svn">deploy.svn</link></li>
<li><link href="#deploy.ftp">deploy.ftp</link></li>
</ul>
</td>
</tr>
<tr>
<td><link href="#notify">notify</link>
</td>
<td>
<ul>
<li><link href="#notify.local">notify.local</link>
(default)</li>
<li><link href="#notify.email">notify.email</link></li>
</ul>
</td>
</tr>
</table>
<p>
If you want to do more advanced processing for your project, you can
override the 'main' target, which by default is <code>&lt;target
name="main" depends="getsrc, build, deploy, notify"/&gt;</code>,
create your own implementation of a workstage, or use any other ant
tasks to do additional work. In order to create your own workstage
implementation, define the workstage target in question in your
<code>mybuildfile.xml</code> anywhere before the
<code>&lt;import&gt;</code> task. This will override the default
implementation provided by Forrestbot.
</p>
<p>
Also, you can choose a different target as the default by changing the
<code>default</code> attribute of <code>&lt;project&gt;</code>. For
example, you will much more frequently do a 'build' without a 'deploy'
during the development of your website, and only at the end do an
actual 'deploy', so you might want to choose 'build' as your default
target.
</p>
<section id="checksums">
<title>Deploying only modified files</title>
<p>
Use the <link href="site:faq/checksums">checkums</link> feature of
the Cocoon CLI. This enables Forrest to keep track of which
generated files have actually been changed. The Ant tasks used by
Forrestbot will then deploy only the modified files. Ant keeps a
<code>cache.properties</code> file. If you need to deploy all files
then remove this file and let it be re-generated.
</p>
<p>
Note that the deplo.svn and deploy.cvs workstages handle modified
files with their own mechanism.
</p>
</section>
<section>
<title>Correct Use of getsrc.local</title>
<p>
There is a wrinkle when using the 'getsrc.local' implementation of
the 'getsrc' workstage. If you define your own 'getsrc.local'
target, make sure it starts with the <code>&lt;property&gt;</code>
task given here:
</p>
<source>&lt;target name="getsrc.local"&gt;
&lt;property name="build.home-dir" location="${getsrc.local.root-dir}"/&gt;
[...]
&lt;/target&gt;</source>
<p>
Alternatively (and preferably), define your 'getsrc' target like
this:
</p>
<source>&lt;target name="getsrc" depends="getsrc.clean-workdir, getsrc.get, getsrc.local"/&gt;</source>
<p>
and then implement the actual fetching of the sources in the
'getsrc.get' target. This latter approach is safer since it is more
likely to be forward-compatible with future versions of Forrestbot.
</p>
</section>
</section>
<section>
<title>Workstage Properties</title>
<p>
Each workstage implementation is configurable with properties. The
following tables describe each property and whether or not you are
required to set it in your buildfile.
</p>
<p>
Many workstage properties use usernames and passwords. You may want to
keep them out of your project's Ant buildfile (especially if you store
that file in CVS or SVN). A nice way to do this is to create a
separate properties file (e.g., <code>auth.properties</code>) that
just sets those properties (don't include it in CVS/SVN). Then, at the
top of your project buildfile, have <code>&lt;property
file="auth.properties"/&gt;</code>.
</p>
<section>
<title>Misc. Properties</title>
<table>
<tr>
<th>Property</th>
<th>Description</th>
<th>Default Value</th>
<th>Required?</th>
</tr>
<tr>
<td>ant.project.name (you specify this by &lt;project
name="____"&gt; in your buildfile)</td>
<td>This must be unique for each project.</td>
<td></td>
<td>Yes</td>
</tr>
</table>
</section>
<section>
<title>getsrc.clean-workdir</title>
<p>
This should be executed before a getsrc implementation is executed,
e.g., <code>&lt;target name="getsrc" depends="getsrc.clean-workdir,
getsrc.svn"/&gt;</code>.
</p>
</section>
<section id="getsrc.local">
<title>getsrc.local</title>
<table>
<tr>
<th>Property</th>
<th>Description</th>
<th>Default Value</th>
<th>Required?</th>
</tr>
<tr>
<td>getsrc.local.root-dir</td>
<td>Absolute path to the project's root directory on the local
computer. Use <strong>location=</strong> instead of
<strong>value=</strong> for this &lt;property&gt;</td>
<td></td>
<td>Yes</td>
</tr>
</table>
</section>
<section id="getsrc.cvs">
<title>getsrc.cvs</title>
<table>
<tr>
<th>Property</th>
<th>Description</th>
<th>Default Value</th>
<th>Required?</th>
</tr>
<tr>
<td>getsrc.cvs.user</td>
<td>CVS username</td>
<td></td>
<td>Yes</td>
</tr>
<tr>
<td>getsrc.cvs.password</td>
<td>CVS password</td>
<td></td>
<td>Yes</td>
</tr>
<tr>
<td>getsrc.cvs.root</td>
<td>CVS root directory</td>
<td>/home/cvsroot</td>
<td>Yes</td>
</tr>
<tr>
<td>getsrc.cvs.host</td>
<td>CVS host</td>
<td>cvs.apache.org</td>
<td>Yes</td>
</tr>
<tr>
<td>getsrc.cvs.module</td>
<td>CVS module name (an alias for or the full path to the
directory that contains forrest.properties)</td>
<td>${ant.project.name}</td>
<td>Yes</td>
</tr>
<tr>
<td>getsrc.cvs.tag</td>
<td>CVS tag or branch name</td>
<td></td>
<td>No</td>
</tr>
</table>
</section>
<section id="getsrc.svn">
<title>getsrc.svn</title>
<table>
<tr>
<th>Property</th>
<th>Description</th>
<th>Default Value</th>
<th>Required?</th>
</tr>
<tr>
<td>getsrc.svn.url</td>
<td>Full repository URL for project (this directory must contain
forrest.properties)</td>
<td></td>
<td>Yes</td>
</tr>
<tr>
<td>getsrc.svn.revision</td>
<td>Revision number to fetch</td>
<td>HEAD</td>
<td>No</td>
</tr>
</table>
</section>
<section id="build.forrest">
<title>build.forrest</title>
<table>
<tr>
<th>Property</th>
<th>Description</th>
<th>Default Value</th>
<th>Required?</th>
</tr>
<tr>
<td>build.work-dir</td>
<td>Directory to temporarily hold working files</td>
<td>work/${ant.project.name}</td>
<td>No</td>
</tr>
<tr>
<td>build.log-dir</td>
<td>Directory to hold log files</td>
<td>logs</td>
<td>No</td>
</tr>
</table>
</section>
<section id="deploy.local">
<title>deploy.local</title>
<table>
<tr>
<th>Property</th>
<th>Description</th>
<th>Default Value</th>
<th>Required?</th>
</tr>
<tr>
<td>deploy.local.dir</td>
<td>Path to deploy site to - the dir that would be the
equivalant of build/site dir. Relative paths are relative to
${basedir}, which defaults to the dir containing the Forrestbot
project buildfile (mybuildfile.xml).</td>
<td>sites/${ant.project.name}</td>
<td>No</td>
</tr>
</table>
</section>
<section id="deploy.scp">
<title>deploy.scp</title>
<p>
The <code>${user.home}/.ssh/known_hosts</code> must properly
recognize the host, so you should manually make an ssh connection to
the host if you never have before.
</p>
<p>
If <code>${deploy.scp.keyfile}</code>is defined, then it will use
key-based authentication in preference. Otherwise it will use
<code>${deploy.scp.password}</code>
</p>
<table>
<tr>
<th>Property</th>
<th>Description</th>
<th>Default Value</th>
<th>Required?</th>
</tr>
<tr>
<td>deploy.scp.dest</td>
<td>Full destination reference in the format
user@host:/directory/path</td>
<td></td>
<td>Yes</td>
</tr>
<tr>
<td>deploy.scp.keyfile</td>
<td>Location of the local file holding the private key.
Usually /home/me/.ssh/id_dsa or /home/me/.ssh/id_rsa
<br />
Note that the deploy.scp.passphrase must also be supplied.
</td>
<td></td>
<td>No. However, if this is not supplied then scp will fallback
to use the less secure deploy.scp.password</td>
</tr>
<tr>
<td>deploy.scp.passphrase</td>
<td>Local passphrase for your private key.</td>
<td></td>
<td>No. You will be prompted if it is not set.</td>
</tr>
<tr>
<td>deploy.scp.password</td>
<td>Password for user@host</td>
<td></td>
<td>No. You will be prompted if it is not set.
<br />
Not needed if using the preferred
deploy.scp.keyfile/deploy.scp.passphrase
</td>
</tr>
</table>
</section>
<section id="deploy.cvs">
<title>deploy.cvs</title>
<p>
This is only available on *nix operating systems.
</p>
<table>
<tr>
<th>Property</th>
<th>Description</th>
<th>Default Value</th>
<th>Required?</th>
</tr>
<tr>
<td>deploy.cvs.user</td>
<td>CVS username to use when committing changes</td>
<td></td>
<td>Yes</td>
</tr>
<tr>
<td>deploy.cvs.password</td>
<td>CVS password</td>
<td></td>
<td>Yes</td>
</tr>
<tr>
<td>deploy.cvs.root</td>
<td>CVS root</td>
<td>/home/cvs</td>
<td>Yes</td>
</tr>
<tr>
<td>deploy.cvs.host</td>
<td>CVS host</td>
<td>cvs.apache.org</td>
<td>Yes</td>
</tr>
<tr>
<td>deploy.cvs.module</td>
<td>CVS module</td>
<td>${ant.project.name}</td>
<td>Yes</td>
</tr>
<tr>
<td>deploy.cvs.commit-message</td>
<td>Message to use when committing. You probably want to put a
machine name or person's name here.</td>
<td>Automatic publish from forrestbot</td>
<td>No</td>
</tr>
</table>
</section>
<section id="deploy.svn">
<title>deploy.svn</title>
<table>
<tr>
<th>Property</th>
<th>Description</th>
<th>Default Value</th>
<th>Required?</th>
</tr>
<tr>
<td>deploy.svn.user</td>
<td>SVN username to use when committing changes</td>
<td></td>
<td>Yes</td>
</tr>
<tr>
<td>deploy.svn.password</td>
<td>SVN password</td>
<td></td>
<td>Yes</td>
</tr>
<tr>
<td>deploy.svn.url</td>
<td>Full repository URL</td>
<td></td>
<td>Yes</td>
</tr>
<tr>
<td>deploy.svn.commit-message</td>
<td>Message to use when committing. You probably want to put a
machine name or person's name here.</td>
<td>Automatic publish from forrestbot</td>
<td>No</td>
</tr>
</table>
</section>
<section id="deploy.ftp">
<title>deploy.ftp</title>
<table>
<tr>
<th>Property</th>
<th>Description</th>
<th>Default Value</th>
<th>Required?</th>
</tr>
<tr>
<td>deploy.ftp.server</td>
<td>FTP server to upload files to</td>
<td>localhost</td>
<td>No</td>
</tr>
<tr>
<td>deploy.ftp.user</td>
<td>FTP username to use for authenticating with the server</td>
<td>anonymous</td>
<td>No</td>
</tr>
<tr>
<td>deploy.ftp.password</td>
<td>Password for the FTP user</td>
<td>forrestbot@</td>
<td>No</td>
</tr>
<tr>
<td>deploy.ftp.remotedir</td>
<td>The directory to upload to (this can be an absolute path or
relative to the FTP user's default directory)</td>
<td>incoming</td>
<td>No</td>
</tr>
</table>
</section>
<section id="notify">
<title>notify</title>
<p>
These settings are used by all notify implementations.
</p>
<table>
<tr>
<th>Property</th>
<th>Description</th>
<th>Default Value</th>
<th>Required?</th>
</tr>
<tr>
<td>notify.administrator</td>
<td>Name and email address of the forrestbot administrator</td>
<td></td>
<td>Yes</td>
</tr>
<tr>
<td>notify.on.failure</td>
<td>On a build failure, notification will happen if this is
true.</td>
<td>true</td>
<td>No</td>
</tr>
<tr>
<td>notify.on.success</td>
<td>On a succesful build, notification will happen if this is
true.</td>
<td>true</td>
<td>No</td>
</tr>
<tr>
<td>notify.log</td>
<td>Log file</td>
<td></td>
<td>No. Set by other workstage(s).</td>
</tr>
<tr>
<td>notify.deploy-location</td>
<td>Deployed location</td>
<td></td>
<td>No. Set by other workstage(s).</td>
</tr>
<tr>
<td>notify.completion-status</td>
<td>Result of the build</td>
<td></td>
<td>No. Set by other workstage(s).</td>
</tr>
</table>
</section>
<section id="notify.local">
<title>notify.local</title>
<p>
No properties.
</p>
</section>
<section id="notify.email">
<title>notify.email</title>
<table>
<tr>
<th>Property</th>
<th>Description</th>
<th>Default Value</th>
<th>Required?</th>
</tr>
<tr>
<td>notify.email.host</td>
<td>SMTP host through which the email will be sent.</td>
<td>localhost</td>
<td>Yes</td>
</tr>
<tr>
<td>notify.email.to</td>
<td>Email address to send notification to.</td>
<td>${user.name}@localhost</td>
<td>Yes</td>
</tr>
<tr>
<td>notify.email.from</td>
<td>From: address in the email</td>
<td>Forrestbot</td>
<td>No, but some mailers may require a valid email address.</td>
</tr>
</table>
</section>
</section>
</section>
<section>
<title>Forrestbot Design</title>
<p>
Forrest and Forrestbot use Ant buildfiles extensively. Ant 1.6's
<code>&lt;import&gt;</code> task is used to import multiple buildfiles
into a single build. The following is the flow of control when running
Forrestbot:
</p>
<ul>
<li>Your project buildfile (<code>mybuildfile.xml</code>)<ul>
<li><code>$FORREST_HOME/tools/forrestbot/core/forrestbot.xml</code>
<ul>
<li>Workstage buildfiles
(<code>$FORREST_HOME/tools/forrestbot/core/{getsrc,build,deploy,notify}.xml</code>)</li>
<li><code>$FORREST_HOME/main/forrest.build.xml</code></li>
</ul></li>
</ul></li>
</ul>
<p>
The workstage buildfiles define the default workstage implementations
and set up the properties and files so that targets in the main Forrest
buildfile (<code>forrest.build.xml</code>) will run. After those targets
are executed, the targets in the workstage buildfiles can perform
reporting, deployment, or other post-build activities.
</p>
<p>
Your project buildfile specifies the workstages you want to use, sets
properties for them, and does any additional pre- and post-processing.
In addition, you can override the default workstage implementations by
defining the relevant targets in your project buildfile before the
<code>&lt;import&gt;</code> task (see the example above).
</p>
</section>
</body>
</document>