Output variable from a release

Hi,

I’d like to be able to obtain output variables from a release as mentioned here

However I’m not able to use the “Deploy Release Step” as I want to deploy to a different environment than the parent deployment. (I’m kicking off deploys to multiple environments from the single parent deployment)
Instead I’m using the community Chain step template
https://library.octopus.com/step-templates/18392835-d50e-4ce9-9065-8e15a3c30954/actiontemplate-chain-deployment
Which lets me pass which environment to deploy to.
I see that has support for a “Post-Deploy Script”, but seems limited on what it can read from the release.

Is is possible for the community chain step template to output variables the same way as the deploy release step does?
Not sure how would go about this?

Or to specify on the Deploy Release Step which environment should deploy to independent of the parent deployment?

Or to obtain these step output variables from a previous release, so I don’t have to trigger a release if it’s already been deployed, just to read the variables?


Or rather than trying to access these output values on a step from a previous release, how else can I obtain an outputted value from a release in another release?

Kind Regards

Ian

Hey Ian,

I’m currently working on a solution for you but won’t be able to finish it and get it to you til sometime tomorrow. I will keep you updated on my progress.

Thanks,
Jeremy

1 Like

Hey Ian,

I’ve come up with a potential solution for you, but you will have to tell me if this fits your use case.

What you will be doing is you will be modifying/creating a variable within a Project with one script, then referring to that variable with a separate script.

The first script to add/modify is this:

ModifyOrAddVariableToProject.ps1

I commented to explain the lines/blocks of code as well as I could. You will use this in a PowerShell script step in a deployment/runbook where you want to edit/create a variable. The only input you should have to do is two sections. You will need to input your server, API key, and project name. The second thing you will need to do is just add any number of Modify-Variable/Add-Variable commands with the desired parameters(scopes are not mandatory but I included them in case you wanted to use them). You can look at my examples towards the bottom of the script.

The second script is this:

GetVariableInProject.ps1

This script you will put in later deployments in a PowerShell script step to refer back to the variables you stored earlier. You will have to put in the same 3 pieces of info as the last script, the url, api key, and project name where the variable is stored that you want to find. In this script you will call Find-Variable with all 3 parameters as in the example (always use $VariableToStore). Then you can use that variable in whatever method you’d like within the script.

Please let me know if this is useful for the scenario you are trying to solve or if you need any explanation/help with the above. As always please read the code and test it so that you’re comfortable with it. It would be good practice to make a dummy project and run the script in various ways and see how the variables within that project get altered and make sure you’re happy with the results.

Thanks,
Jeremy

Thanks,

that’s interesting.
If you had scoped the variable in the first part, in the second part when you retrieve it does Find-Variable need some extra logic to find the correct scoped variable?
I think I would need scoping, so that the project setting the variable could be run in parallel to different locations without overwriting the same variable.

Another idea, could the release generate an Artifact with the output values wanted, say a json file.
And then programmatically retrieve the release Artifact from the release?
With the ability to either get the Artifact from the release that has just run, or if the same package version had already been deployed to that environment to get the Artifact from the release that was previously deployed to that environment?

Kind Regards

Ian

Hi Ian,

You are correct, if the variable is scoped, then extra logic will need to be added to search on and only return the desired scope. The current functionality will only look at if the name matches. So any further logic you will probably need to add yourself. If you have questions let me know.

Regarding artifacts, the process you are describing is absolutely possible, but it will require quite a bit of logic. I will paste you an example of artifact manipulation to get you started. I have also linked a couple examples of API calls to get you started. Please let me know if you have any other questions.

Powershell API Examples
GetListOfPackagesPushedToSpecificEnvironment
GetLastSuccessfulForProjectAndEnvironment

$CommandsToLookFor = $OctopusParameters["Databases.AutoApprove.CommandsToLookFor"]

$OctopusURL = $OctopusParameters["Databases.AutoApproval.BaseUrl"]
$APIKey = $OctopusParameters["Databases.AutoApproval.Api.Key"]
$FileExtension = $OctopusParameters["Databases.AutoApproval.FileExtension"]
$SpaceId = $OctopusParameters["Octopus.Space.Id"]
$DeploymentId = $OctopusParameters["Octopus.Deployment.Id"]

Write-Host "Commands to look for: $CommandsToLookFor"
Write-Host "Octopus Url: $OctopusUrl"
Write-Host "SpaceId: $SpaceId"
Write-Host "DeploymentId: $DeploymentId"
Write-Host "File Extension: $FileExtension"

$header = @{ "X-Octopus-ApiKey" = $APIKey }

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$artifactUrl = "$OctopusUrl/api/$SpaceId/artifacts?take=2147483647&regarding=$DeploymentId&order=asc"
Write-Host "Getting the artifacts from $artifactUrl"
$artifactResponse = Invoke-RestMethod $artifactUrl -Headers $header
$fileListToCheck = @()

foreach ($artifact in $artifactResponse.Items)
{
    $fileName = $artifact.Filename

    if ($fileName.EndsWith($FileExtension))
    {    	
        Write-Host "The artifact is a SQL Script, downloading"
        $artifactId = $artifact.Id
        $artifactContentUrl = "$OctopusUrl/api/$SpaceId/artifacts/$artifactId/content"
        Write-Host "Pulling the content from $artifactContentUrl"
        $fileContent += Invoke-RestMethod $artifactContentUrl -Headers $header
        Write-Host "Finished downloading the file $fileName"
        
        $sqlFileToCheck = @{
        	FileName = $fileName;
            Content = $fileContent;
        }
        
        $fileListToCheck += $sqlFileToCheck                
    }    
}

$ApprovalRequired = $false
$HasChangesToDeploy = $false

if ($fileListToCheck.Length -le 0)
{
	Write-Highlight "No files were found"
    
    Set-OctopusVariable -name "DBAApprovalRequired" -value $ApprovalRequired
    Set-OctopusVariable -name "HasDatabaseChangesToDeploy" -value $HasChangesToDeploy
    
    Exit 0
}

Write-Host "Looping through all commands"
$commandListToCheck = $CommandsToLookFor -split ","
foreach ($sqlFile in $fileListToCheck)
{
	$emptyFileFound = $sqlFile.Content -match "This script is empty because the Target and Source schemas are identical"
	if ($emptyFileFound -eq $false)
    {
    	$HasChangesToDeploy = $true        
    }
	else
	{
    	continue 
    }
    
	foreach ($command in $commandListToCheck)
    {
    	Write-Host "Checking $($sqlFile.FileName) for command $command"
    	$foundCommand = $sqlFile.Content -match "$command"
    
    	if ($foundCommand)
        {
        	Write-Highlight "$($sqlFile.FileName) has the command '$command'"
            $ApprovalRequired = $true
        }
    }
} 

if ($approvalRequired -eq $false)
{
	Write-Highlight "All scripts look good"
}
else
{
	Write-Highlight "One of the specific commands we look for has been found"
}

if ($HasChangesToDeploy -eq $false)
{
	Write-Highlight "All the script files were empty"
}
else
{
	Write-Highlight "The script files have changes"
}

Set-OctopusVariable -name "DBAApprovalRequired" -value $ApprovalRequired
Set-OctopusVariable -name "HasDatabaseChangesToDeploy" -value $HasChangesToDeploy
1 Like

Hi Ian,

I just wanted to let you know I was able to add that functionality to my Find-Variable script. I edited the post above to reflect the new code. It should now check scopes, and prioritize scoped variables. As always, please read the code and test in a test environment to make sure you’re getting desired results. Let me know if you have any questions.

Thanks,

1 Like