huserben / TfsExtensions

Extensions for TFS 2015+ such as custom Widgets (require TFS 2017) and Build Tasks
MIT License
45 stars 22 forks source link

Waiting for triggered builds from different team-projects results in ##[error]Cannot read property 'definition' of null #190

Closed MichaelFreitag78 closed 3 years ago

MichaelFreitag78 commented 3 years ago

Hi,

I really like the plugin but at the moment I am struggling to make it run for our needs.

Thats our setup: We start different builds from various teamprojects via the triggered build plugin and put all of them in the build queue. After that I would like to wait for each of those builds.

Unfortunately the wait-for-build-task tries to wait for all triggered builds on the same teamproject. This results in an error "##[error]Cannot read property 'definition' of null"

grafik

Is there any possiblity to wait only for certain builds? Or wait for all of them within one wait-for-build-task, but in a way that the different teamprojects are considered right?

If not it would be great to have the possiblity to define a custom name for the triggered builds environment variable for the trigger-build-task and the wait-for-build-task. I would then have the chance to define different names for the various builds and wait for each.

Regards, Michael

huserben commented 3 years ago

Hi @BewotecDaVinci

indeed the task(s) were not designed to trigger multiple builds in different projects. It simply didn't occur to me as a use case till now.

Is there any possiblity to wait only for certain builds

So in theory you could just try to await build(s) in one specific team project. For this you would need to change the trigger tasks and only store the build id's of the builds in that team project that you want to await. That would probably be the cheapest solution if this could be done from your side.

Or wait for all of them within one wait-for-build-task, but in a way that the different teamprojects are considered right

I don't think all of them can be awaited, unless some bigger change is made in the task.

If not it would be great to have the possiblity to define a custom name for the triggered builds environment variable for the trigger-build-task and the wait-for-build-task

I think this would be an easier way, but it requires adjustment to both the wait and the trigger task. Currently I do not have planned to make some changes so I could also not tell you when it would be available.

However I think there might be a way you could await all of the builds with multiple wait tasks that would not require any change in the task.

Let's assume we want to achieve the following flow:

  1. Trigger Build 1 (Project A)
  2. Trigger Build 2 (Project B)
  3. Trigger Build 3 (Project C)
  4. Wait for all builds to finish

With a powershell (or bash) command we could store a temporary variable that overwrite the TriggeredBuildIds after we waited for the previous builds:

  1. Trigger Build 1 (Project A)
  2. Store Ids as "BuildIdsProjectA"
  3. Trigger Build 2 (Project B)
  4. Store Ids as "BuildIdsProjectB"
  5. Trigger Build 3 (Project C)
  6. Wait for Build 3 to finish
  7. Restore "BuildIdsProjectB" as BuildIds
  8. Wait for Build 2 to finish
  9. Restore "BuildIdsProjectA" as BuildIds
  10. Wait for Build 1 to finish

The powershell script to "Store" should look something like this

- pwsh: |    
    # Store IDs for project A
    Write-Host "##vso[task.setvariable variable=BuildIdsProjectA;isoutput=true]$($env:TriggeredBuildIds)"

    # Clear triggered build ids
    Write-Host "##vso[task.setvariable variable=TriggeredBuildIds;isoutput=true]"
  name: StoreIds

And to restore them:

- pwsh: |    
    # Restore IDs for project A
    Write-Host "##vso[task.setvariable variableTriggeredBuildIds=;isoutput=true]$($env:BuildIdsProjectA)"
  name: RestoreId

That way the Wait task will only work against the id's we've just restored.

The reading and writing powershell part is based on the docs from microsoft.

Caveat: I have not (yet) tried this myself, so I'm not 100% sure this works and there might be some typos or so in the code.

MichaelFreitag78 commented 3 years ago

Hi,

thanks for the quick response. I gave the powershell solution a try and after some modifications it uses to work now.

Cache triggered build id

  - task: PowerShell@2
    displayName: 'Caching triggered build id for ServiceA'
    inputs:
        targetType: 'inline'
        script: |
          Write-Host "Caching triggered build id"
          Write-Host "##vso[task.setvariable variable=ServiceABuildId;]$(TriggeredBuildIds)"
          Write-Host "Clearing triggered build id"
          Write-Host "##vso[task.setvariable variable=TriggeredBuildIds;]"

Restore triggered build id

- task: PowerShell@2
    displayName: 'Restoring triggered build id for ServiceA'
    inputs:
        targetType: 'inline'
        script: |
          Write-Host "Restoring triggered build id"
          Write-Host "##vso[task.setvariable variable=TriggeredBuildIds;]$($env:ServiceABuildId)"

Thanks for your help

huserben commented 3 years ago

Ok cool to hear that it works. Sorry for not being able to provide this built-in, but as this is working for you I would suggest that we leave it at that for now.

In case there are more requests regarding this in the future I'll consider adding it "natively" in the task.

Thanks for reaching out and providing the code that worked for you, that way others can also profit from your experience if they face the same or a similar problem.

Feel free to create a new issue in case you come across another problem or have a request for a feature.