custom variable (of a TFS build) can't be populated with expression - tfs

In build definition (on Variables tab) I am trying to define a custom variable (Build.Repository.Clean) using simple expression $[not(false)]. But when I print variables during build -- regardless of expression used, Build.Repository.Clean value is always false.
Strangely enough, definining it with something like $(FullBuild) (where FullBuild is another custom variable) works just fine.
Am I missing something?
Notes:
using TFS 2018
Backstory:
Trying to set Build.Repository.Clean variable depending on a custom variable QuickBuild (which can be set by user when kicking off a build). Tried specifying $[not(variables.QuickBuild)] (and other variations of same expression) -- no luck.
here is how it works right now (but I'd rather have QuickBuild instead of FullBuild -- just can't figure out how to negate a variable):

Update 3:
Well, ignore if it changes clean operation during queue time. For what you are looking for, you could try this format:
Build.Repository.Clean=$[not(eq(variables.QuickBuild,'True'))]
If QuickBuild=True, Build.Repository.Clean=False,
If QuickBuild=False, then Build.Repository.Clean.Clean=True
For example:
I have set the clean option in Get Source Step, Clean=true
Build.Repository.Clean=$(FullBuild)
FullBuild=false
Now when I queue the build, then try to change the FullBuild=false during queue
time.
What you thought, the Build.Repository.Clean should change to False , then the clean operation will not be executed. But the truth is, the Build.Repository.Clean is still True and the clean is executed.
Even you do not update the value of FullBuild=false during the queue time, directly set the value FullBuild=false in build pipeline. This will also not use.
In the opposite, if you set Clean=false in Get Source Step. No matter what kind of value you input in FullBuild or Build.Repostiory.Clean during queue build.
It will not clean during the build pipeline.
Conclusion: It's not able to change the clean operation during queue time. This is not related any expression at all. Not matter what kind of value you set for Build.Repository.Clean.
Update 2
After go through your question and all comments once again. Seems your truly goal is assigning the clean options at queue-time based another customized variable.
Since you are not able to change Build.Repository.Clean during queue time. So you are trying to use this workaround. It's not support. There is not a way to assign the clean options at queue-time.
You may have to pre-define this variable in your build pipeline.
Also take a look at this question: How to clean build using self-hosted agent when queuing
In your scenario, you can create two build pipelines as an ugly workaround. One for incremental build (Disable the Clean option in get source step, or use variable Build.Repository.Clean = False), and another one enable the Clean option.
Hope it's clearly.

Expressions are not evaluated when they are used to initialize custom variables (on Variables tab). I.e. variable value ends up being a string with value equal to your expression (e.g. '$[not(<whatever>)]'). Later, when that variable gets used in context that expect boolean -- it still doesn't get evaluated, instead it gets type-casted and any non-empty string yields true.
On the other hand variable substitution happens -- i.e. value $(MyVar) gets replaced with value of MyVar.
Built-in variable seem to be special in sense that if you override them -- this process happens at the start and it's value gets immediately replaced with resulting value.
Note -- this may (or may not) be related to this.
Bottomline: you can't use expressions to override value of a built-in variable.

Related

How to pass an array from Bazel cli to rules?

