Final Release Tasks in TeamCity.

Not sure how to best achieve the following:

We have our builds and deployments all running from standard templates, which works really well, override a few version  numbers, and a source branch, and your new release is good to go.

We run multiple integration cycles until we get a pass from the test team, so build X is our end user release, we don't want to touch or changes those deliverables in any way, they are our signed off release images.   What we want to do some tasks in TeamCity like uploading SBOM for that build, copying deliverables to other locations, notifying users by email etc.

We have a plan to do this, however it's currently a bit basic, and requires some manual input of build numbers and works out what to do from that, and copies the deliverables from a network share and it's not linked to the deployment plans themselves.   It's quite clunky and potentially fragile  I have seen the build approval feature, but that doesn't really fit either.

Is there a better way?

Thanks

0
9 comments
Hi,

Thanks for the detailed explanation.

From what you've described, your goal is to perform a number of post-release tasks against a build that has already been signed off by the test team, while ensuring the original build artifacts remain unchanged.


A common approach in TeamCity is to keep these post-release activities in a separate build configuration rather than adding them to the original build or deployment. This allows the signed-off build to remain immutable while keeping all follow-up activities fully tracked within TeamCity.


The separate build configuration can use an artifact dependency to retrieve the artifacts from the approved build directly and then perform tasks such as:

•Uploading the SBOM

•Copying deliverables to other locations

•Sending notification emails


This avoids relying on network shares and manual build number entry, while maintaining a clear relationship between the original release build and the post-release actions.

To recommend the best approach, could you clarify one point?

How is a build currently designated as the final approved release?


For example:
•Is there a deployment configuration that is only run after the test team signs off?

•Is the approval handled outside TeamCity?

•Or is there another process that identifies which build becomes the official release?
0

Approval is handled outside of TeamCity, basically a manual meeting of all stakeholders, with an action to "release" the software once agreement is obtained from all stakeholders.

Deployment is aleady built and digitally signed at this point.  Once we are in our integration phase, every build is an integration candidate, and once one of these builds meets the quality threshold, that's it.  No more builds.

0

Thanks for the additional details.

Since the release decision is made outside TeamCity, I'd suggest creating a dedicated Post-Release Tasks build configuration with a snapshot dependency on your deployment configuration and an artifact dependency configured as "Build from the same build chain."

After the approval meeting, simply open the approved integration build in TeamCity, navigate to its build chain, and run the Post-Release Tasks build configuration. TeamCity will automatically resolve the artifact dependency to that exact approved build, so there is no need to manually enter a build number or copy artifacts from a network share.

Within the build, you can reference the original build number using:

%dep.<YourDeploymentConfigId>.build.number%

I'd also recommend pinning the approved build so it is clearly identified as the official release and protected from cleanup.

This approach allows the signed-off build and its artifacts to remain completely unchanged while keeping all post-release activities, such as uploading the SBOM, copying deliverables, and sending notifications, fully tracked within TeamCity.

0

the problem with %dep  is it doesn't really work very well with templates (our builds are templated, as are our deployments).  Each time we add something to the chain, we end up having to rewire so many things, the templates start to become useless, it's not just attaching a release to the correct dependency, it's fixing all the things that no longer work, as the dependency name differs each time.

We have done some work on some other plans to work around this, but totally avoid the %dep variables, by serializing and reserializing build variables (that originate in the build, flow into the deployment) using powershell, and this works much better than %dep

Some of this pain would go away, if there was a consistent, plan name independent way to reference upstream variables once you attach your dependency.

 

0

Sort of related, I don't see much documentation on the “Promote build” action.  Would this help me in any way?

0

Thanks for the additional context.

Your PowerShell approach of serializing and restoring the required values sounds like a reasonable workaround in this scenario.

Regarding Promote Build, I took another look and noticed that I can't find the current TeamCity UI exposes a separate Promote action. The closest equivalent appears to be re-running the downstream build with snapshot dependency build reuse enabled (for example, "Do not run new build if there is a suitable one"). In that case, TeamCity can reuse the existing upstream build instead of rebuilding it.

When TeamCity finds a suitable existing upstream build, it can reuse that build and run only the downstream post-release configuration.

This could therefore help you avoid rebuilding the approved and signed deliverables. There are also conditions that determine whether an existing build is considered suitable, including matching branch and source revisions, successful status depending on the dependency settings, and the absence of customized parameters.

0

Promote appears on the overflow menu for each build (deployment in our case), and appears to be able to trigger a downstream “build” from any upstream “build” (we removed all triggers, as we don't want release plan running every time).   We don't use Snapshot dependencies at all, only Artifact Dependencies, the wording for the Snapshot dependencies is really very confusing, and we don't seem to have any problems with Artifact Dependencies.

 

 

 

 

0

Thanks for the screenshots. They were very helpful.

I think Promote could be a good fit for your workflow. Since you're already using artifact dependencies, you can configure the dependency in your Post-Release Tasks build as "Build with specified build number."

When you click Promote on the approved deployment build, TeamCity will present the artifact dependency and pre-populate it with the build you're promoting from. That allows you to run the downstream post-release tasks against the approved build without manually looking up or entering the build number, while keeping the original build and its signed artifacts unchanged.

I also understand your point about snapshot dependencies. They are primarily intended to coordinate builds into a build chain that shares the same sources and revisions, whereas artifact dependencies are focused on consuming artifacts from another build. Given your workflow, where the build has already been completed, signed, and approved before the release activities begin, I can see why artifact dependencies together with Promote feel like a more fit.

 

0

Many thanks for your help. We have something that seems to work pretty well for us now.  In the interesting of knowledge sharing, if anyone is wondering how the serialization and deserialization using a file , by using a powershell task works (to avoid using %dep variables), its like this:

(don't forget to include the build-info.json in your Artifact paths) Concept came from here: Azure-DevOps-Variable-Tools - Repos

Plan A:   Serialize to JSON (Powershell task)

#write to file, so it can be used in the deployment with minimal template changes.
$data = @{
    BuildNumber = "%build.counter%"
    ProjectID = "%teamcity.project.id%"
    BuildConfigId = "%system.teamcity.buildType.id%"
    Branch = "%teamcity.build.branch%"
    Commit = "%build.vcs.number%"
}

$json = $data | ConvertTo-Json -Depth 3
$json | Out-File build-info.json -Encoding utf8

Plan B: Deserialize JSON build artefact back into build variables that can be used in a templated script. (Powershell task)

$info = Get-Content "build-info.json" -Raw | ConvertFrom-Json
$VersionNumber = $info.BuildNumber.Trim()
Write-Host "##teamcity[buildNumber '$VersionNumber']"
Write-Host "##teamcity[setParameter name='env.BuildVersion' value='$VersionNumber']"
Write-Host "##teamcity[setParameter name='env.Commit' value='$($info.Commit)']"
Write-Host "##teamcity[setParameter name='env.BuildConfigId' value='$($info.BuildConfigId)']"
Write-Host "##teamcity[setParameter name='env.Branch' value='$($info.Branch)']"
Write-Host "##teamcity[setParameter name='env.ProjectId' value='$($info.ProjectID)']"
0

Please sign in to leave a comment.