Repository Cleanup with Variable Package Names

Based on the warning in Octopus, as well as this:

I have a question, especially since those are somewhat older questions.

I have setup a nuget package deployment as a step template, and I use a parameter for he package name. Then, when adding it to a project, I hard-code the package name in that parameter, as this allows me to use a standard deployment process with different packages. I assume that this still counts as a variable package name, though if not, that would be wonderful.

Based on the discussion in those threads, I wanted to see what the solution was to cleanup. Do we cleanup based on what is currently used by any existing releases? We have Automatic Deployment to our DEV environment, so our releases always use the package. If cleanup is based on the deployment log of existing releases ,we should be okay. I just wanted to confirm, and if need be, move away from a step template.

That being said, any chance in the future of having nuget package step templates accept parameterized packages that are considered “hardcoded”?

Hi Chris,

Thanks for getting in touch!

Unfortunately, because of the way both the retention policies and the step templates are implemented, it’s really hard for us to do this. For what it’s worth, I absolutely understand why you’d want retention policies that work with packages defined by variables - particularly for library step templates. We’ll talk about it more internally to see if there’s a nicer way to do it. I have some ideas, but they’d involve a lot of rework.

To give you a bit more information, package retention works based on the package and version defined in the Release. Variables are only fully resolved at deployment time, so it’s much harder to find out which packages are being used with which releases if they’re defined as variables. In terms of step templates based on package steps, the only parameters that get exposed are the ones you define. So to pass a variable through to the package name field, it needs to be exposed as a parameter, and the above retention issue comes up.

Probably the best way to get around this at the moment is to create your own retention process. This could be an external scheduled task, or even a step in a deployment itself. If your release versions match the package versions for your project, that would make it much easier. You could query the previous X releases and remove any packages that didn’t match those version numbers.

In terms of moving away from step templates, that might be an option. Especially if you’re able to separate any specific scripts from the package being deployed. If you can use a lightweight package step and have library step templates to do the surrounding work, it would be easier to manage.

Sorry it’s not better news!


Thanks for the reply.

One follow-up: If I click ‘Create Release’ it recognizes the package name (since the parameter is hardcoded) and version numbers. Given that, and that the repository cleanup is done based on the Release, I feel like the packages would not be cleaned up. That being said, it’s not something I want to test with our Production packages.

Is it possible to confirm if that would fix the issue, since querying the release returns the correct package?

Hi Chris,

Unfortunately it’s not that simple - the Release only stores the version number of the package to be used in a step, and the package name and feed are saved with the process snapshot. So the package name in your case is ultimately a variable under the covers. It is a bit confusing so I’ll try to explain.

When you create a Release, Octopus will ask you for a package version for your package step. To help you choose a version number that will actually exist, it resolves the variable that’s being used for the package name (hidden behind a parameter in your case). But what’s actually stored in the Release is just the step name and the version number for that release.

It’s easier to see what’s going on if you use the API.

If you go to /api/releases/[ReleaseId] (e.g. api/releases/Releases-2), you can see a JSON representation of the object we store. To find the Release Id, you might need to look at the API calls in your browser dev tools. You’ll see in the SelectedPackages property the only details we’re storing are the name of the step that needs a package, and the version to use.

In this JSON, look for the Links property. It will have a link to the ProjectDeploymentProcessSnapshot. If you hit that endpoint, you can see the process as it will actually get run. If you find the correct Step and Action, you’ll see in Properties that the Octopus.Action.Package.NuGetPackageId will have the parameter name, not the hardcoded value you’ve given it. You should also be able to see the variable that’s behind the parameter and the value you provided directly in the step. Incidentally, the ProjectVariableSnapshot property of the Release will give you the variable values that may override this variable during deployments.

The short version is the package name for a step template will be resolved each time it’s used. That means even though you chose the version number from PackageA when you created the Release, you could have scoped variables that would change this value later on deployment to PackageB. This is handy for people who want to deploy different packages to different environments.

How does this apply to retention? If a project has a step that defines a package Id with a variable (as will always be the case if you’re using a step template), we try to leave all of those packages alone. The reason is described fairly well in those threads you linked to, but it’s due to the above - that package name may change between environments, so we can’t easily evaluate whether the package being used in Test corresponds to the one that will be deployed in Production.

I understand in your case that you’re hard-coding that value and not changing it later on with variables, so it’s not ideal. However, the way this process currently works makes it very difficult to reason about the packages we need to keep.

I hope that helped explain! Let me know if anything’s not clear.