Mark Argo workflow step as skipped based on the step's own output - argo-workflows

I know that I can refer the output of previous steps to skip another step. Is it possible in argo to mark a step as skipped based on its output?
I am looking for something like this. This would not work but what would be an alternative?
steps:
- - name: hello1
template: echo
when: "{{steps.hello1.outputs.result}} != hello1"
arguments:
parameters:
- name: message
value: hello1

There is no way to mark a step as skipped based on its own output.
When a step is "marked as skipped" (in the UI, in its internal representation in Kubernetes, etc.) it's not simply being marked. The mark is an expression of the fact that the step was, in fact, skipped.
In order to read the output of hello1, you must first run hello1 - at which point it is not, in fact, skipped.
If you are executing hello1 more than once (recursively), then future iterations may be conditioned on the output of past iterations. That's the basis of Argo's coinflip-recursive example which "flips a coin" until the flip comes up heads.

Related

Azure pipeline parameter split doesn't work

I have a mutli-step azure pipeline used to trigger the execution of a certain job based on keywords I have in azure devops work items.
First step executed is a powershell script that stores into a 'validTags' variable a comma-separated list of strings:
Write-Host "##vso[task.setvariable variable=validTags]$csTags"
After this step, I correctly see the list formatted as I expect:
string1,string2,string3
The 'validTags' variable is then passed as a parameter to another pipeline in which I should split this list and trigger separate jobs:
- template: run.yml
parameters:
tags: $(validTags)
directory: 'path\to\tests'
platforms: 'platform1,platform2'
In the 'run' pipeline I defined this 'tags' parameter:
parameters:
- name: tags
type: string
default: 'someDefaultValue'
and I try to split the parameter:
- ${{each t in split(parameters.tags, ',')}}:
- script: |
echo 'starting job for ${{t}}'
but when I execute the pipeline, I have in 't' still the full string (string1,string2,string3) not splitted.
I have noticed that if I try to perform the split on the "platforms" parameter which is passed along with "tags" to the run.yml pipeline, it works, so it seems that the problem is related to the fact that I am trying to split a string stored in an external variable?
Anyone with a similar issue? Any help on this is much appreciated.
Thanks
For those interested in the outcome of this issue:
I tested several possible alternate solutions, including the use of global variables and group variables, but without success.
I submitted a request to MSFT engineering support to get some insight on this and their response is:
The pipeline does not support splitting the runtime variable with
template syntax ${{ }} currently, and we are not able to find other
workarounds to meet your request. Sorry for the inconvenience. Hope
you can understand.
So, to overcome the issue I removed the split at the pipeline level, as initially planned, but rather passed the comma-separated value's string to the template and added there the necessary processing in Powershell.
Another option would have been to perform all the operations from within the first PowerShell script step:
transform the 'run.yml' template in a separate pipeline
in the script, after getting the tags, loop over their values and trigger the 'run.yml' pipeline passing the single tag as a parameter.
I avoided this solution to keep the operations separate and have more control over the execution flow.

in build variable to detect rerun of failed builds

Is there an inbuilt pipeline or build variable to check if the run is actually a re-run of a job/stage.
I need to add this in condition as some of the steps needs to be skipped based on this variable.
- conditions: rerun()
Yes, there are variables regarding this:
System.JobAttempt - Set to 1 the first time this job is attempted, and increments every time the job is retried.
System.StageAttempt - Set to 1 the first time this stage is attempted, and increments every time the job is retried.
You can find the full variable list here.
You can use the predefinded variables System.JobAttempt or System.StageAttempt to determine if it is a re-run of a job/stage.
To skip a step if it is a re-run of a job/stage, you can set the condtion as below:
condition: eq(variables['System.JobAttempt'], '1')

How to add custom pipeline in azureDevops

