ACL and Git – So happy together

In my previous post I discussed the merits of implementing version control software for ACLScript development, and then proceeded to detail how to install Git and get it set up.  We left off with an empty remote repository on our server and a blank development canvas on our local PC.  This post will demonstrate how to use Git in a development workflow, with the following disclaimer: What follows is how I specifically use Git as I develop ACL scripts.  It does not cover all of the functionality of Git, and some of my processes may have room for improvement.

Development starts with creating a new file in the local repository, so let’s do that.  Navigate to the root folder of your PC’s development location, which in my example was a folder called ‘MyNewRepository’ in my Documents library.  Create a new text file, call it ‘HelloWorld.aclscript’, and paste the following code into the file:

PAUSE “Hello World”

Save the script and open up SourceTree.  Make sure you are in the ‘File Status’ tab, located at the bottom of the screen.  SourceTree will automatically detect that there is a new file in the development library, as you can see in the screenshot below.  It also provides a snapshot of the contents of the new file in the right pane.

01 FirstFile

We want to start tracking changes to this file, so click the checkbox to the left of the file name.  Enter a message that provides some details about the new file we are tracking and click the ‘Commit’ button.

02 FirstCommit

We are now tracking changes to the script, meaning our script is version controlled.  Let’s change the code so we can see how changes within a file are handled.  Open up the script in your favorite text editor and replace PAUSE “Hello World” with this:

PAUSE “Hello World, the current time is ” + TIME()

Save the script and go back to SourceTree.  You will notice that SourceTree has automatically detected the change we made.  In the right pane you can see a snapshot of the actual changes that were made.  This level of detail is available to every single change you make once you begin tracking changes to your scripts.  Let’s provide a description of our change and commit this to our local repository.

03 CommitChangedLine.png

At this point, every change we have made has been committed only to our local Git repository.  None of these changes exist on the server repository and you will not find this script in your production script library.  We are happy with the current state of the script, so let’s push our changes to the remote repository.  We do this by right-clicking on ‘master’ and selecting ‘Push to’ -> ‘origin’.  Click ‘OK’ when the Push dialog pops up.

04 PushToOrigin

Now our changes exist on the server.  If another developer clones the server repository, they will get a copy of HelloWorld.aclscript in their local development repository, as well as its complete change history.  You can see the complete history yourself by clicking on the ‘Log / History’ tab at the bottom of the screen.  Clicking on a commit will show the before and after state of every file that was affected by the commit.  We can also see the descriptions we provided when we committed the changes to the repository.  Thus, you can see that providing descriptive messages of your changes is important to getting the most out of Git’s version control capabilities.

05 BranchHistory

You can also validate that the hook we created in the previous post is working correctly.  You should see the most recent version of HelloWorld.aclscript in \\ServerName\MyNewRepository.  By pushing our changes to the server, we have made the script available for everyone to use.

So far, we have been working in the master branch of our local repository.  It seems to be best practice to not work directly in the master branch.  A more typical workflow might be to have one or more development branches to track development work.  When development is finished, those changes are then merged into the master branch, which can then be pushed to the origin on the sever.  This process requires more steps, so I don’t tend to do this for every change I make.  When I do a large project or update, I will create a development branch, make my changes there, perform the necessary testing, and then update everything to the master branch and origin all at once.  For small changes and bug fixes I tend to work directly in the master branch.  How you design your workflow is up to you to decide.

To create a new branch, select the ‘master’ branch and click the ‘Branch’ button in the top toolbar.  Name the new branch ‘develop’ and click ‘Create Branch’.

06 NewBranch

You should now see a new branch with the same structure and commit history as the master branch.

07 DevelopBranchHistory

Let’s do some development by adding the following code to ‘HelloWorld.aclscript’

ACCEPT “What is your name?” TO v_Name
PAUSE “Hello %v_Name%, I am prepared to do your bidding.”

Save the script and switch back to SourceTree.  Make sure the ‘File Status’ tab is active.  SourceTree has detected our changes, so let’s enter a message about our change and commit it to the ‘develop’ branch.

08 ChangeInDevelop

If we want to update our master branch, we need to be in that branch.  Double-click on ‘master’ to switch to the master branch.  You should now see a screen showing where each branch is on the commit chain.  Notice that the ‘develop’ branch has an extra commit.

