I am attempting to extract the Version tags from a git repo using some regex functions from groovy.
def command = "\"C:/Program Files (x86)/Git/bin/sh.exe\" --login -i -c \"git ls-remote user#mysever:myproject.git refs/tags/[vV]*?.*?.*?\""
def proc = command.execute()
proc.waitFor()
def str = proc.in.text
def pattern = ~/^refs\/tags\/[vV][0-9]+\.[0-9]+\.[0-9]+$/
System.out.println("is everything a string? " + str.tokenize().every{ it instanceof String })
System.out.println("String: $str")
System.out.println("split: ${str.split()}")
System.out.println("contains refs/tags/V0.0.0?: ${str.split()*.trim().contains('refs/tags/V0.0.0')}")
System.out.println("contains refs/tags/V0.0.1?: ${str.split()*.trim().contains('refs/tags/V0.0.1')}")
System.out.println("grep: " + ['refs/tags/V0.0.0', 'refs/tags/V0.0.1'].grep(pattern))
System.out.println("split grep: " + str.split().grep(pattern))
System.out.println("split findAll: " + str.split().findAll{ it =~ pattern })
And my output is this:
String: SHA1asdf refs/tags/V0.0.0
SHA1fdsa refs/tags/V0.0.0^{}
SHA1hgfd refs/tags/V0.0.l
SHA1dfgh refs/tags/V0.0.l^{}
split: [SHA1asdf, refs/tags/V0.0.0, SHA1asdf, refs/tags/V0.0.0^{}, SHA1hgfd, refs/tags/V0.0.l, SHA1dfgh, refs/tags/V0.0.l^{}]
contains refs/tags/V0.0.0?: true
contains refs/tags/V0.0.1?: false
grep: [refs/tags/V0.0.0, refs/tags/V0.0.1]
split grep: [refs/tags/V0.0.0]
split findAll: [refs/tags/V0.0.0]
Why isn't the tokenize().grep() producing the expected answer?
I am using Groovy 2.3.6
UPDATE: I've added more test results, see code and output
Not sure why, but your version V0.0.1 is actually an character l and not 1.
If you just the run the following sample (just changed the str), grep will work just fine:
def str = """
SHA1asdf refs/tags/V0.0.0
SHA1fdsa refs/tags/V0.0.0^{}
SHA1hgfd refs/tags/V0.0.1
SHA1dfgh refs/tags/V0.0.1^{}
"""
def pattern = ~/^refs\/tags\/[vV][0-9]+\.[0-9]+\.[0-9]+$/
System.out.println("String: $str")
System.out.println("tokenize: ${str.tokenize()}")
System.out.println("grep: " + ["refs/tags/V0.0.0", "refs/tags/V0.0.1"].grep(pattern))
System.out.println("tokenize grep: " + str.tokenize().grep(pattern))
produces
grep: [refs/tags/V0.0.0, refs/tags/V0.0.1]
tokenize grep: [refs/tags/V0.0.0, refs/tags/V0.0.1]
Related
We need to return as an option on this Jenkinsfile only the revision number from our k8s applications, but the command returns the entire output, and all my regex and escapes on the command was not working on it. Here is the code:
choiceType: 'PT_SINGLE_SELECT',
description: 'Revision of the application on kubernetes',
name: 'revision',
omitValueField: false,
randomName: 'choice-parameter-5633384460832177',
referencedParameters: 'namespaces,deployment',
script: [
$class: 'GroovyScript',
script: [
classpath: [],
sandbox: true,
script: """
if (namespaces.equals("Select")){
return["Nothing to do - Select your deployment"]
} else {
def revResult = null
def kubecmd0 = "kubectl rollout history deploy --kubeconfig=${kubefilePrd} -n " + namespaces + " " + deployment + " "
def kubecmd1 = kubecmd0.execute().in.text.split().toList()
return kubecmd1
}
"""
]
On Jenkins's job:
printscreen
Is there any function or magic regex that could solve this?
Problem solved:
[$class: 'CascadeChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
description: 'Revision of the application on kubernetes',
name: 'revision',
randomName: 'choice-parameter-5633384460832177',
referencedParameters: 'namespaces,deployment',
script: [
$class: 'GroovyScript',
script: [
classpath: [],
sandbox: true,
script: """
if (namespaces.equals("Select")){
return["Nothing to do - Select your deployment"]
} else {
def command = "kubectl rollout history deploy --kubeconfig=${kubefilePrd} -n " + namespaces + " " + deployment + "| grep -v REVISION | grep -v deployment | cut -f1 -d' '"
def output = ['bash', '-c', command].execute().in.text
return output.split().toList()
}
"""
]
Basically, it's necessary to call a bash, and not use groovy directly. Works for me. :)
I currently have the following PS script to extract the SW version from a Git tag and integrate it into the built assembly.
This works for tags like v1.2.3 and creates file-versions and product-versions such as e.g. 1.2.3.16 and 1.2.3.16-13b05b79
# Get version info from Git. For example: v1.2.3-45-g6789abc
$gitVersion = git describe --match "v[0-9]*" --long --always --dirty;
# Get name of current branch
$gitBranch = git rev-parse --abbrev-ref HEAD;
# Write Git information to version.txt
$versionFile = $args[1] + "\version.txt";
"version: " + $gitVersion > $versionFile;
"branch: " + $gitBranch >> $versionFile;
# Parse Git version info into semantic pieces
$gitVersion -match '[v](.*)-(\d+)-[g](.+)$';
$gitTag = $Matches[1];
$gitCount = $Matches[2];
$gitSHA1 = $Matches[3];
# Define file variables
$assemblyFile = $args[0] + "\Properties\AssemblyInfo.cs";
# Read template file, overwrite place holders with git version info
$newAssemblyContent = Get-Content $assemblyFile |
%{$_ -replace '\$FILEVERSION\$', ($gitTag + "." + $gitCount) } |
%{$_ -replace '\$INFOVERSION\$', ($gitTag + "." + $gitCount + "-" + $gitSHA1) };
echo "Injecting Git Version Info to AssemblyInfo.cs"
$newAssemblyContent > $assemblyFile;
I would now like to extend the regex in this script, so that I can use tags with a brief description such as v1.2.3-description, where description can be of variable length.
Ideally, the regex should allow for dashes in the description so that v1.2.3-description-with-dashes would also be valid and any other characters that are allowed in Git tags.
What makes this difficult for me (I have tried) is that git describe command will output this as v1.2.3-description-with-dashes-16, how I can distinguish between the dashes that belong to the Git-output and those that belong to the description.
Using RegEx (and using the new examples) this is what you can do:
$gitVersion -match '(?<tag>v\d+\.\d+\.\d+)(?:-?(?<description>\D+)?)(?:-?(?<count>\d+)?)(?:-?(?<sha1>gd[0-9a-f]+))(?:-?(?<dirty>.+)?)'
$gitTag = $Matches['tag']
$gitDescription = ($Matches['description']).Trim("-")
$gitCount = if($Matches['count']) { $Matches['count'] } else { 1 } # if no count is found, we assume 1 ??
$gitSHA1 = $Matches['sha1']
$gitDirty = $Matches['dirty']
Testresults:
teststring tag description count sha1 dirty
--------------------------------------------------- ------- ------------------------- ----- --------- -----
v1.2.3-123-gd9b5a775-dirty v1.2.3 123 gd9b5a775 dirty
v1.2.3-description-123-gd9b5a775-dirty v1.2.3 description- 123 gd9b5a775 dirty
v1.2.3-description-with-dashes-123-gd9b5a775-dirty v1.2.3 description-with-dashes- 123 gd9b5a775 dirty
v1.2.3-description-with-dashes-123-gd9b5a775 v1.2.3 description-with-dashes- 123 gd9b5a775
v1.2.3-description-with-dashes-gd9b5a775 v1.2.3 description-with-dashes- gd9b5a775
v1.2.3-45-gd9b5a775 v1.2.3 45 gd9b5a775
v1.2.3-gd9b5a775 v1.2.3 gd9b5a775
What is the correct way to tokenize a string on double-forward-slash // in a Jenkinsfile?
The example below results in the string being tokenized on single-forward-slash / instead, which is not the desired behavior.
Jenkinsfile
An abbreviated, over-simplified example of the Jenkinsfile containing the relevant part is:
node {
// Clean workspace before doing anything
deleteDir()
try {
stage ('Clone') {
def theURL = "http://<ip-on-lan>:<port-num>/path/to/some.asset"
sh "echo 'theURL is: ${theURL}'"
def tokenizedURL = theURL.tokenize('//')
sh "echo 'tokenizedURL is: ${tokenizedURL}'"
}
} catch (err) {
currentBuild.result = 'FAILED'
throw err
}
}
The Logs:
The log output from the preceding is:
echo 'theURL is: http://<ip-on-lan>:<port-num>/path/to/some.asset'— Shell Script<1s
[ne_Branch-Name-M2X23QGNMETLDZWFK7IXVZQRCNSWYNTDFJZU54VP7DMIOD6Z4DGA] Running shell script
+ echo theURL is: http://<ip-on-lan>:<port-num>/path/to/some.asset
theURL is: http://<ip-on-lan>:<port-num>/path/to/some.asset
echo 'tokenizedURL is: [http:, <ip-on-lan>:<port-num>, path, to, some.asset]'— Shell Script<1s
[ne_Branch-Name-M2X23QGNMETLDZWFK7IXVZQRCNSWYNTDFJZU54VP7DMIOD6Z4DGA] Running shell script
+ echo tokenizedURL is: [http:, <ip-on-lan>:<port-num>, path, to, some.asset]
tokenizedURL is: [http:, <ip-on-lan>:<port-num>, path, to, some.asset]
Note that the logs show that the string is being tokeni on / instead of on //.
tokenize takes string as optional argument that may contain 1 or more characters as delimiters. It treats each character in string argument as separate delimiter so // is effectively same as /
To split on //, you may use split that supports regex:
theURL.split(/\/{2}/)
Code Demo
My VCS has these tags
0.0.3.156-alpha+2
0.0.3.154
0.0.3.153
build-.139
build-.140
build-.142
build-0.0.1.28
build-0.0.1.29
build-0.0.1.30
build-0.0.1.32
I want to git describe --match "<regex>" to get the latest tag of the form number.number.number.number (so it's 0.0.3.154 in this case)
I have tried with git describe --match "[0-9]*.[0-9]*.[0-9]*.[0-9]*$" but it doesn't result in anything, and neither do these pattern:
"[0-9]*.[0-9]*.[0-9]*.[0-9]+"
"[0-9]*.[0-9]*.[0-9]*.[0-9]{1,}"
I need to get the latest tag in other to bump version for the next release. So i'm thinking of doing this automatically. Please let me know if I miss anything
Thanks
UPDATE:
In my build.gradle file I have a function to get tag like this (follow #Marc reply):
version getVersionFromTag()
def getVersionFromTag() {
def stdout = new ByteArrayOutputStream()
exec {
commandLine 'git', 'tag', '|' , 'grep', '^\([0-9]\+\.\?\)\+$', '|', 'sort' , '-nr', '|', 'head', '-1'
standardOutput = stdout
}
return stdout.toString().trim()
}
Here it gives errors Unexpected Char '\' in the regex above. Hence I removed them to becomes '^([0-9]+.?)+$', then it runs fine but in my final artifact, it does not have the version appended to the name (i.e helloword.jar instead of helloword-0.0.3.154.jar
=> My question is how should I put #Marc's suggested command to the gradle function correctly?
For testing I've put the output of your git describe in a file. This will do:
cat file | grep '^\([0-9]\+\.\?\)\+$' | sort -nr | head -1
0.0.3.154
Suppose you've created some irregular formatted tags and you want to use those as well (like your build--tags) for finding the highest tag:
sed -E 's/^[^0-9.]*//' | grep '^\([0-9]\+\.\?\)\+$' | sort -nr | head -1
Hello everyone and happy new year! I have a text from which I like to return a specific area from a specific string using a python script!
This is the text I have
#!/bin/sh
case "$1" in
start)
ulimit -s 1024
/usr/bin/oscam --config-dir /etc/tuxbox/config/oscam --daemon --pidfile /tmp/oscam.pid --restart 2 --utf8
;;
stop)
kill `cat /tmp/oscam.pid` 2> /dev/null
;;
restart|reload)
$0 stop
sleep 1
$0 start
;;
version)
echo "svn8631"
;;
info)
echo "oscam svn8631"
;;
*)
echo "Usage: $0 start|stop|restart"
exit 1
;;
esac
exit 0
from the text above I need to create a python command that always returns only what is written where the oscam svn8631 is written between the quotes! So far the only thing I managed to do is return another area of this text using this code
try:
f = open("/etc/init.d/softcam", "r")
content = f.read()
f.close()
except:
content = ""
contentInfo = content.split("\n")
if (content != ""):
for line in contentInfo:
if line.__contains__("usr/bin/"):
idex = line.index("n/")
line = line[(idex + 2):]
return line
This of course returns what's after the usr/bin text, and I need another area which comes after the word info). Can anyone help me please? I don't know how to make my script read this specific area I need! Thanks in advance!
Using the content variable that you have created, the
"oscam svn8631" text can be extracted with:
for chunk in content.split(";;"):
if chunk.strip().startswith('info)'):
return chunk.split('"')[1]
The natural way to break up a bash case statement is by splitting it on ";;". Then, we identify the info section (chunk.strip().startswith('info)')) and select the first quoted string in that section (chunk.split('"')[1]).