Controlled Release of new Developments

Issue

Various Developments are in different stages of development, testing and release.
It can be challenging to keep track of all changes and keep the different systems in sync.

Release management option 1: Use XPOs

Process

  • Development system (DEV): Development w/o special consideration of release process
    When done, move completed developments via xpo to TEST.
  • Test system (TEST): Testing
    When done, move successfully tested object to PROD (or REL) using xpo
  • Release system (REL): Create release layer if desired
    When done move Layer to PROD.
  • Productive system (PROD): Active code base

Issues

  • Manual identification and extraction of relevant objects required
  • Three different code bases
  • Danger of object-Ids being out of sync
  • Objects can simultaneously contain modifications in different stages of development; some should be release, others not

Release management option 2: Use configuration keys

Process

  • Development system (DEV): Development adding configuration keys allowing to deactivate the newly created code parts. (Do not use configuration keys for Database objects – PROD, TEST and DEV databases should be identical –> Enabling/Disabling configuration keys will never result in database issues).
    When done, move entire layer to TEST (synchronization between developers required, to ensure that all have disable their changes using configuration keys.)
  • Test system (TEST): Activate Configuration Keys ready for testing; Test. Additional checks required that deactivated developments do not have unintended side effects.
    When done, move entire layer to PROD. (In some cases the code might have been release earlier, so only enabling configuration keys is required in PROD.)
  • Production system (PROD): Enable configurations keys.

Advantages (referring to option 1)

  • Simple identification and activation using configuration keys
  • One code base
  • Identical object-ids in all systems
  • No issues in with objects simultaneously containing modifications in different stages of development.

Disadvantages

  • Incorrectly disabled code can cause issues à additional testing required (release document needs to identify new added – but not enable code)

My conclusion

In my opinion the advantages of Option 2 outweigh the disadvantage of the additional “disabled”-testing required.

Practical aspects

Configuration key structure

Add a configuration key parent for pending objects and one for released objects. In DEV all configurations are always enabled (this can be ensured by script – see below), in TEST only some configurations in the “Release pending” group might be enabled. In PROD, no configurations in the “Release pending” group might are enabled.

image

After successful testing the configuration keys are moved into the released group. Note: Moving between the “Release pending” and the “Released” group does nothing in itself – it is recommended for keeping track of the status of the various objects and can be used by scripts to identify the status of configuration keys.

Enable DEV/TEST configuration keys after restore

The following code enables all config keys under ReleasePending. It is useful after a restore of the PROD database into test and can be run as manually executed job or can be included in Info.startupPost() to automatically run when the current database is TEST (SysSQLSystemInfo::construct().getloginDatabase()).

/// <summary>
/// Activate all configuration keys under ReleasePending ==> for test system only!
/// </summary>
static void enableControlledReleaseConfigs()
{
    int i;
    Dictionary dict = new Dictionary();
    SysDictConfigurationKey sDCK;
    ConfigurationKeySet configurationKeySet;
    ;
    configurationKeySet = new ConfigurationKeySet();
    configurationKeySet.loadSystemSetup();

    for (i=dict.configurationKeyCnt(); i; i–)
    {
        sDCK= new SysDictConfigurationKey(dict.configurationKeyCnt2Id(i));
        if(sDCK.parentConfigurationKeyId() == configurationKeyNum(ReleasePending))
        {
            configurationKeySet.enabled(sDCK.id(),true);
        }
    }
    SysDictConfigurationKey::save(configurationKeySet.pack());
    SysSecurity::reload(true,true,true,false);
}