How to run multiple cucumberjs tags - cucumberjs

I'm using grunt tasks to run my feature files using grunt cucumberjs
grunt cucumberjs --cucumbertags=#favourite
Above command runs all the scenarios with #favourite tag. I have an issue where i want scenarios to run on different env with diff data that belongs to environment.
#Book
Scenario Outline: Search by Author
When I search for "Leo Tolstoy"
Then I should see "<number_of_books>" books
#qa_env
Examples:
| number_of_books |
| 5 |
#dev_env
Examples:
| number_of_books |
| 3 |
How can I run scenario #Book with #qa_env data and #Book with #dev_env data ?

From the readme of grunt-cucumber
========================================================================
tags
Type: String or Array
Default: ''
Only execute the features or scenarios with tags matching TAG_EXPRESSION. Scenarios inherit tags declared on the Feature level. The simplest TAG_EXPRESSION is simply a tag. Example: tags: '#dev'
When a tag in a tag expression starts with a ~, this represents boolean NOT. Example: tags: ~#dev
A tag expression can have several tags separated by a comma, which represents logical OR. Example: tags: #dev,#wip
To represent a logical AND, use an array. This is useful if you want to skip certain features and run other specific features. Example: tags: ['~#wip', '#dev']
========================================================================
When you are on Windows you need to mind the usage of single and double quotes

Related

How to get words by a given pattern of a variable in shell (Jenkinsfile)?

Currently I am facing a problem of how to extract the name of some test classes from a variable (Shell) in my Jenkinsfile.
Scenario: Every time a Pull request is created in Bitbucket, a Pipeline type job is activated in Jenkins where I have access to the variable called "description" in the Jenkinsfile.
For example, the input of the description variable can contain the following:
US-2371
Any description here
Test Classes: testclass1_tst,testclass_test
Any other description here.
Expected output:
Save in another variable only the following:
testclass1_tst,testclass_test
Note: I need the names of the test classes separated by ',' and the pattern is those test classes that end in tst, test, Test.
Thanks in advance.
Reference:
Jenkinsfile - Variable
Since Test Classes: is going to be present in all the descriptions, we can look for it and parse out classes.
echo $description | sed -r 's/(.*Test Classes: )(\w.+)([[:space:]])(.*)/\2/
This would get you
testclass1_tst,testclass_test

How can I get a list of directory names to pass in as an array to an Azure Pipeline template?