i have create CI/CD pipeline in azureDevops.
i need to add custom condition for when only previous task succeeded then it will execute.
so please help me
what i have to write in Custom condition ?
I have attached below screen short where i need to add some custom condition.
i need to add custom condition for when only previous task succeeded then it will execute.
There is directly option Only when all previous tasks have succeeded, which is used to determine if all the previous tasks have succeeded.
If you want to give the condition that just when only the one previous task succeeded, there is no such out of box option to use. We could use the workaround that Napoleon answered:
write the result of the previous task to a variable and then check that variable in your condition
In addition, I posted this answer to emphasize the choice of conditions, we need use always() not succeeded() or failed(). That because the syntax of condition is for all previous steps/jobs:
Check the document Conditions for some more details.
For example:
I add three tasks in my pipeline:
Command line-Intentionally let it run failed
Run Inline Powershell-create a variable, assign it a value.
Write-Host "##vso[task.setvariable variable=TaskStatus;]Succeeded"
Command line-Custom Condition checking that variable.
and(always(), eq(variables['TaskStatus'], 'Succeeded'))
If we use the condition succeeded() or failed(), whether its execution is still affected by all previous task execution results (First command line task.)
Hope this helps.
You could write the result of the previous task to a variable and then check that variable in your condition.
i have found some custom condition which has fulfill my desire task.
in(variables['Agent.JobStatus'], 'Failed', 'Succeeded', 'SucceededWithIssues')
in above custom condition for if the prev task will 'failed' or 'succeeded' next task will executed.

Exception when exiting

I'm writing a chef recipe as shown below. I hope the recipe can stop to continue executing the resources after this, but without giving the exception.
Do you have any ideas about this except from doing exit(0)?
ruby_block "verify #{current_container_name}" do
block do
require "docker"
begin
container = Docker::Container.get(current_container_name)
rescue Docker::Error::NotFoundError => exception
container = nil
end
if container.nil?
exit(0)
end
end
end
You could use ignore_failure true in this ruby block instead of handling the exception. That way it would still output the error messages, but wouldn't treat it as a failure so would continue to execute subsequent resources.
If you want to abort a chef-run under a special circumstance - like the current Docker-container is not available - this is not possible. The solution is to rethink your problem - you want some code to be only run when a special condition is met.
You do this by either leaving the recipe (with a return true), encapsulating your configuration steps in a conditional-clause (like a if my_container.nil? then ... end) or you use node-attributes to step through conditions.
Let's say your cookbook x relies on three recipes, 1, 2 and 3. So if you'd like to define that 2 and 3 are only run if 1 was successful, you're able to to write the state of the 1st recipe into the node-attributes (f.e. node.normal['recipe1'] = 'successful').
In the other recipes you'll then define an entry-gate like:
return true if node['recipe1'] != 'succesful'
But be aware, if you're using node-attributes you'll need to use the ruby_block-resource (mostly) at the end of your first recipe because the bare-ruby-code is evaluated and run during the resource-compilation - which takes place before the converge-run.

Can a list of strings be supplied to Capistrano tasks?

I have a task whose command in 'run' is the same except for a single value. This value would out of a list of potential values. What I would like to do is create a task which would use this list of values to define the task and then use that same value in the command defined in 'run'. The point is that it would be great to define the task in such a way where I don't have to repeat nearly identical task definitions for each value.
For example: I want a task that will get the status of a single program from a list of programs that I have defined in an array. I would like to define task to be something like this:
set programs = %w["postfix", "nginx", "pgpool"]
programs.each do |program|
desc "#{program} status"
task :#{program} do
run "/etc/init.d/#{program} status"
end
end
This obviously doesn't work, but hopefully it shows what I am attempting here.
Thoughts?
Well, I answered my own question... with a little trial and error. I also did the same thing with namespace so the control of services is nice and elegant. It works quite nicely!
set :programs, %w[postfix nginx pgpool]
set :init_commands, %w[status start stop]
# init.d service control
init_commands.each do |init_command|
namespace :"#{init_command}" do
programs.each do |program|
desc "#{program} #{init_command}"
task :"#{program}" do
run "/etc/init.d/#{program} #{init_command}"
end
end
end
end