Octopus output Variables and ways to access them

Rajesh's Avatar

Rajesh

04 May, 2017 02:25 PM

I've octopus variables under "Library" -> "Variable Sets" variables with names
1. DatabaseExceptions
2. ReportsExceptions
3. App ParametersExceptions
4. ApplicationExceptions

And I've setup of my project "Deployment process" in octopus as steps
1. Database
2. Reports
3. App Parameters
4. Application
5. Send Email

The above variable are set with exceptions by using 'PowerShell' scripts that are invoked using predeploy.ps1 of the particular step on exceptions in scripts.
At the last step(Send Email) I was trying to send email with the information in exception variables by checking if particular variable has information in it.

I'm doing this in the send Email step body by checking the check box("Body as HTML")


<h2>Deployment Steps</h2>
<ol>
    #{each step in Octopus.Step}
        #{if step.Status.Code}
            <li>#{step | HtmlEscape} &mdash;
                #{if Step.Name == "Database"}
                    #{if Octopus.Action[Database].Output.DatabaseExceptions}
                        <pre>#{Octopus.Action[Database].Output.DatabaseExceptions}</pre>
                    #{/if}
                #{/if}
                #{if Step.Name == "Reports"}
                    #{if Octopus.Action[Reports].Output.ReportsExceptions}
                        <pre>#{Octopus.Action[Reports].Output.ReportsExceptions}</pre>
                    #{/if}
                #{/if}
                #{if Step.Name == "App Parameters"}
                    #{if Octopus.Action[App Parameters].Output.App ParametersExceptions}
                        <pre>#{Octopus.Action[App Parameters].Output.App ParametersExceptions}</pre>
                    #{/if}
                #{/if}
                #{if Step.Name == "Application"}
                    #{if Octopus.Action[Application].Output.ApplicationExceptions}
                        <pre>#{Octopus.Action[Application].Output.ApplicationExceptions}</pre>
                    #{/if}
                #{/if}
            </li>
        #{/if}
    #{/each}
</ol>

The Database and Reports scripts has errors and my output looks like below which is correct as expected
Deployment Steps
1. Database — Exception on processing DB scripts - info:...
2. Reports — Exception on processing Reports - info:...
3. App Parameters
3. Application
4. Send Email

this is how I'm setting the octopus variable of Reports under Reports package in Predeploy.ps1 and same applies to Database package and App Parameters package too


if($reportExceptions) {
        Set-OctopusVariable -name "ReportsException" -value $reportExceptions
    }
And my Questions Question 1:

Is it possible to do something as below as my step name and starting of my variable name are same


<h2>Deployment Steps</h2>
<ol>
    #{each step in Octopus.Step}
        #{if step.Status.Code}
            <li>#{step | HtmlEscape} &mdash;
                    #{if Octopus.Action[#{step.Name}].Output.#{step.Name}Exceptions}
                        <pre>#{Octopus.Action[#{step.Name}].Output.#{step.Name}Exceptions}</pre>
                    #{/if}
            </li>
        #{/if}
    #{/each}
</ol>

Question 2: with in my teamcity build output has
1. Database.buildversion.nupkg - which has scripts to deploy and predeploy.ps1
2. Reports.buildversion.nupkg - which has scripts reports and predeploy.ps1
3. App Parameters.buildversion.nupkg - which has App Parameters and predeploy.ps1
4. Application.buildversion.nupkg - all my application code
4. PatchNotes.txt
5. ReleaseNotes.txt

can I create an octopus variable under "Library" -> "Variable Sets" with name say 'exceptions' and use it to set 'exceptions' variable from 'predeploy.ps1' if any exception occurs during 'predeploy.ps1' execution.
Lets say in Database Package Predeploy.ps1


if($dbExceptions) {
        Set-OctopusVariable -name "exceptions" -value $dbExceptions
    }
in Reports Package Predeploy.ps1

if($reportsExceptions) {
        Set-OctopusVariable -name "exceptions" -value $reportsExceptions
    }
And back in Send Email Step can I use this 'exceptions' variable, to pull the exceptions occurred in individual deploy step

<h2>Deployment Steps</h2>
<ol>
    #{each step in Octopus.Step}
        #{if step.Status.Code}
            <li>#{step | HtmlEscape} &mdash;
                    #{if Octopus.Action[step.Name].Output.exceptions} <!-- Question: does octopus pulls 'exceptions' variable based on scope of the current Step -->
                        <pre>#{Octopus.Action[step.Name].Output.exceptions}</pre>
                    #{/if}
            </li>
        #{/if}
    #{/each}
