How to retrieve package file from a custom build step without extracting

This is somewhat similar to http://help.octopusdeploy.com/discussions/questions/10040-how-to-get-the-package-in-a-server-side-script

What I want to achieve is to be able use msdeploy.exe from a C# script to directly sync a zip package (in this case, an web deploy package created by msbuild). My reasons for wanting to use msdeploy directly are mostly around flexibility and the ability to specify the package parameters that are passed into the command line.

I definitely want to leverage Octopus’ ability to trigger deployments based on new packages being published (currently using the built-in repo) so it appears that I need at least one step which consumes a feed. Unfortunately I cannot see any way to do this without adding one of the built-in Octopus steps, such as Deploy a Package. The Deploy a Package step provides the desired “Package Feed” and “Package ID” parameters which I want to use, but (understandably) it wants to deploy said package to a Deployment Target.

Unless I’m barking up the wrong tree here, I don’t actually want or need deployment targets for this proposed process so I’m currently adding a dummy target and a dummy environment which I choose not to deploy to, in addition to my actual environments (e.g. Test, UAT, etc). That way when I choose to deploy to my Test environment (let’s say this is Azure) it actually skips the Deploy a Package step but still gives me access to the Octopus Parameters indicating the correct package ID, e.g. my C# script works:

var packageId = Octopus.Parameters["Octopus.Action[Package].Package.PackageId"];
var packageVersion = Octopus.Parameters["Octopus.Action[Package].Package.PackageVersion"];

var packageName = packageId + "." + packageVersion;
var packagePath = $"C:\\Octopus\\Packages\\{packageId}\\{packageName}.zip";

const string msdeploy = "C:\\Program Files\\IIS\\Microsoft Web Deploy V3\\msdeploy";

var cmdArgs = $@"-verb:sync 
-source:package='{packagePath}' 
-dest:auto,ComputerName='https://{azureSiteName}.scm.azurewebsites.net/msdeploy.axd?site={azureSiteName}',UserName='${azureSiteName}',Password='{azurePassword}',AuthType='Basic'  
-enableRule:AppOffline  
-setParam:name='IIS Web Application Name',value='{azureSiteName}'";

// ...
// append other web deploy parameters
// ...

cmdArgs = cmdArgs.Replace(Environment.NewLine, " ");

var process = new Process();
var startInfo = new ProcessStartInfo(msdeploy, cmdArgs)
//...

However, it’s still not right as there is the potential for someone to attempt to deploy to my “dummy” environment.

I realise that Octopus started out with fairly specific use case of extracting and deploying nuget packages and was later extended to support Azure deployments but I’m hoping that there might be some room for movement here as I can see a number of other similar scenarios where I want to leverage Octopus’ built-in repository, wonderful UI and excellent custom step functionality.

Hi Lance,

Thanks for getting in touch!

We’ve actually got some work going on right now to allow a package to be “deployed” without it being unpacked. I would expect it to be available within the month.

At the moment, your script relies on the internal structure of the built-in repository, which is not ideal, but for now, is probably your best bet.

Once the new feature is released, you’ll be able to configure a step to push the package to a Tentacle, and then on the Tentacle, upload it with msdeploy.

I would’ve liked to give you a link to the issue where this work is being done, but nearly all of the team is out at a Christmas lunch and are uncontactable at the moment. I think this issue is probably the closest, and if its not the main one, it should be closed when the work is complete. You can track that issue for progress on the work.

Hope that helps!

Regards,
Matt

Hi Matt,

No worries there - if it’s only a month away then I’m totally happy to wait until then. I’ve started tracking that issue. I’m looking forward to the new features!

Merry Christmas to yourself and the rest of the team.

Hi Lance,

Just a quick note to let you know this new step type has been released in version 3.7.12.

Happy deployments!

Regards,
Matt

Hi Matt,

Thanks for your teams work on this. I’ve given it a bit of an evaluation and it seems to resolve my issue. It’s not quite as simple as what I had imagined but it’s much simpler than before!

My original hope was to be able to run a script directly on the Octopus server but the step only works with deployment targets, so I have installed a tentacle directly on the Octopus server. From an abstract point of view I’m treating this tentacle as a simple scripting agent rather an actual deployment target (e.g. not a web server).

For future reference, I needed to rename the deployed package on the tentacle in order for msdeploy.exe to work with the package (as the package is deployed to the tentacle with a non-zip extension), but this is pretty trivial.

E.g. using C# script:

var originalPackagePath = Octopus.Parameters["Octopus.Action[Retrieve Package].Output.Package.FilePath"];

// Add zip extension (msdeploy is strict)
var packagePath = originalPackagePath + ".zip";

File.Move(originalPackagePath, packagePath);

Good work team!

Hi Lance,
I have provided an update to the package transfer step in response to your comment. The original package name should then be retained when transferred on the remote server. This update will go out in the next release of 3.7.15 in the next few days.
Let me know if you run into any further issues,
Cheers,
Rob

That’s fantastic - thanks Rob.