We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Continuous Delivery with Octopus Deploy

00:00

Formal Metadata

Title
Continuous Delivery with Octopus Deploy
Title of Series
Number of Parts
170
Author
License
CC Attribution - NonCommercial - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Identifiers
Publisher
Release Date
Language

Content Metadata

Subject Area
Genre
Abstract
One of the main tenets of Agile development is to deliver business value to the production environment early and often. That's easy enough if you are delivering one small web app, but what if your application is composed of several web apps across multiple tiers with a large database and maybe even a few Windows services and scheduled tasks? Now you need a deployment system that is built to scale and allows you to automate all of these tasks to achieve consistency in your deployments. In this session I will show you how Octopus Deploy can make these deployments as simple as the click of button. I will also highlight new features in the 2.0 release such as Guided Failure and audit trails.
Continuous functionSoftwareAnalytic continuationTwitterBlogScheduling (computing)Process (computing)InformationSoftwareMultiplication signPhysical systemStrategy gameSoftware developerVelocityMereologyBitBranch (computer science)Bit rateProduct (business)Software bugOffice suiteRight angleLattice (order)Cycle (graph theory)Data miningCartesian coordinate systemGoodness of fitMatching (graph theory)Basis <Mathematik>Limit (category theory)Squeeze theoremVideo gameShared memoryMathematicsTrailComputer animation
Kolmogorov complexityDatabaseTask (computing)Point (geometry)Web serviceLibrary catalogDecision tree learningConsistencyStapeldateiAutomationProcess (computing)LoginComplex (psychology)Scripting languageTask (computing)Server (computing)Point (geometry)Level (video gaming)StapeldateiPhysical systemCrash (computing)Multiplication signProduct (business)Service (economics)Cartesian coordinate systemMereologyGoodness of fitSet (mathematics)Process (computing)Perturbation theoryWeb 2.0BuildingConfiguration spaceBitRight angleVisualization (computer graphics)SoftwareSoftware developerLine (geometry)State of matterWindowComputer fileProjective planeConsistencyMessage passingMobile appLogicPasswordQueue (abstract data type)Revision controlBookmark (World Wide Web)Web serviceSlide ruleArmWebsiteShared memoryIntegrated development environmentData loggerBinary codeWeb applicationAuthorizationOctahedronVirtual machineScheduling (computing)LoginComputer animation
Web serviceWebsiteVariable (mathematics)Process (computing)Complex (psychology)Configuration spaceIntegrated development environmentLibrary (computing)Task (computing)PlastikkarteTablet computerWeb pageField (computer science)Commutative propertyDemo (music)Software developerGoodness of fitGastropod shellProduct (business)Level (video gaming)AreaWeb serviceTouchscreenInformationSoftware testingIntegrated development environmentRevision controlWebsiteBus (computing)Server (computing)WindowVisualization (computer graphics)Bookmark (World Wide Web)Right angleOperator (mathematics)BitProcess (computing)Point (geometry)Task (computing)Coma BerenicesScheduling (computing)Blind spot (vehicle)Computer animation
.NET FrameworkError messageCompilation albumWeb pageAuthorizationShared memoryConfiguration spaceData compressionDefault (computer science)Data managementText editorComplex (psychology)DisintegrationView (database)Local GroupDigital filterLink (knot theory)Convex hullPhysical systemWeb serviceProcess (computing)Server (computing)Associative propertyEvent horizonComa BerenicesComputerWeb browserCryptographyInclusion mapWebsitePoint cloudFile Transfer ProtocolScripting languageBuildingQueue (abstract data type)Online helpPermianInformation managementPhysical systemWebsiteProduct (business)Real numberVirtual machineComplex (psychology)Cartesian coordinate systemWindowMultiplication signFile formatRight angleIntegrated development environmentWeb 2.0Service (economics)Scripting languageComputer fileCASE <Informatik>Demo (music)Goodness of fitProjective planeINTEGRALHookingComputer configurationMoving average.NET FrameworkCloud computingRepository (publishing)BuildingCross-platformMetadataWeb serviceRevision controlData recoverySet (mathematics)Bus (computing)TelecommunicationMobile appIdentity managementDomain nameLevel (video gaming)Power (physics)Gastropod shellSoftware testingSoftware developerMetropolitan area networkInformationPoint (geometry)Server (computing)CodeBoss CorporationShared memorySoftware bugPhysical lawSemantics (computer science)DatabaseComputer animation
Convex hullQueue (abstract data type)BuildingUniform resource locatorMetreComplex (psychology)Revision controlConfiguration spaceVisual systemView (database)Online helpFeedbackCurvatureControl flowEmulationInclusion mapEuler anglesSurjective functionComputer wormPhysical systemComputer programFluid staticsOvalTask (computing)HookingSoftware testingArchitectureBefehlsprozessorComputer fileDuality (mathematics)SpacetimeDefault (computer science)Cellular automatonParameter (computer programming)Gamma functionMaxima and minimaSource codeHausdorff spaceComputer fileRevision controlCuboidCartesian coordinate systemPlug-in (computing)Visualization (computer graphics)Multiplication signMobile appBinary codeRepository (publishing)File formatSet (mathematics)Server (computing)Projective planeWindowType theoryHookingMathematical optimizationWebsiteImplementation.NET FrameworkOrder (biology)Complex (psychology)NumberBuildingShared memoryVariable (mathematics)Virtual machineDirectory serviceContinuous integrationSoftware developerPower (physics)Right angleMultiplicationConfiguration space2 (number)ArmLibrary (computing)Service (economics)Point (geometry)INTEGRALComputer clusterCondition numberData storage deviceDot productLocal ringFile systemOctahedronComputer animation
Condition numberVariable (mathematics)Configuration spaceIntegrated development environmentLibrary (computing)Task (computing)Process (computing)BuildingComplex (psychology)View (database)EmailSineParameter (computer programming)Revision controlFeedbackOnline helpQueue (abstract data type)Core dumpDefault (computer science)Finite element methodIntegrated development environmentKey (cryptography)NumberAdditionMathematicsGraphical user interfaceRevision controlMultiplication signExistential quantificationWhiteboardServer (computing)Projective planeVariable (mathematics)Point (geometry)Process (computing)Coefficient of determinationComputer animation
Web pageTablet computerComplex (psychology)BuildingConfiguration spaceCondition numberRevision controlComputer iconNormed vector spaceSlide ruleComputer-generated imageryData typeMeta elementClique-widthContent (media)Link (knot theory)Digital photographyCalculusHyperlinkComputer fontMethodenbankSocial classPhysical systemCore dumpExtension (kinesiology)Server (computing)Scripting languageView (database)Shared memoryPrice indexField (computer science)WebsiteWeb serviceLibrary (computing)Integrated development environmentTask (computing)Inclusion mapSet (mathematics)Variable (mathematics)Process (computing)Queue (abstract data type)Online helpPermianInformation managementElectric currentMathematicsStatisticsSimultaneous localization and mappingThread (computing)Service (economics)Parameter (computer programming)Physical systemVariable (mathematics)Integrated development environmentArithmetic progressionPoint (geometry)Process (computing)Virtual machineRevision controlConfiguration spaceWebsiteMathematicsGoodness of fitWeb 2.0View (database)System callProjective planeComplex (psychology)Set (mathematics)Product (business)Multiplication signSurfaceBuilding1 (number)2 (number)Forcing (mathematics)Disk read-and-write headRight angleCartesian coordinate systemComputer fileCommitment schemeDifferent (Kate Ryan album)Visualization (computer graphics)Template (C++)Computer animation
Sample (statistics)Complex (psychology)Web pageTable (information)Common Intermediate LanguageDigital photographyHyperlinkLink (knot theory)Slide ruleComputer fontComputer iconExecution unitLibrary (computing)Task (computing)Integrated development environmentVariable (mathematics)Process (computing)Computer configurationSubsetLatent heatWeb serviceSoftware developerMultiplication signMathematicsRevision controlVariable (mathematics)Level (video gaming)NumberComputer animation
Variable (mathematics)String (computer science)Gastropod shellPower (physics)Mountain passScripting languageSinguläres IntegralIntegrated development environmentTask (computing)Configuration spaceLibrary (computing)Complex (psychology)Web serviceOnline helpBuildingQueue (abstract data type)Data miningInformation managementWeb pageGoogle ChromeConvex hullComponent-based software engineeringServer (computing)Configuration spaceWeb 2.0String (computer science)Variable (mathematics)Software testingTransformation (genetics)INTEGRALWeb serviceScheduling (computing)Multiplication signPasswordComputer fileBuildingSet (mathematics)MathematicsMobile appIntegrated development environmentDatabaseScripting languageConnected spaceAdditionCodeLevel (video gaming)Endliche ModelltheorieSoftware developerProduct (business)Sensitivity analysisSheaf (mathematics)Group actionoutputOperator (mathematics)Dependent and independent variablesServer (computing)Default (computer science)Revision controlService PackPower (physics)Gastropod shellTask (computing)Demo (music)Process (computing)Right angleCAN busReliefTrailExecution unitComputer animation
Task (computing)Complex (psychology)Library (computing)Configuration spaceIntegrated development environmentGamma functionElectric currentWeb serviceServer (computing)Sanitary sewerError messageThermal expansionInformationBookmark (World Wide Web)View (database)Lipschitz-StetigkeitVideoconferencingInclusion mapMethodenbankScripting languageProcess (computing)WebsiteEmailVirtual machinePower (physics)Gastropod shellWindows AzurePoint cloudFile Transfer ProtocolComputer fileCommunications protocolHeat transferUniform resource locatorSoftware testingCodeFrequencyDatabaseGoodness of fitPhysical systemScripting languageRollback (data management)Revision controlIntegrated development environmentSoftware bugMultiplication signProjective planeVisualization (computer graphics)Server (computing)Moving averageProcess (computing)Virtual machineWeb serviceEmailWindow2 (number)Cartesian coordinate systemAnalytic continuationVariable (mathematics)Directory servicePoint (geometry)Repository (publishing)TrailConnected spaceTable (information)File Transfer ProtocolType theoryProduct (business)Order (biology)String (computer science)LoginHuman migrationSoftwareData managementRandomizationCommitment schemeLastteilungSequelSoftware developerTask (computing)BlogMathematicsWeb pageRoundness (object)Level (video gaming)WebsiteLogic gatePower (physics)Gastropod shellSystem callReading (process)Single-precision floating-point formatRight angleMobile appComputer animation
Variable (mathematics)Process (computing)Integrated development environmentTask (computing)Library (computing)Configuration spaceWeb serviceRevision controlWebsiteComplex (psychology)Level (video gaming)Software developerEmailMessage passingLocal ringProduct (business)Server (computing)Computer animation
TimestampLink (knot theory)Complex (psychology)Task (computing)Library (computing)Configuration spaceIntegrated development environmentWeb serviceLink (knot theory)Integrated development environmentOcean currentEmailRevision controlHTTP cookieWindowGroup actionSign (mathematics)Point (geometry)Product (business)OctahedronCognitionComputer animation
PasswordTask (computing)Complex (psychology)Integrated development environmentLibrary (computing)Interrupt <Informatik>Web serviceWebsiteBackupPublic key certificateServer (computing)Cross-correlationConfiguration spaceMethodenbankScripting languageSet (mathematics)Uniform resource locatorSoftware testingDatabaseSubject indexingTemplate (C++)Repository (publishing)Client (computing)Revision controlEquivalence relationFunction (mathematics)Gastropod shellFrequencyCodeInstallable File SystemDirectory serviceRegular expressionHost Identity ProtocolElectronic mailing listQueue (abstract data type)Database transactionComputer networkComplete metric spaceStructural loadInstallation artExecution unitVariable (mathematics)Computer fileSubstitute goodCoprocessorLocal ringProcess (computing)Parameter (computer programming)EmailData managementScripting languageCoprocessorProduct (business)AuthorizationPower (physics)Level (video gaming)MethodenbankLibrary (computing)Execution unitDependent and independent variablesFunctional (mathematics)Gastropod shellFigurate numberPoint (geometry)Parameter (computer programming)Configuration spaceRow (database)LoginVariable (mathematics)Computer clusterEndliche ModelltheorieRight angleSet (mathematics)Inclusion mapProjective planeComputer fileStructural loadQuicksortShared memoryData managementStatement (computer science)Physical systemDatabaseChemical equationProcess (computing)Template (C++)Different (Kate Ryan album)SequelMessage passingLink (knot theory)Data storage deviceMathematicsView (database)SpacetimeHuman migrationComplete metric spaceCodeDirectory serviceScheduling (computing)Multiplication signConfidence intervalInteractive televisionBuildingVotingSystem administratorGoodness of fitLocal ringTrail2 (number)Keyboard shortcutLastteilungInstance (computer science)Computer animation
TwitterBlogProduct (business).NET FrameworkReal numberMobile appScripting languageGastropod shellWindowWebsiteServer (computing)Multiplication signMoment (mathematics)Service-oriented architectureRight angleTime zoneCodeVideo gamePoint (geometry)FreewareRow (database)Computer animation
Transcript: English(auto-generated)
All right, good morning. How's everybody doing after the attendee party last night? Well, some of you made it here, and that's good. So my name is Jeff French, and I've been delivering software for, I don't know,
about five to eight years to production systems. I've been delivering it well for about two years, and a lot of that was, you know, a learning experience, and that's what I want to kind of share with you today about my search for what the right delivery process looks like and how I found it in a couple of tools
called Octopus Deploy and TeamCity. So first, a quick show of hands. How many people are practicing agile at your shop? Yeah? It's kind of bright up here. Most people, okay.
And how many of you are practicing continuous delivery currently? Okay, about half. Good, good. Oh, okay, here's my vanity plate,
my shameless self-promotion. If you want to follow me on Twitter, check out my blog. I'll have this information at the end too. So today, here's kind of what we're going to go through. We're going to start by talking about what continuous delivery is and, you know, why it's important,
some of the wrong ways that I have tried to do it over the years, and how I kind of landed on the right way to do it. So this is my definition of continuous delivery, okay? Delivering working, tested software to your customers as frequently as is practical.
Now, I say practical rather than possible because it may be possible for you to deliver working, tested software every 10 minutes if you work someplace like GitHub and they do that. It may not be practical because your end users may not actually tolerate that pace.
This was something that I found in my own experience. Now, here's a couple of quotes from the principles behind the Agile Manifesto. All you people who are practicing agile, have you read the Agile Manifesto? No? It was written back in 2001
when the kind of concepts of agile were first being discussed, and some of the principles they had there were, as you see on the screen, satisfy the customer through early and continuous delivery of valuable software, deliver working software frequently from a couple of weeks to a couple of months, all right?
When the kind of founding fathers, if you will, of agile were kind of coming up with these concepts that we are all practicing today, they understood inherently that continuous delivery was going to be an integral part of practicing a good agile system because it doesn't do you any good to develop in quick, short iterations
if you're not actually taking that business value you've created and delivering it to your users. It's not business value until you deliver it, right? So, I told you before that you need to deliver software as frequently as is practical, all right,
because you don't want to be this guy. This was me. I had a nice agile system set up at one of my companies, and we were getting two-week sprints going, and we were starting to really kind of get a nice pace and building a good velocity and all that, and we set up a nice little continuous delivery system.
Well, it was a decent one anyway, and started delivering to production every two weeks, on the nose, every Wednesday night, or every other Wednesday night, I was pushing out that sprint's deliverables and feeling pretty good about myself, you know, like, all right, look at me go. Good job, Jeff. You went ahead and started doing agile,
and you're delivering business value to your customers early and often. This is great, and I bet my customers are super happy with it, and after about three months, I got called into a meeting with the rest of the business stakeholders that I was delivering these applications to, and they said, hey, why don't you slow down a little bit?
And I was like, what? It just blew my mind. I was like, I'm delivering new features too often? I've never heard this complaint before. Like, I thought that that was the whole reason we're doing agile, and it turns out that the folks who were using this had a jam-packed, busy day,
and they knew our system very, very well, even its limitations or things that they had to use workarounds for, and they were so busy on a day-to-day basis that they didn't have time in their schedule every two weeks to stop and learn new features or find where things had been reorganized as we optimized our user experience.
So even though it was things that were ultimately going to save them time and make them more productive, they didn't have time to learn it that frequently, and they said, we'd rather go quarterly. That way, you know, once a quarter, we know when the release is coming, and we can go ahead and train on it in advance and set aside time that one time once a quarter and then have all those new features.
And, you know, I cried a little bit, and I was sad, and I kind of moped around the office a little bit, and then it kind of hit me. I was like, well, you know, we started practicing it that way. We spent about a quarter doing that, and what we found was that all of a sudden, we were doing this.
Our business users would report a bug that's causing them a problem, and we would pick that up, and we'd put it in the sprint, and we'd fix that bug, and we'd mark it as resolved in our tracking system, and the user who reported it would get a notification that said, great, your bug has been fixed, so now your life is going to be awesome. And they'd say, that's great.
When is that coming out? And they would look at me and say, you already fixed it, though. How come I still have to put up with this? And that's when I figured out that what worked best for my company at the time, and this has been something that other companies have really adopted, too,
is pushing out bug fixes at the end of every sprint, but saving the features for a quarterly release or whenever your business users or end users will tolerate those new features coming out. And so we just developed a bit of a branching strategy where we're like, okay, this branch represents what's in production right now. Here's our development branch. If you build a feature, leave it on the development branch
until the end of the quarter. If you fix a bug and you're signing the bug off, then just cherry-pick that change set down here to our release branch, and we'll push it out at the end of the sprint. And that established a really nice cadence that worked well for both our development team and the end users that we were delivering software for, and it worked out really, really well.
So if you are at a company that, like mine was, before we got a good continuous delivery system going, practicing what I like to call a scrummer fall, where you have a scrum system on your development team that's jammed in the middle of a waterfall delivery cycle,
if you're doing that, you're kind of trolling your users, and you need to find a way to deliver that valuable software to them more frequently. So today, as we talk about continuous delivery, we're gonna look at a system that is described on this slide. And the reason that it has complexity
is because as I was looking for a good way to deliver software, I would go to conferences or watch talks online, and they would show me cool stuff like, hey, here you go, check this out. Here's how you can right-click and deploy from Visual Studio, and it's gonna automatically deploy your stuff, and it's great. And I'd say, yeah, that is awesome.
I love it, that's great. And I'd come back from a conference or from watching a talk, and I'd tell the rest of the dev team, I learned the coolest thing. It's gonna be awesome. We're gonna be able to just right-click in Visual Studio and deploy a website. It's gonna be cool. And then I would go, because these guys stood on stage, and they went File, New, Hello World, MVC app, and shipped it right out the door,
and it was fine. And then I went back and I opened up my copy of Visual Studio with our solution that had 69 projects in it comprised of, oh, about eight or nine deployable web apps, three or four Windows services. We had four or five console apps that had to be run as scheduled tasks.
We had services that used MSMQ for message queuing, and we had to create message queues when we deployed and everything. And I would go, oh, you know, the guy on stage didn't show me how to do this with an actual complex application that has a lot of parts to it.
They just showed me the new hotness of MVC and how I could right-click and deploy. And found out that doing deployments of a real application is hard. And so you need a good set of tooling around that. So I started building it, and I tried this.
We would go ahead and just right-click and deploy and try to build up zip files and X-copy them out to production chairs and unzip them and make sure it was on all the web servers. Wow. That did not work very well at all. We had to do releases at 11 p.m. on Wednesday nights,
and there was many a time that at 4 a.m. on Thursday in a very, very exhausted state where I couldn't even think straight, I was trying to roll back a failed deployment so that whenever all my users got ready to come to work in the morning, they actually had a system to use. It was not good. And the reasons being, it wasn't consistent.
There was no consistency in how things got deployed. It was definitely not repeatable, so if I had to redeploy the same version, there was no way I could actually guarantee I was going to get it right. And there was no traceability. So even trying to roll back my own stuff, I had to try to remember what all I had done so I could go undo it.
And that left a really bad taste in my mouth with deployments. So I did what any smart developer would do. I said, huh, if I got to do something more than once, I'm going to automate it, right? So I wrote some batch scripts. Good old batch files, right? That's the first line of defense in deployment. And it got better.
Suddenly, our deployments were a little bit more consistent. They were a little closer to repeatable. They were a little bit traceable. Like, I had to occasionally write something out to a log file somewhere. And it got a little bit better. But these batch scripts got really, really unwieldy over time.
There was a lot of just really stupid, complex logic in it, hard-coded passwords for production accounts. It was not pretty. But it worked for a while, and we were doing it. And we were using this method when we first started delivering to production every two weeks,
and my users got mad at me. But I had it working. But it left me kind of wanting more and trying to figure out, there's got to be a better way to deploy software. And it made me start thinking about, like, what things really need to be in a good deployment system.
And that's where these bullet points kind of come from, is that I said, hey, it's got to be consistent, right? It's got to do it the same way every single time. It's got to be repeatable so that if I have a production server crash and I need to redeploy my application to it, it's got to be the same as it was before.
And most of all, I needed some traceability, especially as there was more people than just me doing deployments. We needed to know who had been doing what so we could make sure that we went and shook our finger at the right person if everything was broken. And it was usually me. So maybe the traceability kind of bit me in the ass.
Then I stumbled across a product that at the time was in beta called Octopus Deploy. And it kind of opened my eyes to a new way of building things, right? It's got the concept of build once and deploy everywhere, right? Build your executables, your binaries, your DLLs, whatever your deliverable package is
for your website, your service, your EXE. Build it once and then deploy that same exact built thing everywhere that you needed to go. And that means all your multiple environments, right? This is big, especially if you have to be like SOX compliant at your company,
you need to be able to prove that the very binary that you tested and signed off as good is the exact same thing that you sent to production. Octopus Deploy supports that. And I was like, oh, that's brilliant because I was running a new build every time, you know, because I wanted all my web config transforms to work for each one of my environments, so I was having to run that.
It's repeatable. It's automated, which is the biggest thing. I don't know if you guys know this about yourselves, but you're human, I'm pretty sure. And like me, you probably make mistakes from time to time, and so do the other, well, I'm sorry, you guys, I'm sure, don't make mistakes, but the other engineers
on your team, am I right? Like, those guys make mistakes. And that's why you want to automate your stuff. So you can say, hey, look, I wrote the automation script, so I know it's good, therefore, you don't have to go do this process and screw it up, which is one of those things that really saved my own butt a lot of times because I only had to get it right once.
Octopus Deploy introduces the concept of like an approval process for your deployments, right? So you can go ahead and get, you know, authority, an authoritative approval by the right person in the company that says, yes, these things can go to production. They've been signed off.
And it also created a whole lot of logging and traceability, so I had good insight into what was going on. So let's take a look at it.
So over here, I've got a nice little Windows Server 2012 machine, and this beautiful little thing you see here is Octopus Deploy. Right off the bat, you're gonna see one of my favorite features of Octopus Deploy, which is this dashboard. This dashboard becomes an information radiator
that you can use, and you can put this up on a screen somewhere, you know, in your ops area or your dev area or both, and all of a sudden, everybody, your dev team, your ops team, your dev ops team, if you're cool enough to have that title, can all see what version you've got deployed
in what environment. Was it a successful deployment or is there a big red failure? So let's take a look at this. As you can see here, I've got version 2.0.7.25 in development, but I'm only on .24 in staging and production.
And so I'm pretty sure that .25 is ready to go. It's ready to go out to staging and be tested. So let's go push it to staging. Um, I'm gonna click in here, and I'm gonna say, promote. Two. Staging. Okay. Here's the steps it's gonna run.
Great. Do it. And here it goes. It's deploying. That's all I had to do. Click, click. Done. It's acquired its packages that it's gonna deploy. It's going through and deploying my service bus. It's deploying my website. Uh, it's gonna deploy the mailer scheduled task. Um, and there you go.
Now I just pushed the exact same bits that I said were in development that I was like, hey, I went out and I tested it in development right over here. 2.0.7.25 in our development environment at development.complexcommerce.com.
And I pushed it out to staging. Here's our staging area. As you can see, we're in staging.complexcommerce.com. So let's go ahead and refresh and take a look at, ah, look at that. 2.0.7.25. Push to staging.
That was pretty simple. I didn't even open up a command shell or visual studio to do that. That's good stuff. So let's take a look at what this did for us. All right, obviously it deployed our website. Let's go have a look in here.
Everybody see that okay? That's not what we want. So as you can see here, I've got this complex commerce website. Obviously, you know, like a real production system, I'm running dev, staging, and production all on one machine. Hit the demo. Um, I've got complexcommerce.development, complexcommerce-production, complexcommerce-staging.
Octopus Deploy came in here and created those sites for me. They didn't exist before I did the first deployment. All right? It came in and set up my site in IIS. Um, it created application pools that you can see here,
set them to the right version of .net framework of 4.0 and integrated, set them to have application pool identity, or I could tell Octopus, hey, go ahead and use this dedicated user I've set up for each environment. It did all that for me. Great. That means that now I know my websites are created in a repeatable manner.
If I have to deploy this onto six or eight or ten web servers, it's gonna set those sites up for me the right way. It's gonna set the right application pool identity so that if I've configured my production domain so that this particular app pool identity has access to a database or a particular file share, Octopus Deploy's gonna make sure I've got all that set up and ready to go.
Now, I told you we were deploying something complex. We also had some Windows services in there, right? We had one, anyway, our service bus that handles communication between whatever. Full disclosure, this website doesn't work. But, um, but it does have these Windows services,
and as you can see here, it created the complex commerce service bus for development, production, and staging. Again, those didn't exist before I did the first deployment. Um, and it came in here, and every time I do a new deployment, it updates those. We pointed at the right version of the EXE running under the right service account.
So, what all kind of stuff can you deploy with Octopus Deploy? Um, anything you can think of just about that gets deployed on Windows, you can do it with Octopus Deploy. Um, it's got really great, rich support
for deploying websites to IIS, deploying Windows services. It's got integrated support for deploying to Windows Azure, Windows Azure websites, Windows Azure cloud services. Um, you can deploy over FTP or SFTP. Um, basically, you can deploy just about anything.
You can deploy a command line file. Um, all you've got to do is package up your application in a certain format that we'll talk about in a minute and feed it to Octopus Deploy and say, I want you to go put it on these machines. Now, the reason I say you can deploy anything is because Octopus Deploy,
uh, is based on PowerShell. Um, basically, anything you can do with PowerShell, you can do with Octopus Deploy. And you're going to go ahead and put in some of these scripts that it's going to run by convention. If it finds one of these scripts in your package, it will run it at the appropriate time. So, we've got, obviously, you know, you can tell by the names pretty much what they do.
We've got to pre-deploy that it's going to run before it actually starts the deployment after it's unzipped your package. It's got the deploy.ps1 that's going to represent the actual deployment that needs to happen. Um, a post deploy if you need to do any cleanup or, you know, run any integration tests or, you know, warm up your site. And, uh, deploy failed in case something goes wrong during the deployment.
You can have a hook in there to actually go and log it somewhere, gather some debug info, roll something back. Um, there's a lot of good options there. So, let's have another demo.
So, I told you that Octopus Deploy supports the concept of build once and run everywhere. So, let's look at what we're doing for our builds. Um, in this system, I'm using TeamCity.
Um, I used to use Team Foundation Server, um, but, you know, I'm recovering. So, I'm using TeamCity now. Um, to be fair, I haven't used Team Foundation Server since about TFS 2010. Um, so, I hope it's gotten better, maybe.
Um, but I abandoned it for TeamCity and I haven't looked back since. Um, TeamCity is super easy to configure and it has a ton of features and, um, and it was also, it's also good for running. It can run on multiple platforms and it can build for multiple platforms as well, um, which is a lot harder to do with TeamCity
from what I recall. So, as you can see, I've got myself this build project here and every time that I check in some code, it runs this build. It's looking at my Git repository and every time it sees a commit, it says, all right, cool. Well, I'm gonna build that for you
and run all your build steps. So, let's go look at what the build steps look like. Um, we've got some general metadata about the build here, a build version here, so I'm having it create a nice semantic versioning thing for me by, uh, obviously I've, you know,
done a really nice thing of locking this into 2.0.7 and then just using TeamCity's build counter. You can really customize this based on a lot of things. You can even share build counters and build numbers between multiple build configurations. There's a lot of powerful stuff here. In our build steps, you can see TeamCity's got, um,
nice support for doing NuGet package restore, right, because you don't want to check all those things into your Git repository. So just check in your package.json file, or your, uh, your, uh, package file. Sorry, not NPM. And, um, have your, uh, your package.config and then have this guy go ahead
and run your NuGet install, put all your NuGet packages back in for you. Um, keeps your repository size nice and down. And then it's got a built-in solution runner that says, okay, cool, I'm gonna just run this build for Visual Studio solution. You point it at the solution file, uh, tell it what targets that you want it to build, and it goes off and builds it for you.
Yay. Um, it just shells out to MSBuild for that. Um, and then right here, I've got a NuGet publish step, right? So I told you before that you needed to package your application a certain way for Octopus Deploy to use it. Well, that certain way is a NuGet package.
Um, which sounds a little weird. It's like, well, wait a second. That's for packaging up, I don't know, libraries and tools, not my application. And to be honest, it uses the NuGet package as a glorified zip file. Um, essentially it's a zip file that contains metadata, most important of which being a version number.
Um, and that's what Octopus Deploy is really after out of the thing. Um, so because that provides a nice way that .NET developers are already kind of accustomed to working with stuff, it makes a great packaging format that can also support versioning. Now, let's take a look at my solution over here,
and we're gonna see that up here at the top of my complex commerce solution, I've got this little thing called .OctoPack that looks a lot like the way .NuGet embeds itself in your solution to support package restore. Um, it even has its own copy of NuGet EXE. It's got a .targets file here
that essentially provides a set of MSBuild targets that allows it to hook in to your native build solution and create this NuGet package for you, so you don't have to worry about how to do it. Um, it has automatic support for both websites
and then binary type things such as executables or Windows services, and it will detect your project type and handle it accordingly. Um, and all you really have to do is set a MSBuild variable that says, oops,
as you can see here, it injects itself in the build depends on OctoPack target, and it's got this runOctoPack condition, okay? So you probably don't want to build the NuGet package on your local machine every time you run your app from Visual Studio. Well, this is gonna go ahead and allow you to not have to worry about that,
and you can just set this on your continuous integration server and have them built out there, okay? Um, and this is what we have done with our TeamCity solution. So let me switch back over to TeamCity. Octopus Deploy provides a...
provides a TeamCity plug-in that makes working with or integrating TeamCity with Octopus Deploy much, much simpler. Um, so after installing the Octopus Deploy plug-in for TeamCity, if I come down here and look at my Visual Studio build step, um, there is some Octopus packaging down here. So I just check a box that says runOctoPack,
and I say, okay, just use the build number for this build that we're already generating in order to create the package versions that we want to look at. And now whenever my builds run, it automatically creates those packages, which I can then publish using this NuGet publish step.
Now, what's interesting here, you'll notice that the target is localhost. That's actually pointing at my Octopus Deploy server. Octopus Deploy has a built-in, uh, NuGet package feed that works pretty well and is very fast. Um, you don't have to use it. You can use an external feed if you already have your own myGit setup, maybe,
or you're running a local one. Uh, be wary of using a file store, you know, a file system-based NuGet feed. For whatever reason, they're insanely slow. Um, hopefully improvement has been made on that, but I don't think so. Uh, Octopus Deploy's internal implementation is really, really fast. It's got some optimizations to handle it a little bit better.
Um, so I tell it, cool, go pick up the .newpackage file out of these directories that I built and publish it out to my Octopus Deploy server so that Octopus Deploy has packages to send out. Now, we're gonna go ahead and take this one step further, because right now, I'm running a build
on every single check-in. But then I have to come over here to Octopus Deploy and say, okay, yeah, that's great. I've got my build going here, but now I gotta go create a new release and select the package versions
that I want to deploy. Well, I probably want to deploy the latest version that I just built. And I can add some release notes and say, okay, cool, let's create this version. Well, I don't want to have to do that every time. I want to continuously deliver, right? I want this to happen automatically, especially to my dev environment where, you know, we're trying to dogfood this thing and make sure that it's working well.
So let's go add a step to our build process here. I'm gonna say, let's add a new build step. And this is going to be, based on the Octopus Deploy plug-in, a create release step.
And you can see I've already got my URL there. My API key's already in. Thanks for remembering that for me, Chrome. By the way, Chrome knows way too much about me. It's a little bit scary. And I'm gonna tell it the project that I want it to create. I'm gonna say, for the release number, let's go ahead and use this built-in TeamCity variable
for the build number. And I want you to deploy it to my development environment. And I want you to wait for the deployment to complete, because if the deployment fails, I want my build to fail. I want everything to go red across the board on my build server, on my deployment server. I want to know that something's wrong.
And I can pass in additional command line parameters and save. Excellent. So let's go make a change. You'll notice up here in our title bar, you can kind of see that I've got the environment that these things are deployed to
in the title of the site. But it would be a lot easier to read that if those two things were switched around. So let's go take a look at how that environment is getting put in there and make that change. So you'll see here, if I come open up this complexcommerce.web,
in my home view, this is a Nancy app, I am simply saying, great, I'm sorry, it's in the actual shared template.
I am saying, great, on our title, set it to complexcommerceviewbag.environment. Awesome. And as you can imagine, we are pulling that from our
system.configuration.configurationmanager.appsettings environment. Ah, great, it's in our web config. Cool. So in the web config, I've got this thing set to local. So how's it getting set to the rest of those things? Octopus deploy has the concept of variables,
and it will go through and perform these transforms for you. So rather than having, you'll notice, I only have a web.debug and a web.release. I don't have a web.staging, a web.production, I don't have any of that in there to actually transform this thing for those environments.
I'm letting Octopus deploy handle that for me. So if I come in here and look at the setup of my Octopus deploy project in our build process, here's all the steps that I've told it how to deploy my stuff. And I've also got a set of variables.
And you'll see right here, I created a variable called environment. It's not a very creative name, but it works. And I've told Octopus to plug in the special value that Octopus deploy creates. It has all these built-in variables, like the environment name, the machine name it's deploying to, the step that it's currently deploying, the version that it's deploying, what was the last version that was deployed,
all these variables that it makes available to you. And you can scope those variables to different settings, such as, oh, I want this variable to only apply to this particular environment or on these machines or in these roles. Well, I've told it to put the environment name that it's deploying into my environment variable, so that gets surfaced in my application.
And we see that in what is made right here in our... Where did our little shared config go? Layout.cshtml. Great. So let's go ahead and make this change to say... Let's put the environment name first.
And let's save it. And let's jump down here to our...
Okay, great, we've got a changed file. We'll say git add.git commit. Yay, new changes. And we'll commit that. And when we come over here and take a look at our TeamCity,
if we come back to our project view, we're going to see that TeamCity is watching our repository, and it will go ahead and pick up that pending change or make a liar out of me.
Let's see, oh, there we go. Picked up our pending change, as you can see here. And after a very short delay, it will automatically kick off the build, because I've told this, hey, every time there's a change, kick off a build. So there it goes.
I think it's got a 60-second delay built in. So it kicked off our build for us automatically, and now we're building 2.0.7.26. I'm sure you guys can see that here. This build is running. We'll click on it and see the details. And luckily it's a pretty simple project. It doesn't take too terribly long to run the build.
And it's going to start to show us what steps it's taking. You see this here. Okay, it's updating the resources. It's running our Visual Studio build. It already ran the NuGet package install because there was no new NuGet packages, so it used the cached ones.
And now it's publishing those. And hey, great, it created Octopus Deploy, waiting for one deployment. Let's go check out Octopus Deploy. Let's see what's happening on our dashboard. Ah, look at that. We've got a deployment in progress. Right there on our dashboard. Everybody can know, hey, cool, we're pushing out the latest changes to 2.0.7.26. This is good stuff.
Great, successful deployment. Let's go take a look. In our development environment, we hit refresh. And hey, looky there. Now we've swapped our title around. Great change. New version number has been published as well, which is also coming from an Octopus variable.
So, awesome. That looked pretty good. And let's go ahead and at the same time say we want to push that to staging. Well, cool. We'll just come back like we did before, tell it we want to promote it to staging.
Go. Do your thing. Excellent. Now we can deploy our next new version. So we'll let that do its thing, and we'll come back over here. So these variables and transformations
are actually really, really powerful. It uses the same concept of the web config transform, but it applies it to any kind of file. By default, it's going to go through and look for a star.release.config, whether that's web.release.config, app.release.config,
and it's going to go ahead and apply that first on every deployment. And then it's going to look for a star.environmentname.config. So if you have web.staging.config that has a bunch of settings in it, it'll go apply that when it does the deployment to staging. This is how it supports the build-once-deploy-everywhere model. You don't have... Because now your config transformation
is no longer tied to your build process. It's tied to your deployment process, which is where you want it, right? Because those configuration values don't need to change at build time. They need to change based on the environment the code is headed into. You can also define any custom files. You can say, hey, look, go look for this file and apply config transforms across that as well.
So in addition to just applying a config transform between two files, it'll also substitute in any variables that you have defined. I showed you that variables grid. So it's gonna automatically look at the connection string section of your config file and sub those in, which is great. And you can actually set some sensitivity
and access level on these variables. So maybe your developers have access to your Octopus Deploy portal, but your, you know, your production ops team says, well, I'm not giving you the connection strings for our production database. And as a developer, I don't want the connection strings for the production database. That's more responsibility than I'm looking to take on.
But they can go and input those variables in and say, great, these variables are gonna be available during the deployment, but we're not gonna show them to you in log files, and we're not gonna let people who aren't authorized see these variables. Awesome. That's gonna make your ops guys really happy. This stuff can happen automatically, and they don't have to give you the password. Great. It's gonna go through and look in,
as we saw, your app settings of all these things and apply your variables into there. And then it's also gonna make all of those variables that you have defined in the portal available to any of those PowerShell scripts we talked about, the deploy.ps1, predeploy.ps1, so you can take action based on those variables whenever you are running your own scripts.
Okay, more demo. So this is all fine and good. We've got this creating our build and deploying to dev every time. Great. Now we can test. Well, let's say that we decide what we want to do is we want to push out...
Oh, Lord. I broke it. Well, that's not good. Let's see what we did here. Probably killed the service.
Let's see. We'll find our TeamCity server. We'll start that service back up. Not sure what happened there. Let's go see. Okay, TeamCity's warming back up. So let's say that we want to
make sure that every night we want to produce a nightly build for people to go test and use and publish that somewhere. I don't want to have to go do it every night. I want it to be automated, right? That's why I automate the things. Well, I can set up in TeamCity a build step that's called Nightly
that's set on a schedule to run every night at, I don't know, 8 p.m. or something and grab the latest change out of dev and promote it to our staging environment. And if TeamCity ever warms itself up, I will show you that. You know, we're running short on time, so that's not that interesting of a demo.
Anyway, let's move on to something cooler. One of the cool things that you can do with this whole promote concept is you can also have it run smoke or integration tests before it promotes to the next environment, right? So if I set up this nightly build, let's say I've written a bunch of Selenium tests to go out and test my website,
or I've written a bunch of end-unit tests that are gonna run integration test calls against my API. I can script that out to run in TeamCity and go ahead and say, all right, well, cool, run this, and if those pass, then promote that build from dev to Nightly, right?
But if they fail, then don't do it. And notify me about it. Now, one of the other things I mentioned that's really important in Octopus Deploy is that it creates an audit trail.
Let's have a look at what our audit trail looks like. First off, you can see right here from the deployment that we've got nice logging. Let's look at our task log. We can see all the steps that were taken. I can see that it acquired these packages and where it got them and what version it used, and it's gonna tell me all about how it decided to deploy these things. It's gonna go through here and show me what it did
in order to deploy this tentacle, deploy to this tentacle, and how it actually ran this deployment. So tentacles are an interesting concept in Octopus Deploy. Let's come look at our environments page. Here you can see where I've defined my development, staging, and production environments.
Each machine that I deploy to is called a tentacle in Octopus. Just taking the metaphor a little further. And you install a Windows service on there called the Octopus Tentacle Service. That is listening for commands from the Octopus server. All right? And whenever it receives a command to do a deployment, it starts following those instructions
that I've defined out in my Octopus Deploy process. And it will come in here and deploy these applications into these particular folders that it runs. So if I come in here and look at the C Octopus folder under Applications, I've got a folder for each one of the environments
that exists on this tentacle. And in Development, you'll see each one of my applications. And in there, you'll see a package. You'll see a semantic versioning folder for each one of the deployments I've run and it going up for each one. This is really powerful in that, say with an IIS website, when Octopus Deploy runs this deployment,
it unzips it into a whole new folder and gets everything ready to go, performs all those transforms so everything's ready to launch. And then it goes to IIS and says, well, let me go ahead and just swap your home directory on this folder. So instead of pointing at 2.0.7.24, I'm now gonna point it at .25.
This is really valuable because now your old version is still there. If you absolutely had to roll back, you just have to go point an IIS directory back. Of course, the nice thing about Octopus Deploy is that it's repeatable, so I could just go back and say, you know what? Redeploy version .24, and it's gonna go back and redeploy
the version exactly as it sat at .24. Now, this is valuable because if you have written any, say, deployment scripts, right, like a deploy.ps1 or something to handle your deployment process, since that is checked in alongside your application, it's versioned with your application, okay? And that means that,
let's say it's a website and you've got some static assets that are served out of a folder called dist. And for whatever reason, you decide you need to change the name of that folder to public. So you go and change your deploy.ps1 that's generating those static assets to start putting them into .public. If your build script is centrally managed,
then if you have to go redeploy an old version of your app, now it's putting the static assets in the wrong place. The old version expects them to be under dist, but now your build script is putting them under public. By having your build script versioned along with your application, redeploying an old version is still going to work because it's going to use the version
of the build script as it existed at the time that that package was created. It's also going to snapshot all of the variables that you could define in your Octopus deploy portal with that version. So even if you go and change a connection string or a variable for future deployments, redeploying that old version to any environment is still going to use
a snapshot of the variables as they existed at that time. What about the database? That's the biggest question I always get with Octopus Deploy. Yeah, so my answer is, yeah, what about the database? No. Octopus Deploy doesn't have any built-in support for database deployment.
It doesn't have any database magic built in, mostly because database deployments are hard, if you guys have tried that. I have, you know, there are a few tools out there that will help. I have previously set up a system in the past where I would, we were using Redgate's SQL source control product,
if you guys have seen that, that lets you check all your database scripts and everything into your Git repository and it automatically versions them and everything. It set up a system where I was using that and then using Redgate's SQL compare command line tool that I ran in an Octopus deploy package that would go ahead
and compare the scripts as they existed at that version to whatever environment I was deploying into and it would apply those changes. It didn't work worth a damn. That command line tool was not very good and it would fail on all random stuff all the time. There is, there's a few other products
depending on how you do your database development that said, that are like Roundhouse, that you can actually version your scripts right there with your app and run it. That's one way you can go about your database deployments. Another tool is called Ready Roll SQL and it integrates in Visual Studio and uses the SQL database project types
and does kind of a similar concept where it goes ahead and versions your database and creates a version table in there so it knows what version you're deploying and what scripts go with that version and will apply those migrations for you. And database migrations are great as long as you're going forward.
Rolling back a database is a big problem. But that brings up a really interesting point. As you get into continuous delivery, you're going to find that rollbacks become a thing of the past. A rollback is not something you should really do. When you have a good continuous delivery system
and you have good repeatable automated deployments, there becomes less and less need to rollback simply because if you found something wrong with your deployment, you know there was a bug in your software or some kind of problem, it's really a lot easier, I've found, to most of the time just go fix that bug.
Commit it. Rebuild the package and push out the new deployment. Roll forward instead of rolling backward because do you really want to abandon your new deployment just to go fix a bug or would you rather say, hey, let's get all these features out here and fix this bug. And when you've got a good, fast, repeatable system, it becomes really easy to do that.
So let's take a look at what kind of stuff we can do with our deployment process in Octopus. If I come here on the process tab, you see I've got all these steps like notify release manager and approval and then deploying all these NuGet packages. If I click add step, we'll look at all the things that are available to us. I can tell it
I want to deploy a NuGet package. I can tell it I want to run a random PowerShell script. Maybe this script handles pulling a server out of a load balancer and then at the end I want to put it back in. I can send an email. I can say that there's manual intervention required. We'll show that in just a minute. I can tell it I want to deploy something to Windows Azure,
deploy, you know, upload something over FTP. So let's take a look at these email and approval steps because these are really interesting. If I come over here to our releases and we've got this
O.26 release and we've deployed it to development and we've deployed it to staging and it's been all signed off by QA and said this thing's ready to go to production. Let's send it out. Okay, well, I'm just a developer. I don't have permission to deploy to production but I'm going to go ahead and do it anyway because, you know, hey, come stop me if you don't like it,
right? Well, guess what? Somebody's already set this up so that whenever I go and deploy this release to production, it says, oh, and look at this. This little guy popped up and said on my little local mail server here saying that an email has been sent. Let's view that message.
So here's this nice email that came in that says, hey, release dude, deploy, ready to deploy this version to production and follow the link below to approve this and if I was in a real mail client, it would be clickable but I'm not
so we're going to copy and paste. So we will copy this lovely, lovely link here and let's go take a look at the current status of Octopus Deploy and look at this. It's paused. Even if we go to our dashboard, we can see, hey, this is waiting. It's chilling.
It's not doing anything yet and it says here that approval is required and it's assigned to no one. Let me show the details of that and it says, hey, a new release is ready for deployment to the production environment. Click the green button to proceed with deployment now although the button is not green but I don't have permission to do this. I'm not in the group that's allowed to release
so let me open up an incognito window that does not have my cookies in it and paste this in and we're going to come here and sign in as release dude.
So if release dude has already signed in and he followed that link, he comes here and he says, oh, okay, this needs approval. Oh, look, assigned to me. Let me show the details of that, great. Well, I can't interact with it yet because maybe this notification, maybe the people who are allowed to approve this, there's two or three different people who could approve it
so the first one to get there is going to click assigned to me and now I get to do this and I can put in notes here and I can say, you know, maybe I've got a different change management system that change requests have to go through and get all this approval and I can put a reference to that ticket in here if I needed to to say, oh, yeah, this was assigned off by all the people. I'm just going to say
that I'm release dude and I approve this message. Vote for me and I'm going to click proceed and now it's going to go ahead and finish doing that deployment. Well, this becomes really, really powerful because now you can automate the queuing
of a production release. Say you guys do a release to production every night or every two weeks or every quarter, whenever it is, you could have that scheduled automatically from TeamCity and you have the confidence of knowing it's not just going to send that code out without approval. It's going to stop and wait for someone who has the authority to say, yes,
this is ready to go and we're ready to go push it out to production or they could cancel it and say, no, we're not ready to push this out and that becomes really, really nice and then if I go look under, oh, this guy's not an Octopus Administrator so he can't see the configuration so let's go back where I'm the Octopus Administrator and can view
my configuration and say, let's look at this audit. What all's been going on here? Ah, okay. Here we go. A deployment was queued. Ah, release dude took responsibility for this and then said, yes, I approve it. Let's see the details. Ah, okay. Cool. Here's what he did. Here's how he changed that record. Great.
Now I've got a nice audit trail and I can even filter this down to say, oh, I think release dude's been up to no good. Show me only stuff he's been doing and I can start sifting through that. Now, in our Octopus Deploy configuration,
there's this nice little thing in here called the library, right? So this shows me, A, my internal NuGet packaging, package manager, package store, where I can view my packages that are here. I can manage my external NuGet feeds if I have any. Um, and then the script modules is really interesting, right?
So I can come in here and I've defined this script module. These are basically like PSM1 files if you guys have written PowerShell cmdlets. Um, let's say I've got a bunch of PowerShell that I want to reuse across multiple projects in, uh, in my Octopus Deploy settings. I can define that here at this level
and then make it be included with every project. And if I do that, then in all of my pre-deploy and post-deploy and deploy.ps1 files, this say hello cmdlet will be available. And I can make it take parameters and I can bind it to Octopus variables and this way I can build reusable pieces of functionality, right, that are centralized
but they're not necessarily shared. Rather than having a whole bunch of if statements that say if it's this project, if it's that project, I can just include the pieces I need and parameterize it and make that available to my other deployment scripts. Um, and then I've also got a nice thing called step templates. This is relatively new.
Um, these step templates are where I can define some of those different steps that need to be in my process, um, that are reusable. And what's really cool is that not only can I define my own, but there's a community library up here that has, you know, currently 46 templates that can do all kinds of cool stuff. Chocolatey and sure packages installed. Um, you can, uh,
back up a directory. You can do find and replace. You can interact with get. Uh, you can do all this cool stuff with IIS. You can create an MSMQ if you need to do that sort of thing. Um, you can notify New Relic of your deployment and your deployment is complete. Um, update a rack space load balancer. Here's SQL execute script.
If you're using SQL scripts for your database migrations, um, run in unit. And these are contributed by the community. So you can write your own scripts and contribute them back to the community. Right? And, um, you can create local users or get processor load. You can do all kinds of cool stuff here. And you can take these and include them right into your Octopus instance as a step template.
Right? Or you can define your own. So that little notify release manager step that we had before, I could say, well, I always wanted to do that. So let me define this at my deployment level. That way, this one common step can be included with all of my deployments. And I can define these parameters that are automatically going to become variables in the project
that includes these steps. So that becomes a powerful way to share the configuration that you've set up for one project with other projects. And then I can also create variable sets. So if there's sets of common variables that I use a lot throughout my projects, I can define that here so I don't have to repeat those in every project. And I can manage them
centrally if I need to. All right. We are just about out of time. So let's see. And all right. So that's all I have. Do you guys have any other questions you'd like to ask real quick?
No? Yes. So I assume you're deploying the node stuff to Heroku, or are you actually deploying your .NET stuff to Heroku as well?
Okay. So could you, yeah, I mean, you could do a deployment if you wanted to. If you look at the, stuff like the Windows Azure deployments and things take place on the Octopus server rather than a tentacle, because obviously there's not a tentacle being installed on Azure
for a website deployment. You can execute a shell script, right? And some of those step templates that say I'm going to execute this script from the server, from the Octopus deployed server, have git pull and git push, right? So you could, if you really, really, if you really hated life, you could go ahead
and package your Node.js app in a NuGet package and have Octopus deploy git push it to Heroku for you. I would not recommend it. I think you're going to be, you're going to be fighting the tool a lot because it just wasn't made to work with non .NET products. I would highly recommend using a different tool
like maybe Codeship. It's great for deploying Node apps to Heroku. But yeah, Octopus deploy is great for deploying .NET apps. It's not great for deploying non .NET apps at the moment. All right, any other questions? No? Okay. Well, thank you very much for your time this morning.