start portlet menu bar

HCLSoftware: Fueling the Digital+ Economy

Display portlet menu
end portlet menu bar
Close
Select Page

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
deployment processes

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

Start a Conversation with Us

We’re here to help you find the right solutions and support you in achieving your business goals.

  |  August 7, 2023
New Version Release: Announcing HCL Launch 7.3.2
Read here for the exciting details about the new release of our continuous integration and continuous delivery solution, HCL Launch Version 7!
  |  December 14, 2021
Resiliency for CI/CD Pipeline
Building a resilient DevOps automation framework means the application delivery process can continue uninterrupted even when the unexpected occurs.
  |  July 26, 2021
HCL Launch In The Cloud: Automating Continuous Deployment
HCL Launch can deploy workloads to cloud-based environments, and HCL Launch excels at deploying hybrid applications.