I'm trying to get a list of directories and then pass that array to an azure pipeline template. Here's the code for getting the array names:
- script: |
cd $(Build.StagingDirectory)
directoryList=( $(ls -d */ | sed 's#/##') ) # sed gets rid of the trailing slash
echo $directoryList
echo "##vso[task.setvariable variable=directoryList]$directoryList"
# Archive all directories in staging directory created by sam build
- template: zip-template.yml
parameters:
directories:
- $(directoryList)
One thing I noticed is that echo $(directoryList) only outputs the first entry. When I try to pass this to the template it only performs 1 iteration which makes me think I'm not creating the array correctly. Here's the azure pipeline template that should receive the list of directory names:
parameters:
- name: "directories"
type: object
default: {}
steps:
- ${{ each dir in parameters.directories }}:
- task: ArchiveFiles#2
displayName: "Zip ${{ dir }}"
inputs:
rootFolderOrFile: '$(Build.StagingDirectory)/${{dir}}'
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.StagingDirectory)/${{dir}}/package.zip'
replaceExistingArchive: true
Another odd outcome I observed is that the displayName outputs "Zip ($directoryList)" when I run the pipeline. What can I do to get the list of directories an pass that to the template to iterate through and run the zip task multiple times?
There are a number of things going on here, and ultimately I don't believe this is possible the way you're doing it.
The immediate cause of your problem with directoryList is that the syntax to access all elements of a Bash array is not $arrayName, but ${arrayName[#]}. $arrayName is equivalent to accessing element 0 (${arrayName[0]}).
BTW, parsing ls is a bad practice. A better way here would be:
IFS=$'\n' directoryList=($(find ./* -maxdepth 1 -type d -printf '%f\n'))
This prevents all manner of issues that could occur when your directories have weird names (if any contain newlines, this could still get messed up, but in this context, if that happens you probably have bigger problems).
I do not know if a VSO log command (the last line of your script) will split up a variable containing spaces or newlines into an array that you can loop over -- I'm not too familiar with the for-each template syntax. You might want to check this, though, because the log command is just writing a string of text onto standard output, it's not somehow passing the array itself back to Azure DevOps.
Another odd outcome I observed is that the displayName outputs "Zip ($directoryList)" when I run the pipeline. What can I do to get the list of directories an pass that to the template to iterate through and run the zip task multiple times?
${{ }} expressions are evaluated at template compile time, prior to when your script is running to populate the directoryList variable on the pipeline using the VSO log command. You have to use $[ ] expressions if you want to evaluate them at runtime. Unfortunately, I do not believe there is a way to use $[ ] expressions to loop over a step:
Compile time expressions can be used anywhere; runtime expressions can be used in variables and conditions.
I'm thinking your best bet is to do the archive-files step within a Bash script, perhaps looping over that array you created earlier. Or just hard-code the list of directories into your pipeline or put them in a variable in the pipeline YAML that you have to update when the list of directories changes. The best approach may depend on how often that list of directories changes.
I am afraid that it's not supported defining an array as a variable, the variable syntax is variables: { string: string }.
Here is a Ticket about the Variable, you could refer to it.
The parameters support passing the Array.
From your requirement, you need to use command to get the directory list. But the Yaml parameters couldn't be set in the command.
In summary, we cannot pass the array to the template via variable to run the archive file task multiple times.
Workaround:
You could use Powershell script to get the directory list and archive them as ZIP.
Here is the Pipeline example(The tool is 7-zip):
steps:
- powershell: |
$arr = Get-ChildItem '$(Build.SourcesDirectory)' |
Where-Object {$_.PSIsContainer} |
Foreach-Object {$_.Name}
echo "##vso[task.setvariable variable=arr;]$arr"
displayName: 'PowerShell Script'
- powershell: |
$string = "$(arr)"
$Data=$string.split(" ")
foreach($item in $Data){
function create-7zip([String] $aDirectory, [String] $aZipfile){
[string]$pathToZipExe = "$($Env:ProgramFiles)\7-Zip\7z.exe";
[Array]$arguments = "a", "-tzip", "$aZipfile", "$aDirectory", "-r";
& $pathToZipExe $arguments;
}
create-7zip "$(build.sourcesdirectory)" "$(build.sourcesdirectory)/$item/package.zip"
}
displayName: 'PowerShell Script'
Explanation:
The first Powershell task is used to get the folder list in the target folder(source directory.) Then it will be send to the variable value, the type is string.
The second powershell task could get the variable and split it.
Finally, loop the result and compress it into zip through the script.
Result:

Ruby or Bash or Grep regex is not working for '?' i.e. 0 or 1 occurrence of previous character

Linux Red Hat Enterprise Linux Server release 6.9 (Santiago)
Issue:
I have 2 Jenkins jobs and they both which calls another common/reusable downstream job (that uses a regex to pick its rpm). Actual code is written in Ruby (where I was using ::Dir.glob("<pattern>",'') and it didn't work for picking the correct rpm name (without giving me any error), but here I'm just focusing on the regex part.
In job1, in my workspace, I see myrpm.rpm and myrpm-extra.rpm.
In job2, in my workspace, I see myrpm-3.0.0.1027-2018_12_21_121519.noarch.rpm and myrpm-extra-3.0.0.1027-2018_12_21_121519.noarch.rpm rpms which I'm getting after downloading these files from Artifactory via some AQL.
Once rpms are downloaded from Aritfactory i.e. available in Jenkins workspace , then I use this common downstream job to pick a given rpm that I need by
using "${rpmname}*.rpm" regex.
The issue is, when I'm passing rpmname parameter value as "myrpm", the logic is picking myrpm-extra.rpm (in Job1) or myrpm-extra-3.0.0.1027-2018_12_21_121519.noarch.rpm (Job2) instead of the correct one (non extra one), as - character's order comes first due to ASCII sequence.
I tested the regex and seeing why in the last command I didn't see expected output. Isn't 1? in the regex going to give us any lines which has arun with either 0 or 1 occurrence of character 1?
[giga#linux-server giga]# echo -e "arun\narun1\narun2\narun11" |grep "arun"
arun
arun1
arun2
arun11
[giga#linux-server giga]#
[giga#linux-server giga]# echo -e "arun\narun1\narun2\narun11" |grep "arun1"
arun1
arun11
[giga#linux-server giga]#
[giga#linux-server giga]# echo -e "arun\narun1\narun2\narun11" |grep "arun1?"
[giga#linux-server giga]#
Questions:
1. Why this works if I use egrep?
2. Why it didn't work with grep, while grep man page / examples tells it supports it?
3. What regex can I use so that if I pass myrpm as the job parameter's value, then it works in both Job1 and Job2 where rpm filename contains either the short and full rpm name.
Here: https://www.cyberciti.biz/faq/grep-regular-expressions/ (search for grep Regular Expression Operator) and
man grep shows:
Repetition
A regular expression may be followed by one of several repetition operators:
---------------------------------------------------------------
? The preceding item is optional and matched at most once.
---------------------------------------------------------------
* The preceding item will be matched zero or more times.
+ The preceding item will be matched one or more times.
{n} The preceding item is matched exactly n times.
{n,} The preceding item is matched n or more times.
{,m} The preceding item is matched at most m times. This is a GNU extension.
{n,m} The preceding item is matched at least n times, but not more than m times.
egrep is the same as grep -E, in your case, the regex used, need -E or -P to support ?.
Search for different regex support please. There're POSIX, Extended, and Perl etc.
Resources:
POSIX Basic and Extended Regular Expressions
Perl regular expressions
Regular expression
Final Solution:
Used this regex pattern: ${package_name}(?:-[0-9]*)?\..*rpm, example of code (in Ruby) is shown below.
In Ruby: after you change to the directory where the rpms existed, I got this line to find the correct rpm name. NOTE: In Ruby, ::Dir.glob("<pattern>",..) is not a real REGEX pattern, it's just a SHELL glob pattern.
wildcard = "#{new_resource.session['package_name']}(?:-[0-9]*)?\..*#{ext_type}"
rpmfullname = Dir["#{new_resource.session['package_name']}*.#{ext_type}"].select { |f| f =~ /#{wildcard}/ }.sort.first
This website greatly helped.
https://rubular.com/
with example pattern being myrpm(?:-[0-9]*)?\..*rpm:
and test cases strings as:
myrpm.rpm
myrpm-extra.rpm
myrpm-1.0.0_112233.noarch.rpm
myrpm-11.0.0_112233.noarch.rpm
myrpm-111.0.0_112233.noarch.rpm
myrpm-1.0_112233.noarch.rpm
myrpm-extra-1.0.0_112233.noarch.rpm
foo.yum
berayan.rpm
arun.yum
Toni.rpm
myrpm-1.0.0_112233.rpm

Working on Files in Similarly (but differently) Named Directories

I have 2 files on which I need to run various commands. These two files have the exact same name, but are in different folders. The trouble is in the folder names. I can count on these things in regards to the folders:
1) The path leading up to the folders will always be the same.
2) The first folder will always include one hyphen in the name.
a. Before the first hyphen will be the same across all servers.
b. After the first hyphen will be different across servers, but the same on the same server (like a servername, but not always specifically servername).
3) The second folder will always include the same name as the first folder, but with a second hyphen along with another random set of characters.
Here's a more visual breakdown:
Server01
/same/fld/path/dir1/
|
+--same-nameX/
| |
| +--sameFileName
|
+--same-nameX-abc123/
|
+--sameFileName
Server02
/same/fld/path/dir1/
|
+--same-nameY/
| |
| +--sameFileName
|
+--same-nameY-a1b2c3/
|
+--sameFileName
I'm scripting in bash, and I'm trying to write a script that works regardless of the server I'm running it on.
So my question is, how can I formulate a bash command (for simplicity, "cat") such that it authoritatively works on one file vs the other?
For exampe, this:
cat /same/fld/path/dir1/same-*-*/sameFileName
This will definitely give me the contents of "same-nameX-abc123/sameFileName"
However, this:
cat /same/fld/path/dir1/same-*/sameFileName
This won't work, because it will affect both files, and I want to specifically work on the file ".../same-nameX/sameFileName".
Any help would be appreciated.
To add additional clarity, this question isn't related to folder names with a single character difference. It's related to folders that are significantly different, but the differences lie between "hyphens". Here are some examples:
Server03
/same/fld/path/dir1/same-zxy12/sameFileName
/same/fld/path/dir1/same-zxy12-xYz/sameFileName
Server04
/same/fld/path/dir1/same-g1f2e3d4/sameFileName
/same/fld/path/dir1/same-g1f2e3d4-ab12c345/sameFileName
Server05
/same/fld/path/dir1/same-nmo/sameFileName
/same/fld/path/dir1/same-nmo-ab/sameFileName
Again, thank you, everyone, anyone, for your knowledge.
I would recommend using an extended glob to match the first file in each of your cases:
shopt -s extglob # enable extended globbing
cat /same/fld/path/dir1/same-!(*-)/sameFileName
This pattern will match any directory name not containing another -.
I think you can try use character range like this:
cat /same/fld/path/dir1/same-name[a-zA-Z$]/sameFileName

Using a Facter Fact within a fact for command execution

I am trying to write a custom facter module that incorporates a fact within a fact for the command via concatenation of the command string plus a facter fact variable:
Facter.add("customfact") do
setcode do
$string_to_parse = Facter::Util::Resolution.exec('somecommand' + $::fact)
end
end
Newbie to ruby and Puppet...
1. What would be the proper syntax to do something with this?
Is there any way to parse the output into an array of facts or what is the correct way to search the $string_to_parse for the content I need.
Here is an example of the output generated with the command:
TAG security-group sg-0a7a8a61 aws:cloudformation:stack-name awseb-e-5tzgj9fq5b-stack
I would need the security group and stack name.
You want to use Facter.value(:sourcefact) inside your new fact to access the variable. As for getting the individual values, you probably want those as separate facts, but you could pipe 'somecommand' + Facter.value(:sourcefact) + ' | awk {"print $3"}' will give you the security group (as an example).

Resources