</ol>
  1. 1 Posted by a.milorava on 09 May, 2017 08:41 AM

    a.milorava's Avatar

    For question 1 please find the answer in your stackoverflow:
    http://stackoverflow.com/a/43815240/1223982

  2. 2 Posted by Vanessa Love on 10 May, 2017 11:26 AM

    Vanessa Love's Avatar

    Hi Rajesh,

    Thanks for getting in touch! Sorry about the delay in getting back to you, I have been thinking over solutions for you and then testing it.
    My best solution for part one is to name your variables the same so you can iterate over them. Due to how output variables are saved per step, you can name them the same and get different values back.
    If they were named Exceptions it would remove a lot of the complexity. Then a simple iteration would print out the values per step ie:

    #{each action in Octopus.Action}
        <p><strong>#{action.Name}</strong> #{action.Output.Execeptions}</p>
    #{/each}
    

    Which in part answers your second question. You do not need to first define output variables in the project, but you can also declare a variable of the same name per step, again for easy iteration with different values, as it is an array based off step name.
    Set-OctopusVariable -name "execeptions" -value "myvalue" is how you would define the variable and using the above script in your email how you would iterate through without needing to know step names.

    Hope this helps.
    Vanessa

  3. 3 Posted by Rajesh on 10 May, 2017 01:16 PM

    Rajesh's Avatar

    Hi Vanessa,

    The solution is really helpful, this reduced the complexity in building my email notification message. I really appreciate the answer. And is there any way I can display this exceptions next to the step name that they occurred in while displaying the step name and it's status in email notification, that is something that looks like below message.


                                 Deployment Steps
    

    1. Database — Failed
      Exception on processing DB scripts - info:...
    2. Reports — Failed
      Exception on processing Reports - info:...
    3. App Parameters - Succeed
    4. Application - Succeed
    5. Send Email - Running

    Note: the Failed message display in red, succeed in green and remaining status are default black.
    This is what I'm trying to construct, which is not mandatory structure but it looks user friendly and easy to understand for the one who is receiving emails.

  4. 4 Posted by Vanessa Love on 10 May, 2017 11:25 PM

    Vanessa Love's Avatar

    Hi Rajesh,

    I absolutely understand the want to make it easier to read but as the two arrays of variables are different and email structure doesn't allow for direct substitution you will have to have two different lists unfortunately.

    Vanessa

  5. 5 Posted by a.milorava on 11 May, 2017 08:08 AM

    a.milorava's Avatar

    Rajesh, it seems to me the below would do what you are after (apart specific styling, like colouring).

    #{each action in Octopus.Action}
        <strong>#{action.Name}</strong>
        #{if action.Output.Exceptions}
            <p> - #{action.Output.Exceptions}</p>
        #{/if}
        #{unless action.Output.Exceptions}
            - Succeeded
        #{/unless}
    #{/each}
    
  6. 6 Posted by rajesh on 16 May, 2017 12:28 PM

    rajesh's Avatar

    Hi Vanessa, thanks for clarifying my question. I'll see if I can achieve the result by using two different list.

    Hi a.mailorava, thanks for the reply. It seems I can use the example on your reply to achieve my required result, I'll try it and update post with the answer if I come up with one.

    Thanks guys.

  7. 7 Posted by rajesh on 18 May, 2017 01:13 PM

    rajesh's Avatar

    Hi everyone, finally I came up with the below script that helps me to get my desired output.

    I believe in the script using 'step' loop #{each step in Octopus.Step} inside the 'action' loop #{each action in Octopus.Action} is not a good idea as for each action the step loop iterates multiple times depending on the number of steps in build.

    - Let me know, if this is the good approach.
    - Does it have any drawbacks.
    - Any improvement can i make to this script.

    Script

    <h2>Deployment Steps</h2>
    <ol>
    #{each action in Octopus.Action}
        <li><strong>#{action.Name}</strong> &mdash;
        #{if action.Output.Exceptions}
            <strong><font color="red">Failed</font></strong>  </br>
            <font face="courier" size="-1" color="red">#{action.Output.Exceptions} </font>
        #{/if}
        #{unless action.Output.Exceptions}
            #{each step in Octopus.Step}
                #{if step.Name == action.Name}
                    #{if step.Status.Code == "Pending"}
                        <strong>#{step.Status.Code}</strong> </br>
                    #{/if}
                    #{if step.Status.Code == "Skipped"}
                        <strong><font color="orange">#{step.Status.Code}</font></strong></br>
                    #{/if}
                    #{if step.Status.Code == "Abandoned"}
                        <strong><font color="orange">#{step.Status.Code}</font></strong></br>
                    #{/if}
                    #{if step.Status.Code == "canceled"}
                        <strong><font color="orange">#{step.Status.Code}</font></strong></br>
                    #{/if}
                    #{if step.Status.Code == "Running"}
                        <strong>#{step.Status.Code}</strong></br>
                    #{/if}
                    #{if step.Status.Code == "Succeeded"}
                        <strong><font color="green">#{step.Status.Code}</font></strong></br>
                    #{/if}
                    #{if step.Status.Code == "Failed"}
                        <strong><font color="red">#{step.Status.Code}</font></strong></br>
                    #{/if}
                #{/if}
            #{/each}
    #{/unless} #{if action.Status.Error} <font face="courier" size="-1" color="red">#{action.Status.Error | HtmlEscape}</font> <font face="courier" size="-1" color="red">#{action.Status.ErrorDetail | HtmlEscape}</font> #{/if} </li> #{/each} </ol>

    Output

    Deployment Steps
    1.   Database — Failed
          Exception on processing DB scripts - info:...
    2.   Reports — Failed
          Exception on processing Reports - info:...
    3.   App Parameters — Succeeded
    3.   Application — Succeeded
    4.   Send Email — Running
    5.   Post Deploy Task — Pending
    
    Note: The Step status Code(Succeeded, Failed, Running, etc.,) are displayed based on the color code assigned. For example the "Failed" status code is displayed in red color and the exception message is also displayed in red color as defined in script.

    Thanks, I really appreciate you time and help.

  8. Paul Stovell closed this discussion on 25 Aug, 2017 06:37 PM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac