Introduction and Utility

One of the exciting new features added in HCL Launch version 7.1.1.0 is the ability to configure application and component processes outside of the web UI. With our “Process as Code” format, development teams can define and store their processes in an easily modifiable format.

The HCL Launch server comes bundled with our Process as Code Compiler which is a utility comprised of several commands. Its main purpose is to interact with the Launch server and translate between the PAC format and the JSON format that is understood by the Launch server.

The most useful commands are the upload and download commands. There are four of these commands: download-component-process, download-application-process, upload-component-process, and upload-application-process.

The download commands are pointed at a specific version of a process in Launch and will download that process, convert it into the PAC format, and save it.

download-<process-type>-process <user-name> <server-url> <process-id> [<version>|latest] output.pac

The upload commands will do the opposite; an upload command will translate a local PAC file to the JSON format expected by the server and then upload it as a new version of the specified process.

upload-<process-type>-process <user-name> <server-url> <process-id> <next-version | latest> input.pac

Two other commands are also available: the pacc script will translate a locally stored Launch JSON file to the PAC format and the ccap script will convert from PAC to JSON formats.

Basic Syntax

The PACC utility README includes a fleshed-out description of the custom syntax that we’ve defined, but here are the basics:

  • “start” and “finish” are used to represent the entry and exit points of the process.
  • “start <name>” is used to invoke a defined step
  • “plugin step <name> is” defines and configures a step. This generic syntax can specify any plugin command, and we have shorthands for commonly used steps like “shell”
    • “plugin” points to the plugin to use
    • “command” points to the specific plugin step within that plugin to use
    • “on [success | failure | complete]” define the subsequent steps that execute after a specific step finishes.
    • “property “<field name> = <value>” specifies values for plugin step fields

Here’s an example of a small component process that downloads the artifact set for a simple Tomcat web application and uses the our Tomcat plugin to deploy the application.

start is
    start "Download Artifacts"
end

plugin step "Download Artifacts" is
    plugin "UrbanCode Deploy Versioned File Storage"
    command "Download Artifacts"
on success
    start "Deploy Tomcat Application"
end

plugin step "Deploy Tomcat Application" is
    plugin "Tomcat"
    command "Deploy Application"
    property "tomcatManagerUrl" = "${p:environment/tomcat.manager.url}"
    property "tomcatUsername" = "exampleTomcatUser"
    property "tomcatPassword" = "${p:environment/secureTomcatPassword}"
    property "tomcatContext" = "/TestA"
    property "warFile" = "./TestApp.war"
    property "configFile" = ""
on success
    finish
end

In this example I’m explicitly defining certain properties for my Deploy Application step while leaving the Download Artifacts commands basically empty to use the default values for the step. Since the PAC process is uploaded directly to HCL Launch and converted to a format the server understands we can still reference properties.

To get started I recommend using the download process commands to convert existing Launch processes into the PAC format and using them as the starting-off point for PAC modifications.

I’m currently managing my deployment processes on development Launch server using Processes as Code and a custom githook to automatically upload processes after I commit changes to the PAC files. The processes I want to manage on my server are stored in my “deployment-processes” repository using the following directory structure:

Deployment-processes/<processType>/<nameOfComponentOrApplication>/<ProcessID>.pac

This ensures that the path of my changed .PAC files include all the information my githook needs to upload my process on commit. In my example I’m using a post-commit hook to upload as soon as I commit to a branch, though in non-toy examples a pre or post-receive hook on the git server side would be more appropriate.

The githook example below is written in python and uses the pexpect library to get around the fact that the current version of the PAC utility requires users to manually input a password when interacting with the Launch server.

#!/usr/bin/env python3 
from subprocess import check_output
import pexpect
import json
TYPE = 0
NAME = 1
ID = 2
username = ''
password = ''
serverUrl = ''
# returns tuple of type, name, processId
# assumes files are appropriately structured
def parseTargetsFromFile(filepath):
    #component/testComponent/175427f6-0a8b-93b4-d73a-6a8ba534b060.pac
    targets = filepath.split('/')
    filename = targets[ID]
    return targets[TYPE], targets[NAME], filename[:filename.index(".")]
def uploadProcess(cmd):
    child = pexpect.spawn(cmd)
    try:
        i = child.expect([pexpect.TIMEOUT,'password:'])
        if i == 0:
            print("Got unexpected output: %s %s" % (child.before, child.after))
        else:
            child.sendline(password)
        child.read()
    except:
        print("Problem encountered: ")
        print(str(child))
def uploadChangedProcesses():
    # git diff-tree -r --name-only --no-commit-id HEAD
    changedFiles = check_output(['git', 'diff-tree', '-r', '--name-only', '--no-commit-id', 'HEAD']).decode()
    lines = changedFiles.splitlines()
    for line in lines:
        print(f"uploading pac file: {line}")
        line = str(line)
        targets = parseTargetsFromFile(line)
        cmd = buildCommand(targets, line)
        uploadProcess(cmd)

def buildCommand(targets, filename):
    return f"upload-{targets[TYPE]}-process {username} {serverUrl} {targets[ID]} latest {filename}"
if __name__ == "__main__":
    with open('conf.json') as confFile:
        conf = json.load(confFile)   
        username =  conf['username']
        password = conf['password']
        serverUrl = conf['url']
    uploadChangedProcesses()

Saving the above script as a post-commit hook and commiting modifications to my PAC files will upload those files as the latest version of the process with the same ID on my Launch server as seen below:

Inserting image...

If you want to see the new “Processes as Code” feature in action, along with all the other updates to HCL Launch 7.1.1, join my webinar by registering here.

Comment wrap
Further Reading
Secure DevOps | November 6, 2020
More on Process as Code, new in HCL Launch 7.1.1
With the release of HCL Launch 7.1.1, our continuous delivery tool is even more developer and integration integration friendly because of a new feature called PACC - Process as Code Compiler.
hcl launch
Secure DevOps | October 27, 2020
What’s new in HCL Launch 7.1.1.0
Our continuous delivery software, HCL Launch, has new features that make it easier than ever to deploy anything, anywhere. Find out what's new in HCL Launch 7.1.1.
Secure DevOps | September 29, 2020
HCL Launch – In Love with Snapshots
Learn how Snapshots from HCL Launch can make handling deployments easier than ever.
a/icon/common/search Created with Sketch.