You can also use the WSL on recent Windows and call the wsl shell, which can be call with:
“wsl ${cmd}”
I made myself a function that do call the proper shell based on the current platform, so my pipeline script does look like a big if else mess for each shell command, on windows it append the wsl in front of my command and fix the stdout return value.
Here is some groovy scripts function I do inject to “fix” (or if you prefer bring it to human decent version of command) the shell:
/*
* Console cross platform command
*/
def BasicConsole(labelStr, cmd, returnStatus = false, returnStdout = false, useWsl = false) {
// Only good for exact same syntax command on all platform or use wsl to execute the command into unix like under Windows if this is available
if(isUnix()) {
return sh(label: labelStr, script: cmd, returnStatus: returnStatus, returnStdout: returnStdout);
} else {
return WindowFixReturn(bat(label: labelStr, script: WindowFixCmd(cmd, useWsl), returnStatus: returnStatus, returnStdout: returnStdout), returnStdout);
}
}
def ConsoleVar(varName) {
if(isUnix()) {
return "\${${varName}}";
} else {
return "%${varName}%";
}
}
def WindowFixReturn(data, returnStdout) {
if(returnStdout) {
// Remove the requested command echo into the shell, this make the behavior more closer to unix for cross platform behavior
return data.trim().readLines().drop(1).join("\n");
}
return data;
}
def WindowFixCmd(cmd, useWsl) {
if(useWsl) {
return WindowsWslCommand(cmd);
}
return cmd;
}
def WindowsWslCommand(cmd) {
return "wsl ${cmd}";
}
def WindowsEscapeVarPercentage(str) {
if(isUnix()) {
return str;
}
// If we want literal %
return str.replace("%", "%%");
}
def ConsoleScriptExtension() {
if(isUnix()) {
return ".sh";
} else {
return ".bat";
}
}
def ConsoleCommandDelimiter() {
// When doing command that must be execute no matter the results of the first one
if(isUnix()) {
return ";";
} else {
return "&";
}
}
I did some file manipulation commands for files and folders manip (delete, create, exist, etc) some my pipeline scripts now run the same code on all platform without issues and remove the big if(isWindows()) mess all around.
Wish they have made this build in. This is a CI, this is what it should do manipulated files in many env. Feel like this is lacking big time.
If you want to detect the main platform for the 3 majors OS and you need to determine which one it is:
/*
* Platform specific check
*/
def GetOS() {
if(isUnix()) {
def uname = sh(script: 'uname', returnStdout: true);
if(uname.startsWith("Darwin")) {
return "MacOS";
}
// TODO godboutj 2019-07-30, Add other *nix check here
return "Linux";
}
return "Windows";
}
def IsMacOS() {
return GetOS() == "MacOS";
}
def IsLinux() {
return GetOS() == "Linux";
}
def IsWindows() {
return GetOS() == "Windows";
}
Then you can manipulate the path:
/*
* Path Manipulation
*/
def ToWindowsPath(path) {
return path.replace("/", "\\");
}
def ToUnixPath(path) {
return path.replace("\\","/");
}
def ToNativePath(path) {
if(isUnix()) {
return ToUnixPath(path);
}
return ToWindowsPath(path);
}
This allow for very simple scripts and make it bearable to work with the Jenkins API.