Hi Marc,
I can imagine that would be nice to have integrated into UDeliver instead of combining it as explained in this article. maybe @Rob.van.Haarst can elaborate on the possibilites, challenges involved? A Git client will need to be included/shipped along I suppose or maybe you could specify a location of the Git client to use with UDeliver?
More on USoft Delivery manager:
Yes, the link describes what we do now, but it would be nice to have proper ‘Git pull’ and ‘Git push’ actions in UDeliver.
Hi Dara and Marc,
This is an interesting suggestion and part of a much larger discussion about sourcing. When USoft started out all those years ago, the idea was to have a central database repository, with some additional features for deliverables that really had to be files and not database records. But in 2021, we are in a reality where Git file-based repositories are the leading delivery model for business software, and USoft database repositories will just have to fit into this larger framework. UDeliver is a step in this direction, because it automates conversion from database repositories to file-based deliverables.
More concretely, at USoft, when we create PDF documentation for our USoft Studio product, we use UDeliver to pull and push directly to and from Git, using task steps like the following.
This solution uses RDMI components. The USWTW_WINFILES performs common file system operations such as building filepaths for copying, moving and deleting files and folders. The code for the USWTW_SYSTEM component appears at the end of this reply.
Step 1: Hard reset and pull
This is risky in that any locally outstanding uncommitted work is automatically discarded. But this is necessary to avoid running into Git merge conflicts when these UDeliver steps are carried out as an automated routine.
UDeliver Action: Run SQL Command
SQL command:
(Note: ‘${git_local_folder}’ is something called a ‘user-defined source variable’ in UDeliver.)
INVOKE
USWTW_System.Execute
WITH SELECT
'git.exe', '--git-dir="${git_local_folder}"\.git --work-tree="${git_local_folder}" reset --hard -q origin/develop'
Step 2: Upload edits
UDeliver Action: Copy Folder
Source folder:
${my_edited_folder}\pdf
Destination folder:
${git_local_folder}\Alt\Website\pdf
Step 3: Commit PDFs
UDeliver Action: Run SQL Command
SQL command:
INVOKE USWTW_System.Execute
WITH
SELECT 'git.exe', '--git-dir=' || '${git_local_folder}' || '\.git --work-tree=' || '${git_local_folder}' || ' commit -a -q -m "URequire ' || '${curr_vs}' || ' PDF files"'
WHERE /* Only commit/push if pdf's have been successfully created s*/
TO_DATE(
USWTW_WINFILES.MODIFIED(
'${git_local_folder}' || '\Alt\Website\PDF\workspace.pdf'
),
'YYYY/MMDDHH24MISS'
) > ( current_date() - 1 )
Step 4: Push PDFs
UDeliver Action: Run SQL Command
SQL command:
INVOKE USWTW_System.Execute
WITH
SELECT 'git.exe', '--git-dir=' || '${git_local_folder}' || '\.git --work-tree=' || '${git_local_folder}' || ' push -q'
WHERE /* Only commit/push if pdf's have been successfully created */
TO_DATE(USWTW_WINFILES.MODIFIED('${git_local_folder}' || '\Alt\WebSite\pdf\workspace.pdf'), 'YYYY/MMDDHH24MISS') > ( current_date() - 1 )
.NET Component: USWTW_SYSTEM
using System;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Text;
using System.Globalization;
using System.Diagnostics;
using System.Threading;
class USWTW_SYSTEM
{
public string Execute(string cmd, string arguments)
{
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = cmd;
startInfo.Arguments = arguments;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
process.StartInfo = startInfo;
process.Start();
string errors = process.StandardError.ReadToEnd();
if( errors != "")
throw new Exception(errors);
return process.StandardOutput.ReadToEnd();
}
public string ExecuteReturnError(string cmd, string arguments)
{
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = cmd;
startInfo.Arguments = arguments;
startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = false;
process.StartInfo = startInfo;
process.Start();
return process.StandardError.ReadToEnd();
}
public int ExecuteReturnExitCode(string cmd, string arguments)
{
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = cmd;
startInfo.Arguments = arguments;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
process.StartInfo = startInfo;
process.Start();
string errors = process.StandardError.ReadToEnd();
if( errors != "")
throw new Exception(errors);
return process.ExitCode;
}
public void ExecuteShell(string cmd, string arguments, string error_string)
{
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = cmd;
startInfo.Arguments = arguments;
startInfo.UseShellExecute = true;
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
if( process.ExitCode != 0)
throw new Exception(error_string);
}
public void Exit(string dummy)
{
Process.GetCurrentProcess().Kill();
}
}
Rob, thanks for the detailed information! I’ll play around with this when I have some time.