0

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):

build process variables

C.M.
  • 3,071
  • 1
  • 14
  • 33

2 Answers2

0

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

enter image description here

enter image description here

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.

enter image description here

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.

enter image description here

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.

enter image description here

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.

PatrickLu-MSFT
  • 49,478
  • 5
  • 35
  • 62
  • I thought about that -- that is why I used `$[not(false)]` which is supposed to be a [boolean literal expression](https://learn.microsoft.com/en-us/azure/devops/pipelines/process/expressions?view=azure-devops#boolean). Or does it have to be `$[not(False)]`? – C.M. Feb 27 '20 at 16:48
  • Weird... I ran few tests (where I set custom variable `Build.Repository.Clean` to various expressions) and now it is always `true`, not matter what that expression was (`$[not(true)]`, `$[not(false)]`, `$[not]`, `$[invalid]` -- all result in `Build.Repository.Clean` being `true`). Looks like expression isn't evaluated at all! – C.M. Feb 27 '20 at 17:27
  • @C.M. `$[not(false)]` This even is not a support format..... As part of an expression, you may access variables using one of two syntaxes: Index syntax: variables['MyVar'] Property dereference syntax: `variables.MyVar`. I am not sure how you are testing. But I also added some test and screenshot to make it more clearly. Details please see my update answer. – PatrickLu-MSFT Feb 28 '20 at 03:37
  • If `$[not(false)]` is not a valid expression, then [expressions documentation](https://learn.microsoft.com/en-us/azure/devops/pipelines/process/expressions?view=tfs-2018#boolean) is very misleading. – C.M. Feb 29 '20 at 03:42
  • I am sorry, I read your bolded paragraph ('You should ...') few times and I can't make any sense out of it. Which expression I should use for `Build.Repository.Clean` so that it becomes negation of another variable (`QuickBuild`) during build? I tried `$[not(eq(variables.QuickBuild, 'true'))] -- it doesn't work – C.M. Feb 29 '20 at 03:46
  • Hi @C.M. Thanks for getting back. I have go through your question and comments once again. Sorry for the misunderstanding. I was thought you are just trying to define `Build.Repository.Clean` of your build definition. But 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. Also updated answer, hope this make sense. – PatrickLu-MSFT Mar 02 '20 at 11:44
  • I am certainly able to change `Build.Repository.Clean` during queue time (see additional info in my post), I just can't use negation of another variable for some reason. Like I said before -- it seems that `expression` simply doesn't get evaluated at all. – C.M. Mar 02 '20 at 19:26
  • @C.M. `I am certainly able to change Build.Repository.Clean during queue time` Yes you are able to change the value of `Build.Repository.Clean`, but this will not change the real clean operation of your pipeline. And I have ran few tests, which proof my opinion. Did you disable the default **Get Source step**? If not, what you are using will not effect the clean operation during queue time. No matter what kind of value you set in `Build.Repository.Clean`. You build will finally run the clean operation which defined in Get Source Step. Your question is actually not related any expression. – PatrickLu-MSFT Mar 03 '20 at 03:37
  • `this will not change the real clean operation of your pipeline` -- strange... it certainly does for me. My build is working just fine with `Build.Repository.Clean=$(FullBuild)` (i.e. at queue time I change it to false and during build clean step is not executed. I am printing env variables during build -- I could see `BUILD_REPOSITORY_CLEAN` changing as I change `FullBuild` during queue time). I just wanted to change it to `Build.Repository.Clean=$[not(variables.QuickBuild)]` and couldn't find how to do it. Which TFS version you use? mine is `16.131.27701.1` – C.M. Mar 03 '20 at 22:01
  • ... and I see how `GetSources` step time changes dramatically (from 10 mins to 15 seconds). I also observe TFS executing different steps if flag is false – C.M. Mar 03 '20 at 22:03
  • @C.M. It's a little wired. I was using Azure DevOps Service. Do not have TFS 2018 around me. Not sure if there are difference between them. Have to verify it after backing to work environment next week. `I just wanted to change it to Build.Repository.Clean=$[not(variables.QuickBuild)] and couldn't find how to do it. ` Well, ignore if it changes clean during queue time. For what you are looking for, you could try this, `Build.Repository.Clean=$[not(eq(variables.QuickBuild,'True'))]`. In this case, if QuickBuild=True, `Build.Repository.Clean`=False, If QuickBuild=False, then `xx.Clean`=True – PatrickLu-MSFT Mar 04 '20 at 14:29
  • Tried it -- it didn't work. Feels like substitutions (i.e. `$()` get evaluated, but expressions don't. Wasn't sure if I can't read documentation or it is TFS bug/deficiency. – C.M. Mar 04 '20 at 14:33
  • @C.M. What if you define another variable and print them, not use `Build.Repository.Clean` such as `variabletest= $[not(eq(variables.QuickBuild,'True'))]`, QuickBuild=True or False . When you input QuickBuild=True, variabletest should be False; when you input QuickBuild=False, variabletest should be True. And use True/False , not true/false. – PatrickLu-MSFT Mar 04 '20 at 15:29
  • Case shouldn't matter according to docs. I ran test you've suggested -- ended up with `_TEST_VAR_1=$[not(eq(variables.FullBuild,'True'))]` printed out by `cmd /k set`. Like I said -- looks like expressions are simply not evaluated. `Build.Repository.Clean` seems to be special -- it gets converted to `bool` (but again -- without expression evaluation). – C.M. Mar 04 '20 at 18:38
  • I am thinking [this expansion logic](https://github.com/jessehouwing/azure-pipelines-variable-tasks/wiki/Expand-Variable) was implemented without expressions support... – C.M. Mar 04 '20 at 18:46
0

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.

C.M.
  • 3,071
  • 1
  • 14
  • 33