Let's say I have a rule like this.
foo(
name = "helloworld",
myarray = [
":bar",
"//path/to:qux",
],
)
In this case, myarray is static.
However, I want it to be given by cli, like
bazel run //:helloworld --myarray=":bar,//path/to:qux,:baz,:another"
How is this possible?
Thanks
To get exactly what you're asking for, Bazel would need to support LABEL_LIST in Starlark-defined command line flags, which are documented here:
https://docs.bazel.build/versions/2.1.0/skylark/lib/config.html
and here: https://docs.bazel.build/versions/2.1.0/skylark/config.html
Unfortunately that's not implemented at the moment.
If you don't actually need a list of labels (i.e., to create dependencies between targets), then maybe STRING_LIST will work for you.
If you do need a list of labels, and the different possible values are known, then you can use --define, config_setting(), and select():
https://docs.bazel.build/versions/2.1.0/configurable-attributes.html
The question is, what are you really after. Passing variable, array into the bazel build/run isn't really possible, well not as such and not (mostly) without (very likely unwanted) side effects. Aren't you perhaps really just looking into passing arguments directly to what is being run by the run? I.e. pass it to the executable itself, not bazel?
There are few ways you could sneak stuff in (you'd also in most cases need to come up with a syntax to pass data on CLI and unpack the array in a rule), but many come with relatively substantial price.
You can define your array in a bzl file and load it from where the rule uses it. You can then dump the bzl content rewriting your build/run configuration (also making it obvious, traceable) and load the bits from the rule (only affecting the rule loading and using the variable). E.g, BUILD file:
load(":myarray.bzl", "myarray")
foo(
name = "helloworld",
myarray = myarray,
],
)
And you can then call your build:
$ echo 'myarray=[":bar", "//path/to:qux", ":baz", ":another"]' > myarray.bzl
$ bazel run //:helloworld
Which you can of course put in a single wrapper script. If this really needs to be a bazel array, this one is probably the cleanest way to do that.
--workspace_status_command: you can collection information about your environment, add either or both of the resulting files (depending on whether the inputs are meant to invalidate the rule results or not, you could use volatile or stable status files) as a dependency of your rule and process the incoming file in the what is being executed by the rule (at which point one would wonder why not pass it to as its command line arguments directly). If using stable status file, also each other rule depending on it is invalidated by any change.
You can do similar thing by using --action_env. From within the executable/tool/script underpinning the rule, you can directly access defined environmental variable. However, this also means environment of each rule is affected (not just the one you're targeting); and again, why would it parse the information from environment and not accept arguments on the command line.
There is also --define, but you would not really get direct access it's value as much as you could select() a choice out of possible options.

Jenkins MultiJob Phases share ${BUILD_TIMESTAMP}

I have a parent jenkins multijob that calls 3 children jobs, passing to the children the same parameters the parent was built with.
Each child needs to use the same timestamp as it is a unique identifier that each child needs to search for on a webpage.
My problem is this:
When the parent is built, the "name" parameter is set to ${BUILD_TIMESTAMP}, lets call this "02201200" short for Feb 20, 12:00. Each child is called with "pass current job parameters". However, instead of each child receiving 02201200, they each receive ${BUILD_TIMESTAMP} and fetch this value again (eg 02201204).
How do I force the parent to evaluate ${BUILD_TIMESTAMP} and pass its evaluation to the children instead of the variable itself?
One possible solution would be to write the value of this time stamp to a file. Then you could reference that value in subsequent jobs via the "Parameters from properties file" option. Obviously you would just keep overwriting this file every time your job sequence runs.
I used this method and also ended up generally saving all metadata (system/environment variables, jenkins parameters, and build properties, etc) into a properties file and even archived them. This approach simplifies/works around many problems I had. Now, every build has its metadata archived, for downstream jobs or later references, I can get all necessary information from this one file; no extra parameters need to be passed around.
Furthermore, if anything goes wrong, the metadata is very helpful for investigating. I would recommend this simple strategy as it has proven extremely useful to myself and my team.

How to change a tfs build variable in script

I'm using TFS2015 update 1. I want to pass information from one build step to the next, how is this possible?
That seems like a very simple task, but I can't figure out how that's suppose to work. Passing a variable to a build step is easy, but passing information from one step to the next seems to be impossible. I hope I'm wrong.
You can call the task.setvariable Logging Command, which sets a variable in the variable service of taskcontext. The first task can set a variable, and following tasks are able to use the variable. The variable is exposed to the following tasks as an environment variable.
Example:
##vso[task.setvariable variable=testvar;]testvalue

Unit testing grails ConfigSlurper behavior

I'd like to write tests that would test behavior of externalized configs and assert that what gets set is what I expect. This is for the specific case where something like this is done:
Config.groovy:
a.reused.value = 'orig'
my.variable = '${a.reused.value}'
Externalized groovy file:
a.reused.value = 'new_value'
I expect that both a.reused.value and my.variable would be 'new_value'.
Now, I think I could have my unit test read in strings representing these config files (I do similar things for other unit tests to populate Holders.grailsApplication.config, for example), utilizing perhaps merge?
But what I cannot figure out is how to get the value that Grails actually gets during application run time. Instead, I get "${a.reused.value}" in my unit tests.
Is there a way to mimic this behavior of what Grails does of actually resolving this value? I did some digging around in Grails 2.4.4 source (which is what we are using) and didn't have any luck in figuring this part out. I also did try Eval.me(), but that doesn't seem to be quite right either.
While setting my.variable, you are not using a GString object, causing the expression to be treated as a value itself. Use double quotes to resolve expression automatically.
a.reused.value = 'orig' my.variable = "${a.reused.value}"
Update 1:
What you want to do is directly not possible. You are assigning the value to a variable from an expression. During evaluation of the config object for the first time, my.variable has been assigned a value, and now it doesn't contain an expression any more. So you have two options: 1) either reassign the second variable in external config also or 2) use a closure to assign the value to second variable.
my.variable = { -> "$a.reused.value" }
and while accessing do: grailsApplication.config.my.variable.call()
But again, in your code, you would have to be sure that this variable contains a closure not a value itself.

How do I change the Build number format parameter while queuing a build

I am using Visual Studio Online for Source Control and Build processes. I created a new build definition using the TfvcContinuousDeploymentTemplate.12.xaml. When Queuing a new build from within VS I have the chance to change some parameters, but I can't change the Build number format. What determines what shows up on that parameter list and how can I make sure the Build number format appears there?
My suggestion is to investigate modifying the build template to:
1) Take a custom input value, which I believe you can change on each invocation of the build; and
2) Finding the appropriate step to interrogate the existing Build Number and modify it based on this input.
This should get you started:
http://msdn.microsoft.com/en-us/library/dd647551.aspx
Alternatively, you could remove the Build Number Activity in its entirety and substitute your own – but I don’t think these measures are warranted in this case. This would get you started down that trail:
http://blogs.msdn.com/b/willbar/archive/2010/01/21/generating-custom-build-number-in-tfs-build-2010.aspx
HTH –
jlo
To show the property you have to edit the template, expand the arguments, search for Metadata and click on the ellipse towards the right of the row. Find the property you want, in my case it is BuildNumberFormat and change the View this parameter when: Always show the parameter

Resources