views:

1787

answers:

7

I want to load a different properties file based upon one variable.

Basically, if doing a dev build use this properties file, if doing a test build use this other properties file, and if doing a production build use yet a third properties file.

A: 

The way I've done this kind of thing is to include seperate build files depending on the type of build using the nant task. A possible alternative might be to use the iniread task in nantcontrib.

Andy Whitfield
+3  A: 

You can use the include task to include another build file (containing your properties) within the main build file. The if attribute of the include task can test against a variable to determine whether the build file should be included:

<include buildfile="devPropertyFile.build" if="${buildEnvironment == 'DEV'}"/>
<include buildfile="testPropertyFile.build" if="${buildEnvironment == 'TEST'}"/>
<include buildfile="prodPropertyFile.build" if="${buildEnvironment == 'PROD'}"/>
Tim
+15  A: 

Step 1: Define a property in your NAnt script to track the environment you're building for (local, test, production, etc.).

<property name="environment" value="local" />

Step 2: If you don't already have a configuration or initialization target that all targets depends on, then create a configuration target, and make sure your other targets depend on it.

<target name="config">
    <!-- configuration logic goes here -->
</target>

<target name="buildmyproject" depends="config">
    <!-- this target builds your project, but runs the config target first -->
</target>

Step 3: Update your configuration target to pull in an appropriate properties file based on the environment property.

<target name="config">
    <property name="configFile" value="${environment}.config.xml" />
    <if test="${file::exists(configFile)}">
        <echo message="Loading ${configFile}..." />
        <include buildfile="${configFile}" />
    </if>
    <if test="${not file::exists(configFile) and environment != 'local'}">
        <fail message="Configuration file '${configFile}' could not be found." />
    </if>
</target>

Note, I like to allow team members to define their own local.config.xml files that don't get committed to source control. This provides a nice place to store local connection strings or other local environment settings.

Step 4: Set the environment property when you invoke NAnt, e.g.:

  • nant -D:environment=dev
  • nant -D:environment=test
  • nant -D:environment=production
scott.caligan
+3  A: 

I had a similar problem which the answer from scott.caligan partially solved, however I wanted people to be able to set the environment and load the appropriate properties file just by specifying a target like so:

  • nant dev
  • nant test
  • nant stage

You can do this by adding a target that sets the environment variable. For instance:

<target name="dev">
  <property name="environment" value="dev"/>
  <call target="importProperties" cascade="false"/>
</target>

<target name="test">
  <property name="environment" value="test"/>
  <call target="importProperties" cascade="false"/>
</target>

<target name="stage">
  <property name="environment" value="stage"/>
  <call target="importProperties" cascade="false"/>
</target>

<target name="importProperties">
  <property name="propertiesFile" value="properties.${environment}.build"/>
  <if test="${file::exists(propertiesFile)}">
    <include buildfile="${propertiesFile}"/>
  </if>
  <if test="${not file::exists(propertiesFile)}">
    <fail message="Properties file ${propertiesFile} could not be found."/>
  </if>
</target>
Ryan Taylor
A: 

The solutions above are exactly what I've been trying to do, but I'm getting the following error on the include line:

Task not allowed in targets.  Must be at project level.

Any ideas?

Nate
A: 

Task not allowed in targets

THe task is not allowed inside a target you must move the statement be a direct element of the project.

The above code doesnt work.. :) At least not in my world.

heres what I mean.

<project default="all">
 <include buildfile="wip.build"/>
 <target name="all">
  <echo message="Building default target " />

  <call target="WipTarget" /> 
 </target>
</project>
Nick
A: 

NAnt's documentation states the following for the include task:

This task can only be in the global (project level) section of the build file.

When I try a similar solution like scott.caligan's, I also receive the following error:

Task not allowed in targets. Must be at project level.

Seems to me that you cannot use the include task within a target task. Has anyone actually gotten scott.caligan's solution to work or was it just conjecture?

Gary B
Ok, I figured out why I was getting the "Task not allowed in targets. Must be at project level." error.This error is thrown when using the include task within a target task that gets called from another target class. If I move the include task up to the "parent" target task, no error is thrown and it works as expected.
Gary B