09 ExtraDevelopCommit

To update the master branch, right-click on the top commit and select ‘Merge’.  The master branch is now updated with our new code.

10 MasterUpdated

You will notice that SourceTree has detected that your ‘master’ branch is different from ‘origin’ and has provided a visual cue to that effect.  Let’s push these changes to ‘origin’ to complete the development cycle.  If you open HelloWorld.aclscript on \\ServerName\MyNewRepository, you should see the updated code.

And that is about it.  This is the basic workflow I use to develop and track changes to my ACL scripts.  Git is a very powerful tool and we have only scratched the surface of its capabilities.  I would recommend you explore its functions, especially if you are on a multiple-person development team.

Before we wrap this up, let’s talk about script design in a development environment such as this.  I want my internal customers (i.e. the audit department) to be able to use these scripts from their own installations of ACL Analytics.  I also want to be able to test my scripts as I develop them.  You may have noticed during this post that we have not actually tested any of the changes we made.  This is bad practice and I only did this to keep this post small-ish.  Make sure you test your scripts.

If we want to test our scripts, we can do so by running the following command from ACL’s command line or from a script in an ACL project:

DO “PathToLocalRepository\MyNewRepository\HelloWorld.aclscript”

We can run the production scripts from the server by running this command:

DO “\\ServerName\MyNewRepository\HelloWorld.aclscript”

This works fine, except for two issues:

  1. Whenever you call an external script a copy of that script gets created in your ACL project.  If you call an external script three times, you get three copies.  Over time these copies accumulate and make our projects look ugly.  I abhor messy projects – scripts should clean up after themselves.
  2. What happens when one script in the script library needs to call another script?  If we embed the server path into the DO command, then how do we test them on our local repository?

To address issue 1, every script I create begins and ends with two DELETE commands:

DELETE SCRIPT ScriptName OK
DELETE SCRIPT ScriptName2 OK

This means the HelloWorld script would look like this:

DELETE SCRIPT HelloWorld OK
DELETE SCRIPT HelloWorld2 OK

PAUSE “Hello World, the current time is ” + TIME()
ACCEPT “What is your name?” TO v_Name
PAUSE “Hello %v_Name%, I am prepared to do your bidding.”

DELETE SCRIPT HelloWorld OK
DELETE SCRIPT HelloWorld2 OK

I do this at both the beginning and end because the script can fail in the middle.  The commands at the beginning of the script do not delete the current version that is running, but the commands at the end will.  This means, if the script fails in the middle, the current version will not be deleted and the copies will still accumulate over time.  Having the commands at the beginning delete any old version that previously failed.

To address issue 2, every script I create assigns the server script library path to a variable if that variable does not already exist:

v_Library = “\\ServerName\MyNewRepository” IF FTYPE(“v_Library”) = “U”

Then, to run a script in the library, the DO command is as follows:

DO “%v_Library%\ScriptName.aclscript”

This means, in the production environment, the scripts will always reference the files on the server.  If I need to do some development testing, I set v_Library to the path to my local development folder.  I can do this in the ACL command line or embed the command into the Applications Toolbar (my current approach), which allows me to set up the development environment very quickly.  With this addition, our HelloWorld script would look like this:

DELETE SCRIPT HelloWorld OK
DELETE SCRIPT HelloWorld2 OK

v_Library = “\\Servername\MyNewRepository” IF FTYPE(“v_Library”) = “U”

PAUSE “Hello World, the current time is ” + TIME()
ACCEPT “What is your name?” TO v_Name
PAUSE “Hello %v_Name%, I am prepared to do your bidding.”

DELETE SCRIPT HelloWorld OK
DELETE SCRIPT HelloWorld2 OK

With this design framework I am able to maximize my development productivity and meet all of my objectives:

  • Scripts clean up after themselves.
  • Scripts need to be testable from the local development repository.
  • Scripts need to be able to call other scripts either in the production repository on the server (by default) or the local development repository.
  • Scripts need to work from ACL Analytics, Analysis Apps, and AuditExchange.
  • It should be easy and take very little time to set up the test environment for the local development repository.

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s