I am trying to add a "validation" stage in Jenkinsfile based on the time. If it is later than 16, validation is required, otherwise not.
the if statement is not working
here I am declaring the variable
HOUR=sh(returnStdout: true, script: 'date +"%H"').trim().toInteger()
and here is the stage
stage('validation') {
steps {
script {
if ( HOUR > 16 ) {
echo "Validation is required, time now is $HOUR"
}
else {
echo "No validation required, time now is $HOUR"
}
}
}
}
and here is the output
Validation is required, time now is 9
the value of the variable HOUR is correct, but the if statement doesnt work correctly
thanks in advance
Try first to refer to your variable with the ${xx} syntax:
if ( ${HOUR} > 16 ) {
Actually, that would be to be defined in an environment step to be working, as ${env.HOUR}, as illustrated here.
The OP Judy1989 confirms in the comment that you can use HOUR, but in two steps:
HOUR=sh(returnStdout: true, script: 'date +"%H"').trim()
...
if ( HOUR.toInteger() > 16 )
You can see an example of such a deferred use in this question.
Related
I have a pretty large repository and need to include static analysis, since it takes far too long (about 4 hours) for a normal working day we have a cron set to trigger the build automatically every morning purely to perform the static analysis stage and the way we have it set up it only does the static analysis if there has been a change in the code otherwise the static analysis becomes redundant.
The problem lies with the cron, because it is set every day we are now losing build history as well as artifacts.
I've tried to conditionally set the cron but that didn't seem to work since it should have triggered the build this morning and didn't.
triggers {
cron ( checkBuildStatus() )
}
def checkBuildStatus(){
if (currentBuild.changeSets.size() > 0){
return '0 4 * * 1-5 '
}
else {
return ''
}
}
Even if the above implementation worked I'm still not convinced that it would solve my problem of "empty" builds.
Is there a way to trigger a stage/step after working hours and only once (not everyday)?
Any advice will be greatly appreciated.
I decided to change my approach and found the best solution. I created a method, it first checks if there has been a change in the code between the current build and the one before it, and also checks that the branch name is 'master'. I then went ahead and checked the day of the week and set the cron to the following day (e.g if the build is on a Monday the cron will be set to Tuesday morning where it will then perform the static analysis stage). Now the cron will only be set if there has been a change in code and always only for the next day (of course until the next week but I'm hoping there will be changes on the master branch at least every week therefore resetting the cron)
def setCronTrigger(){
if (currentBuild.changeSets.size() > 0 && BRANCH_NAME.equals('master')){
Calendar calendar = Calendar.getInstance()
def day = calendar.get(Calendar.DAY_OF_WEEK)
cron = '* 4 * * ' + day
return cron
}
else {
return ''
}
}
well we can try to solve that problem in another way.
let's create one more job, e.g. cronTrigger. That jobs only triggers external job with static analysis.
if (currentBuild.changeSets.size() > 0) {
build(job: externalJobName, parameters: []) // run another job
}
You can keep more build. That possible to changes as well
Is it possible to give multiple values as input in a string parameter in the Jenkins job..?
If yes, what will be the syntax and how are we calling that in a for loop so the values take one after the other.?
This is for a declarative job in Jenkins.
Thank you for the help in advance
parameters {
string(name: "usernames", value: list.join (","), description: "enter the user names")
}
stages{
need the syntax for this --> //for user in usernames list
do
$echo ---> username
this username which print will be called in my curl command one after the other.
so please do help me with the right path
Generally it is only possible to pass one string.
That being said, since you are using strings you can encode whatever data you want in them.
Suppose you want to pass the pipeline a list of strings myList with values ['foo', 'bar', 'baz']. In the calling job you could simply do:
build ... parameters(string(name: "myString", value: myList.join(",")))
which passes 'foo, bar, baz' to the called job. There you could parse it out again:
params.myString.split(',') // results in ['foo', 'bar', 'baz']
To iterate over this, you could use a for-in loop or a list function like each or collect.
In order to iterate over all the elements you receive you can use the each method
stages {
stage("Iterate over parameters"){
script{
def userNames = params.userNamesString.split(',')
userNames.each { user ->
echo "$user"
}
}
}
}
Alternativly (instead of the userNames.each block you can just use a for-in statement:
for(userName in userNames){
echo "$userName"
}
For more informations on this please have a look at the links I included in my previous answer.
if(Total_sell_pos() == 0 && Total_buy_pos() == 0) {
double previous_balance = AccountBalance(); //usd1000
}
if (AccountEquity() > previous_balance + (previous_balance *0.05)){ //usd1000 + 50 = usd1050
CloseSellOrders();
CloseBuyOrders();
Delete_Pendings();
}
if Equity more than usd1050 then delete pending and orders.
But why when run the code, it keep delete pending and orders immediately even when Equity is less than previous balance?
The following code is the problem, and I replace it :
AccountEquity() > previous_balance + (previous_balance *0.05)
with
AccountEquity() > 1050
then only it works. I did try to check the value :
double check_value = previous_balance + (previous_balance *0.05);
printf (check_value); //1050
May I know why I cannot use the following code?
AccountEquity() > previous_balance + (previous_balance *0.05)
Q: How to store AccountBalance() into a variable?
Let's start with the variable - declare it:
double aPreviousBALANCE;
The scope-of-declaration is driven by the enclosing code-block boundaries. MQL4/5 can declare a variable on the "global"-scope, that may become visible from inside other code-blocks, but if any such has a variable name identical to the "global"-scope defined one, the locally declared ( explicitly in the code, or introduced from the function-parameters' declaration in the call-signature specification ) will "shade-off" the access to the variable declared on the "global"-scope. This you have to check in the original code and MQL4/5-IDE may warn you about such collision(s) during the compilation ( ref. Compiler Warning Messages ).
Let's store in it the actual state, we'll have more steps here:
RefreshRates(); // Force a state-update
aPreviousBALANCE = AccountInfoDouble( ACCOUNT_BALANCE ); // Store an updated value
Q: May I know why I cannot use the following code?
Well, any language, MQL4/5 not being an exception, has some order of execution of mathematical operators. MQL4 need not and does not have the warranty about using the same one as any other language we may have had some prior experience. So, always be rather explicit in this a specify all ordering via explicit parentheses, this will save you any further "surprises" when the language parser / compiler will suddenly change the priority of operators and sudden nightmares will appear. Not worth a single such shock to ever happen:
if ( ( ( a * b ) + c ) < fun() ) // is EXPLICIT and a way safer, than
if ( a * b + c < fun() ) // is DEPENDENT on not having {now|in future}
// a binary boolean (<)-operator
// a higher priority than (+)-op
so, rather be always explicit and you remain on the safer side.
Finally, test:
RefreshRates(); // Force a state-update
if ( ( aPreviousBALANCE * 1.05 ) < AccountInfoDouble( ACCOUNT_EQUITY ) )
{
...
}
Also check, how are your settings pre-set from the Broker-side - they run a Support-Line for you to ask about their settings:
Equity calculation depends on trading server settings.
Print( "Profit calculation mode for SYMBOL[ ",
Symbol(),
" ] is ",
MarketInfo( Symbol(), MODE_PROFITCALCMODE ),
" { 0: mode-FOREX, 1: mode-CFD, 2: mode-FUTURES }."
);
And where is my AccountBalance() function?
Recent Terminal Builds use a set of new types of calls to:
AccountInfo{Integer|
Double|
String}( <anEnumDrivenItemIDENTIFIER>
)
SymbolInfo{Integer|
Double|
String}( <aSymbolNAME>,
<anEnumDrivenItemIDENTIFIER>
)
to name just a few, so re-read the documentation to adopt the most recent changes. Always. ALAP when your Terminal has got a new Build updated ( might be seen when loading a new version of Help files for the MQL4-IDE and/or Terminal ).
Well, this happens. MQL4 evolves and some features we were used to for ages cease to exist, start to suddenly yield inaccurate or indefinite result or change its behaviour ( ol' MQL4-ers still remember the day, when string data type simply ceased to be a string in silence and suddenly started to become a struct. Ok, it was mentioned somewhere deep inside an almost unrelated page of an updated Help-file, yet the code-crashes were painful and long to debug, analyze and re-factor )
I have a jenkins job configured to run hourly. I want the success build mail to be sent as email only once a day. Email-Ext gives me the option to send emails for all success , failures etc. But what i wanted is the ability to send success email only once.
This is an old question and you have probably found your own workaround already, but I had a similar need and I thought I'd share my solution anyway. What I was trying to do was generate a once-daily summary email of jobs in a failed state. This is fundamentally very similar to sending a once-daily success report for a single job.
My solution uses a Groovy build step coupled with the Email-Ext plugin's pre-send script feature. I got the idea from the Nabble thread referenced in the comments above. See also Email-Ext Recipes on the Jenkins site.
Here's the initial groovy script that determines which builds are failed, configured under Execute System Groovy Script. You could do something similar to determine whether your build succeeded or failed:
// List the names of jobs you want to ignore for this check
ignore = [ ]
// Find all failed and unstable jobs
failed = hudson.model.Hudson.instance.getView("All").items.findAll{ job ->
job.getDisplayName() != "Daily Jenkins Job Nag" &&
!ignore.contains(job.getDisplayName()) &&
job.isBuildable() &&
job.lastCompletedBuild &&
(job.lastCompletedBuild.result == hudson.model.Result.FAILURE ||
job.lastCompletedBuild.result == hudson.model.Result.UNSTABLE)
}
// Log the job names so the build results are legible
failed.each { job ->
println(job.getDisplayName() +
" " + job.lastCompletedBuild.result +
" at build " + job.lastCompletedBuild.number +
" (" + job.lastCompletedBuild.timestamp.format("yyyy-MM-dd'T'HH:mm ZZZZ") + ")");
}
// Return failure if there are any failed jobs
return failed.size
Then, down in the Editable Email Notification section, I set the Email-Ext plugin to notify on failure. I set Content Type to Plain Text (text/plain), left Default Content empty, and set the following as the Pre-send Script:
failed = hudson.model.Hudson.instance.getView("All").items.findAll{ job ->
job.getDisplayName() != "Daily Jenkins Job Nag" &&
job.isBuildable() &&
job.lastCompletedBuild &&
(job.lastCompletedBuild.result == hudson.model.Result.FAILURE ||
job.lastCompletedBuild.result == hudson.model.Result.UNSTABLE)
}
def output = StringBuilder.newInstance()
output << "<html>\n"
output << " <body>\n"
output << "<p>Jenkins reports the following failed jobs:</p>"
output << " <ul>\n"
failed.each { job ->
url = hudson.model.Hudson.instance.rootUrl + job.url + "/" + job.lastCompletedBuild.number + "/"
output << " <li>"
output << "" + job.displayName + ""
output << " " + job.lastCompletedBuild.result
output << " at build " + job.lastCompletedBuild.number
output << " (" + job.lastCompletedBuild.timestamp.format("yyyy-MM-dd'T'HH:mm ZZZZ") + ")"
output << "</li>\n"
}
output << " </ul>\n"
output << " </body>\n"
output << "</html>"
msg.setContent(output.toString(), "text/html")
The key is that you have access to the msg object, which is a MimeMessage. You can set the content of the MIME message to whatever you want.
In this case, I'm generating a list of failed jobs, but in your case it would be whatever message you want to receive for your once-daily success report. Depending on what you need, you could have Email-Ext send a result for every build rather than just for failed builds.
How about suppressing e-mails if insufficient time has lapsed since the previous e-mail? Although not precisely what was requested, a pre-send script like this might be worth considering for its simplicity?
if (build.result != hudson.model.Result.SUCCESS) {
cancel = true;
}
else {
try {
long minEmailGap = 1000 * 60 * 60 * 16; // 16 hours in milliseconds
File file = new File("/TimestampForMyJob.txt");
if (file.exists() == false) {
file.createNewFile();
}
else {
long currentTime = (new Date()).getTime();
if (file.lastModified() + minEmailGap > currentTime) {
cancel = true;
}
else {
file.setLastModified(currentTime);
}
}
}
catch(IOException e) {
// We can't tell whether the e-mail should be sent out or not, so we do nothing
// and it just gets sent anyway - probably the best we can do with this exception.
}
}
Well, there is no plugin that can do that for you. The default email feature in Jenkins is very simple and it works fine. There is Email-ext plugin though, and this one can do lot more for you.
First of all, with Email-ext, you can configure a specific trigger to send the email notification - it can be on success or failure, which is similar to the default behaviour of Jenkins. But then you have the more refined one, like First failure and Still failing. This will give you a great deal of control on when and to whom (Recipients list, Commiter or Requester) your Jenkins will send an email. In my case a good configuration here will help a lot with email traffic generated by Jenkins. And you can send specific emails in specific situation to specific list of people - great!
The other option, if you really do not need that level of control and want to just to limit the email traffic to one summary per day is to set up a mailing list. Most mailing list engines will let you send a daily digest of all email traffic to the list. It should be enough, although I really do not feel like it is actually a good option on the long term. I would definitely give a try to Email-ext plugin.
I am brand new to ZF2 and am trying to use a tableGateway to manage and update entries in a database. I am able to select and update items without a problem, but when inserting I get an error. Since the tableGateway class creates the query on the fly, how can I see the query itself?
$this->tableGateway->insert($data);
An error occurred during execution; please try again later.
Additional information:
Zend\Db\Adapter\Exception\InvalidQueryException
File:
/[redacted]/vendor/zendframework/zendframework/library/Zend/Db/Adapter/Driver/Pdo/Statement.php:220
Message:
Statement could not be executed
Just some notices to #zdenek-machek answer:
1) To profile database queries, BjyProfiler module should be installed too.
2) (skip if you use PDO) When I used BjyProfiler last time, there was an issue with mysqli connection (buffer_results option was not passed to ProfilingStatement class). Maybe it is fixed now, or I set it up in the wrong way, but my patch is to manually pass this parameter in BjyProfiler/src/BjyProfiler/Db/Adapter/ProfilingAdapter.php:
case 'Zend\Db\Adapter\Driver\Mysqli\Mysqli':
$statementPrototype = new Driver\Mysqli\ProfilingStatement($this->options['buffer_results']);
break;
3) ZendDeveloperTools displays count of queries, but doesn't list them. To list in the bottom of the page, I have modified view/zend-developer-tools/toolbar/toolbar.phtml in the following way:
<!-- END Zend Developer Toolbar -->
<?php
$queryProfiles = $this->getHelperPluginManager()->getServiceLocator()
->get('Zend\Db\Adapter\Adapter')->getProfiler()->getQueryProfiles();
echo '<ol>';
foreach($queryProfiles as $queryObj)
{
$query = $queryObj->toArray();
echo '<li>';
echo '<b>' . ($query['elapsed']*1000) . '</b> ms<br/>';
echo $query['sql'];
if(count($query['parameters']))
{
echo '<br/><i>Parameters:</i> ';
$list = array();
foreach($query['parameters'] as $key => $value)
$list[] = '?'. $this->escapeHtml($key)
."='". $this->escapeHtml($value) ."'";
echo implode(', ', $list);
}
echo '</li>';
}
echo '</ol>';
In my case I just covered this in one in try catch: $e->__toString() was the key
try {
this->tableGateway->insert($data);
} catch (\Exception $e) {
\Zend\Debug\Debug::dump($e->__toString()); exit;
}
Very elegant way how to see db queries is to use zend-developer-tools.
Easiest way how to use it is to install module by adding it to composer.json file
.....
"repositories": [
{
"type": "composer",
"url": "http://packages.zendframework.com/"
}
],
"require": {
"php": ">=5.3.3",
"zendframework/zend-developer-tools": "dev-master"
}
see documentation
For what I wanted to do, in Dev, which was to know exactly which queries were run associated to every step in the flow of my processes, this is what I did (using PDO with MySQL / MariaDB):
I went to the Statement class (vendor/zendframework/zendframework/library/Zend/Db/Adapter/Driver/Pdo/Statement.php)
I went to the execute method and just before it is executed I put:
...
error_log("DebugQ: ".print_r($this->getSql(),1).", ".print_r($this->getParameterContainer()->getNamedArray(),1));
try {
$this->resource->execute();
}
...
I wanted a quick and disposable solution to have the queries logged in the error logs. I was able to have all the queries and their conditions.