Configuration Files
  • 09 Jan 2023
  • 5 Minutes to read
  • Dark
    Light
  • PDF

Configuration Files

  • Dark
    Light
  • PDF

Many applications rely on configuration values that are stored in files stored alongside application executable files, such as web.config in .NET or .properties files in Java.

These configuration files often need to be managed independently from other files in a build because their contents will change from environment to environment, and even contain sensitive data such as database connection strings, third-party service URLs, API keys, etc.

BuildMaster provides two strategies for managing configuration files: configuration file assets and text-templating.

Configuration Files Assets

Configuration file assets stores multi-instance configuration files, and provides a multi-tabled editor to edit and compare these instances.

  • File contents are compared before deployment and will not deploy the file if the contents have not changed
  • Deployments are separately logged
  • Version history is maintained and allows for arbitrary comparison between instances and versions
  • You can manually deploy outside the scope of a deployment
  • Restrict certain instances from being viewed or edited using access controls

Naming

Configuration files should be named after the file they represent, e.g. web.config. These names are unique per application. In cases where there may be multiple files with the same name within an application, aliases may be used to uniquely identify them in the UI. When deploying a non-unique configuration file, make sure to specify the name of the output file directly.

Instances and Versions

Each configuration file contains at least one instance and instances may be associated with an environment. A configuration file is versioned as a whole—meaning any changes made to any instance increments the version number. Instances should generally be named after the environment the file will be deployed to.

Security and Permissions

Permissions may be assigned to users by associating an environment to a configuration file instance and granting or restricting any of the following tasks:

  • Deploy
  • Edit Instance
  • View Instance

Template Instances

Configuration file templates are designed to simplify deployment of configuration file instances that contain virtually identical content except for minor, environment-specific differences. The item that contains the placeholders for substitution is referred to as the template, and the item that contains the substitution values is referred to as the template instance. BuildMaster supports three types of transform syntaxes:

Key-Value Pair

Template instances are specified as newline-separated, key-value pairs, and each key-value pair is separated by an equals sign. Additional equals signs on the same line are permitted and included in the replacement value. If the value requires a new line, the $NewLine variable function may be used.

Template

<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
    <add key="Core.DbConnectionString" value="$ConnectionString" />
    <add key="IntegratedWebServer.Enabled" value="True" />
</appSettings> 

Template Instance

ConnectionString=Data Source=localhost;Initial Catalog=BuildMaster;Integrated Security=SSPI;

Result

<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
    <add key="Core.DbConnectionString" value="Data Source=localhost;Initial Catalog=BuildMaster;Integrated Security=SSPI;" />
    <add key="IntegratedWebServer.Enabled" value="True" />
</appSettings> 

XSLT

Templates or their instances may be used as XSLT stylesheets and XML data that will be automatically transformed before deployment. In most cases, "XSL Stylesheet as Template" is the desired transform option because the XML data would be stored in the template instances.

Data

<?xml version="1.0" ?>
<config>
    <connection>
        <value>https://example.org/v1/service1</value>
    </connection>
    <connection>
        <value>https://example.org/v1/service2</value>
    </connection>
    <connection>
        <value>https://example.org/v1/service3</value>
    </connection>
</config>

Stylesheet

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns="http://www.w3.org/1999/xhtml">

    <xsl:output method="xml" indent="yes" encoding="UTF-8" />

    <xsl:template match="/config">
        <html>
        <head>
            <title>Testing XML Example</title>
        </head>
        <body>
            <h1>Connections</h1>
            <ul>
                <xsl:apply-templates select="connection"></xsl:apply-templates>
            </ul>
        </body>
    </html>
</xsl:template>

<xsl:template match="connection">
    <li>
        <xsl:value-of select="value" />
    </li>
</xsl:template>

</xsl:stylesheet>

Result

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Testing XML Example</title>
</head>
<body>
    <h1>Connections</h1>
    <ul>
        <li>https://example.org/v1/service1</li>
        <li>https://example.org/v1/service2</li>
        <li>https://example.org/v1/service3</li>
    </ul>
</body>
</html>

Variable Replacement

All configuration variables, runtime variables, and parameterless variable functions in context are considered when variable replacement occurs before deployment and follows the same resolution rules as configuration variable replacement.

Template file variables are treated as runtime variables when replacement occurs and, therefore, override any configuration variables. In practice, it is not recommended to have template instance variables override existing configuration variables or variable functions. It is also not recommended to rely on runtime variables created during a deployment.

Escaping Variables

There are many cases when a configuration file needs to contain literal text that appears to be a variable name. In this case, escape any $ signs with a `, e.g. `$DoNotProcess.

Note that the behavior for variable replacement prior to BuildMaster 6.2 was different; see the Legacy Features to learn more.

Deployment

Automated Script-Based Deployment

The most common method of deployment is the Deploy Configuration File operation (Deploy-ConfigFile in OtterScript). When this operation is executed during a deployment, the version of the configuration file instance associated with the release currently in context will be deployed to the target path. If there is an existing file at the target path, it will only be overwritten if its text contents are different than the configuration file text in BuildMaster, otherwise the operation effectively becomes a no-op.

Manual One-Off Deployment

Configuration files may also be deployed outside the context of a deployment. It is generally not recommended to deploy configuration files in this manner because much of the context associated with the script-based deployment is lost (e.g. release number and build number). One-off deployments should be reserved for emergency cases that require a configuration change immediately without the overhead of the traditional release cycle.

History

Deployment history for configuration file instances is stored for configuration files deployed from BuildMaster. The instance, version number, user, and date of deployment is visible, as well as the ability to compare arbitrary versions to highlight what changes were made to an instance.

Association with Releases

A release may be associated with a specific version of a configuration, or if unspecified, associated with the latest version. By default, a release is associated with the latest configuration file version. When a release is deployed to the final stage in a pipeline, the current configuration file version will become associated with that release to preserve the contents at that point in time, facilitating future rollbacks if necessary.

Text-templating

Text-templating relies on the text templating in the Inedo Execution Engine, along with configuration variables and conditionals for environment-specific settings.

There are several advantages to using this method over configuration file assets:

  • Allows for the use of if/else conditionals, loops blocks, and access to all variable functions (i.e. $ArtifactPath(...))
  • More familiar to developers, and is how nearly all other build and deployment tools manage configuration file deployment
  • You can store the majority of your template in source control, alongside the code, and store only variables in BuildMaster

Differences Between Configuration File Strategies

While using text templates is a powerful yet simple replacement for Configuration File Assets, there are some important differences:

  • Configuration file assets will compare file contents before deployment and will not deploy the file if the contents have not changed
  • Configuration file assets maintain version history and allow arbitrary comparison between instances and versions
  • Configuration file assets allow manual deployment outside the scope of a deployment
  • In contrast to configuration file assets, text templates allow the use of if/else conditionals, loops blocks, and access to all variable functions (i.e. $ArtifactPath(...))
  • Text templates only support OtterScript-style variable syntax (i.e. the legacy %-syntax and $-syntax are not supported)

Was this article helpful?

What's Next