Delivery Dependency Support (or How Your Project is Not an Island)
Mink, Jess
Want to get a handle on dependency support and safe promotion, what does that mean anyhow and how can they help? You've come to the right place. This talk will dive into the philosophy of dependencies, how to use 'em and a bit about how the sausage is made.
 So, as Nell said, my name is Jess Mink. I've been a tech lead on workflow, aka delivery, and we're going to talk about dependencies. So if you're not here to talk about dependencies, you are in the wrong talk. I will not be offended if you leave. But if you are, welcome! Thank you for coming. So let's step back. Why does workflow, why does delivery, why does that product exist? What are we trying to accomplish? We've got all these freaking stages. We do all these things. We run unit tests, we run lint, syntax. We make humans interact with it and make sure it's the right thing. What are we trying to accomplish? We're trying to make sure it doesn't break production. That's the point of this whole thing, right? We go through all these hoops to make sure that our changes are safe to ship, that we're not scared to push them to production. So all the things I just talked about are for one single project, right? You might get lucky. You might catch cross-project dependencies in acceptance. But in general, all of our tests are targeted around one particular project and not how projects interact with each other. And the reality of our ecosystem, right, is that so many of our really interesting bugs are where different pieces of code hit up against each other. Because that's where team boundaries are, that's where people are thinking about things differently. So when we talk about dependencies, there's a couple different types of dependencies, right? So one type of dependency people mean are library dependencies, right? But that's not what we're talking about here. You're going to catch those at build time. When you go and build your project as a second stage, you're going to catch your build time dependencies. Your thing will fail to build, so that's not very interesting. What I'm here to talk about is API level dependencies. So your project exposes some type of interface that another project, another application, is consuming. So the example I'm going to use here today is a tiny URL server. So we've got an API where you give it a URL and it gives you a little summary, right, or vice versa, and a UI to make it easier to deal with. So clearly they're interacting via an API. They're built, they're deployed, and then they interact. So let's say one day your product person comes to you and they're like, dude, your API, this design sucks. It's not restful at all. I need you to go back and make it restful. So you do. You update all the APIs. And then while you're at it, you update the UI to, you know, talk to the new APIs so that you don't break everything. But you didn't pay attention. The API gets to production first. So we have all these tests. We did all these things. How do we avoid this type of failure, right? And like you can tell your product person, no, you have to check every single page of every single thing in acceptance, but that just doesn't scale well, right? We're in the business of automating things, not making people's lives miserable. So what else can we do to help with this? So in terms of thinking about this, let's go back and look at all the stages in delivery and talk about what they're for, because that'll tell us where we need to change things. So we have verify, right? This is, is your code reasonable, right? Like, are you just throwing bugs in there? Does your code look awful? Does it make me cry, right? Do we want to take it into our code base? Is it going to get merged to get? So that's what that's about. Build, build time dependencies, right? Does the thing build? Can we use it? We've already accepted it, but like, let's make sure it can build. Then we get to acceptance. That's where we bring in our product people. Did you build the right freaking thing? Does it look really ugly because we're engineers and we don't always know about UI, right? This is where we bring the rest of the company in and they mess with what we have and make sure it's what we want to ship out to production. This is also an interesting place because it's the first time your project is dealing with its dependencies, right? It's runtime dependencies and API dependencies because we've taken all those from Union and pulled them over because if you're playing with that tiny URL, UI, right, you need the API to try it out. But when you get to Union is when life gets really interesting because you flip everything on its head. Suddenly that's when everyone else has to deal with you. So this is where we should be finding those API level incompatibilities. And historically you didn't have any way to do that, right? You got to Union, you ran your projects, smoke and functional tests, but if you just changed the API, you might not even know what UIs are relating to you, right? In the tiny URL example, sure. But in a real organization, do you really always know who all is depending on you, who all your consumers are? Are you going to bet me that you didn't ever forget one that no one put a dependency on your project you didn't know about? It doesn't happen, right? So we need some way to automate that. And then rehearsal, we're rerunning the tests from Union to make sure that they still work in a clean environment because Union may have had breakages that we fixed and delivered as your production environment. So as I alluded to, you want a way to programmatically declare your dependencies, your runtime dependencies. So here we've got an example. The top there is the code in the config.json that will actually make the UI depend on the API. It's that bottom line. It's pretty darn simple. And when you do that, when that change gets to Union, because Union is where we have to interact with other projects, we actually update the workflow UI. So it'll show your dependencies and who depends on you, which is cool, right? A new person on your project can go and be like, hey, look, this is the web. This is where that thing is happening. I understand now how these projects interact. So that has some value, but that still doesn't keep you from breaking production. So this is what keeps you from breaking production. Because what we do is we're actually running the tests. This is the API running, and we're running the UI tests because it has a dependency on us. Now in Union, we're going to run the tests of every single project that has a dependency on us. And that's how we're going to know we don't break things, right? This broke in the tests before it made it to production. Yes, that's what we want. So now we'll go and ship the UI, right? We can fix it. That's weird. You've probably never seen that before. The button is orange. Why is the button orange? The button is orange because things are broke, right? Your Union environment is very sad right now. And it's not just sad in general. It's sad in ways that relate to this project. So please don't be shipping changes if it's not going to make this better, right? Don't pile on to the problem. That's what that orange button means. It means things are broken. Let's go fix them. But in this case, we're fixing them, right? We're shipping that change we thought about. Same thing happens in acceptance. You get two warnings. Okay. And now we're in Union. We ran our tests. They passed. We had a bug. We caught it in our tests. We're good. So we're done, right? Everyone knows what to do, right? You just put that line in your config.json. All good. We can go home, right? No questions? Yeah, I didn't think so. So here I'm talking about delivery controlling promotion. And those of you who've used delivery a lot or workflow a lot are probably being like, hey, it's kind of? How does it do that? I wrote my deploy cookbook. I'm dealing with deploying my applications. And yeah, it's true. Delivery directly can control that orange button. But that just warns you, right? That's not actually controlling what goes out to production. So what's happening behind the scenes is delivery truck is actually managing a bunch of version pinnings for you. And this is a screenshot from Chef Server because that's where delivery truck puts them. Delivery truck, if you don't know, is a build cookbook that is recommended to be used as the basis for your build cookbook. So you can include it and you can include those recipes. And then you can add extra stuff in your recipes that you'd like. And in particular, it's the provision stage of delivery truck that does all this version management. So you really, really, really want to use delivery truck, the provision phase at the very least because that's how you get this. So you're probably being like, yeah, I heard about delivery truck. I mean, how many of you have heard of delivery truck and use it? Okay, cool. How many of you have heard that delivery truck is just for cookbooks? Ha-ha, it's not. So it also does applications. And it was a total pain in the butt before, but we made it easy. You just do that. You just put that in your published face and delivery truck will keep track of what applications and your version go with what project. And we actually store it in the override attributes. So if you need to be debugging, if you need to debug stuff, you can go into the override attributes and actually see what all the versions are. And of course, delivery truck can't automatically deploy your application, but you can query and pull these version numbers in to figure out what you want to deploy. And you can version your build artifacts, right? And that's how it all ties together. So there's more documentation about delivery truck here. I know that's a tiny URL, but you're not taking notes anyway. You're going to look at the slides later. Also, if you Google for Chef Delivery Truck Doc, it's the first hit. So in there, I talked about failed projects, right? And things being related to a failed project. And how you don't want things related to a failed project to promote. So you understand what I mean by promote now, but what do I mean by related to a failed project, right? The most obvious thing is, well, if it's a dependency or a consumer, if there's a dependency relationship with the failed project. But what does that really mean, right? If you just have this, sure, right? You've got your failed stuff, you've got your healthy stuff, the healthy stuff can keep shipping and will just hold the failed stuff back. And I really mean this, right? This will get stuck in union. And this will go out to rehearsal and delivered. Your union isn't a bottleneck, right? You can have a failed project in union and still ship other things that are unrelated. Your entire company doesn't have to come grinding to a halt, which it did before. But I bet you're all thinking, that's not what my company looks like. My company looks like this. I never have completely unrelated projects. That is not my life. So say you have this again, you've got your failed projects, you've got some new stuff that's related, that's trying to test against it. Anything that tries to test against something that's blocked gets blocked. That's the simplest way to put it. So this means that if you have a union failure, you can ship completely unrelated things. But you want to get on that union failure as quickly as you can because it's going to grow like an amoeba consuming the universe until things that you would never expect are getting blocked. And you're probably wondering, why the heck would you do that? Why is it this all-consuming blockadness? And it's actually pretty simple. So this changed, which broke the red one. And then we tested those two green ones, and they're test-passed, but they tested against that red one. They tested against a version that's not safe to ship. And we don't actually know how they would have tested against the version that's already in rehearsal and already delivered. It might break horribly against the version that's further along in the pipeline. So we can't ship them until we have a chance to test them against a version that's actually shipable. So that whole freaking thing is blocked until you fix it. Sorry. We did what we can. There's not magic, right? So yes, fix your union fast. Otherwise, people are going to get sad, and it's going to get confusing. If you see that yellow square, if you go to the dashboard, you'll see what's broken in union. So you probably want this magic, right? This sounds pretty cool. You already have it. If you're using a delivery that's less than six months old and you're using delivery truck, you already have all this functionality. All you have to do is go modify your config.json to add the dependencies array. Add all you have to do, and you get all this power. If you don't remember what I said, there's documentation that says it all, though possibly with less giggling. So here's the summary. We're talking about API-level dependencies. We don't mean compile time. That's a completely different kettle of fish. We mean cross-project at runtime. You need to use delivery truck. In particular, you need to use the provision phase. If you don't, or if you use a really old version of delivery truck that you hacked for your company, you're going to be sad because very old versions of delivery truck just promote everything as a block, and your safety is gone. So don't do that. Use one that's less than six months old. Keep union healthy because it's going to become a raging amoeba and block everything. And that's where the docs are. What questions do you all have? Okay, so you're saying you have an application and a... So you're saying you have a cookbook and you have an application, and you need the cookbook to be updated before the application? Sure. Sure. So if you have a dependency... It's kind of long, can we hand it over here? So basically, my understanding of your question is you have a cookbook and you have an application, and they have to be in tight secrecy, right? They could almost be in the same code repo, but you've decided to make them separate projects, but they're really tied together, and they have to move in lockstep. In this instance, yes. So that's the case. They basically have a dependency on each other, and there's actually nothing against putting circular dependencies in, so you can just make it so whenever one of them changes, it will run the test for the other one. That'll break union until you get the change for the other one out there. But if the cookbook can't deploy the application without its change, how will it get through acceptance? So you've... How do you get them through acceptance now? I'd rather not say. Okay. Why are they separate projects? Because that cookbook is shared amongst a lot of... It's the generic JBoss cookbook, and just this application needs a change to that to be able to deploy. And why can't you update the cookbook first? Yeah, I think you can. So yeah, just update the cookbook first, and then your project can't get through acceptance anyway, you said. So you don't even need to set up a formal dependency relationship. What other questions do you have? This is a ton, and I purposefully left a lot of time for questions because there are so many freaking directions people can go in with this. So if I've been using delivery a while... Hold it close to your mouth. If I've been using delivery for a while, and I've got a lot of projects not doing dependency management, if I turn it on on some, what happens with all the other projects? Sure, they keep acting the way they are. Well, so back in January, when you updated delivery truck, something subtle happened. It used to be that no matter what, all projects would be updated at once. What happened instead is only successful projects would get promoted at once. So what I mean by that is say you have a project foo that's broken in union. A year ago, if you're using an ancient version of delivery truck, what would happen is when you shipped bar to union, if it passed its test, foo and bar would go down the pipeline, and your broken foo would go out, and you would be a very sad panda. And this last winner, what will happen is foo will stay there, and bar will happily go through the pipeline, but foo will stay in union and will not get promoted through until it's fixed. So that's the current state of the world before you add your dependencies in. As you add dependencies in, it just increases the set of things that will get stuck in union. But everything else is independent and can flow through. Actually the assumption right now is all your projects are completely independent. You've got one behind you. So I'm fairly new to delivery. I do have a question in your example where you had the two green ones that were depending on the red one, and it kind of stopped everything, right? So my question is... This one? Yeah, yeah. So if the two one... If the red one, the version of the red one in production is still valid, is there a way for me to test those two green ones in this current state against the production version, and if that passes, I can push those through? Nope. The kind of the fundamental vision inside of delivery is that you roll forward. We don't really give a way to roll back. If you decide that you can't fix that red one reasonably, the thing to do is to push an older version through the pipeline, and then that'll unblock your pipeline again. Right. In that case, it will be the version that's already in production. Yeah. Yeah. So if you can push one through, that'll make everything work. That works. But no, we don't have any way to say ignore this particular project and roll back without putting a change through. Okay, it makes sense. Thank you. Yep. Keeps things simpler. Chris? So if I have some really terrible looking code that does my version stuff today, that example that you gave, does it allow me to just basically set the project name, the version number, and then just pass it in an arbitrary hash of things that I want to know about later? Yep. Oh, awesome. So you can give it an arbitrary list of attributes. Wow. That's like 30 lines of code that just went away. Yay. Any other questions? Cool. So that's what I had put together. I wanted to make sure there's a lot of questions. I'm going to be out front if people have additional conversations they want to have. Cool. Thank you, Josh. Thank you. Thank you. We'll back up in session. Thanks for joining us. Yeah. Thanks,生애들.
 So, as Nell said, my name is Jess Mink.  I've been a tech lead on workflow, aka delivery, and we're going to talk about dependencies.  So if you're not here to talk about dependencies, you are in the wrong talk.  I will not be offended if you leave.  But if you are, welcome!  Thank you for coming.  So let's step back.  Why does workflow, why does delivery, why does that product exist?  What are we trying to accomplish?  We've got all these freaking stages.  We do all these things.  We run unit tests, we run lint, syntax.  We make humans interact with it and make sure it's the right thing.  What are we trying to accomplish?  We're trying to make sure it doesn't break production.  That's the point of this whole thing, right?  We go through all these hoops to make sure that our changes are safe to ship, that we're  not scared to push them to production.  So all the things I just talked about are for one single project, right?  You might get lucky.  You might catch cross-project dependencies in acceptance.  But in general, all of our tests are targeted around one particular project and not how  projects interact with each other.  And the reality of our ecosystem, right, is that so many of our really interesting bugs  are where different pieces of code hit up against each other.  Because that's where team boundaries are, that's where people are thinking about things  differently.  So when we talk about dependencies, there's a couple different types of dependencies,  right?  So one type of dependency people mean are library dependencies, right?  But that's not what we're talking about here.  You're going to catch those at build time.  When you go and build your project as a second stage, you're going to catch your build time  dependencies.  Your thing will fail to build, so that's not very interesting.  What I'm here to talk about is API level dependencies.  So your project exposes some type of interface that another project, another application,  is consuming.  So the example I'm going to use here today is a tiny URL server.  So we've got an API where you give it a URL and it gives you a little summary, right,  or vice versa, and a UI to make it easier to deal with.  So clearly they're interacting via an API.  They're built, they're deployed, and then they interact.  So let's say one day your product person comes to you and they're like, dude, your API,  this design sucks.  It's not restful at all.  I need you to go back and make it restful.  So you do.  You update all the APIs.  And then while you're at it, you update the UI to, you know, talk to the new APIs so that  you don't break everything.  But you didn't pay attention.  The API gets to production first.  So we have all these tests.  We did all these things.  How do we avoid this type of failure, right?  And like you can tell your product person, no, you have to check every single page of  every single thing in acceptance, but that just doesn't scale well, right?  We're in the business of automating things, not making people's lives miserable.  So what else can we do to help with this?  So in terms of thinking about this, let's go back and look at all the stages in delivery  and talk about what they're for, because that'll tell us where we need to change things.  So we have verify, right?  This is, is your code reasonable, right?  Like, are you just throwing bugs in there?  Does your code look awful?  Does it make me cry, right?  Do we want to take it into our code base?  Is it going to get merged to get?  So that's what that's about.  Build, build time dependencies, right?  Does the thing build?  Can we use it?  We've already accepted it, but like, let's make sure it can build.  Then we get to acceptance.  That's where we bring in our product people.  Did you build the right freaking thing?  Does it look really ugly because we're engineers and we don't always know about UI, right?  This is where we bring the rest of the company in and they mess with what we have and make  sure it's what we want to ship out to production.  This is also an interesting place because it's the first time your project is dealing  with its dependencies, right?  It's runtime dependencies and API dependencies because we've taken all those from Union and  pulled them over because if you're playing with that tiny URL, UI, right, you need the  API to try it out.  But when you get to Union is when life gets really interesting because you flip everything  on its head.  Suddenly that's when everyone else has to deal with you.  So this is where we should be finding those API level incompatibilities.  And historically you didn't have any way to do that, right?  You got to Union, you ran your projects, smoke and functional tests, but if you just changed  the API, you might not even know what UIs are relating to you, right?  In the tiny URL example, sure.  But in a real organization, do you really always know who all is depending on you, who  all your consumers are?  Are you going to bet me that you didn't ever forget one that no one put a dependency on  your project you didn't know about?  It doesn't happen, right?  So we need some way to automate that.  And then rehearsal, we're rerunning the tests from Union to make sure that they still work  in a clean environment because Union may have had breakages that we fixed and delivered  as your production environment.  So as I alluded to, you want a way to programmatically declare your dependencies, your runtime dependencies.  So here we've got an example.  The top there is the code in the config.json that will actually make the UI depend on the  API.  It's that bottom line.  It's pretty darn simple.  And when you do that, when that change gets to Union, because Union is where we have to  interact with other projects, we actually update the workflow UI.  So it'll show your dependencies and who depends on you, which is cool, right?  A new person on your project can go and be like, hey, look, this is the web.  This is where that thing is happening.  I understand now how these projects interact.  So that has some value, but that still doesn't keep you from breaking production.  So this is what keeps you from breaking production.  Because what we do is we're actually running the tests.  This is the API running, and we're running the UI tests because it has a dependency on  us.  Now in Union, we're going to run the tests of every single project that has a dependency  on us.  And that's how we're going to know we don't break things, right?  This broke in the tests before it made it to production.  Yes, that's what we want.  So now we'll go and ship the UI, right?  We can fix it.  That's weird.  You've probably never seen that before.  The button is orange.  Why is the button orange?  The button is orange because things are broke, right?  Your Union environment is very sad right now.  And it's not just sad in general.  It's sad in ways that relate to this project.  So please don't be shipping changes if it's not going to make this better, right?  Don't pile on to the problem.  That's what that orange button means.  It means things are broken.  Let's go fix them.  But in this case, we're fixing them, right?  We're shipping that change we thought about.  Same thing happens in acceptance.  You get two warnings.  Okay.  And now we're in Union.  We ran our tests.  They passed.  We had a bug.  We caught it in our tests.  We're good.  So we're done, right?  Everyone knows what to do, right?  You just put that line in your config.json.  All good.  We can go home, right?  No questions?  Yeah, I didn't think so.  So here I'm talking about delivery controlling promotion.  And those of you who've used delivery a lot or workflow a lot are probably being like,  hey, it's kind of?  How does it do that?  I wrote my deploy cookbook.  I'm dealing with deploying my applications.  And yeah, it's true.  Delivery directly can control that orange button.  But that just warns you, right?  That's not actually controlling what goes out to production.  So what's happening behind the scenes is delivery truck is actually managing a bunch of version  pinnings for you.  And this is a screenshot from Chef Server because that's where delivery truck puts them.  Delivery truck, if you don't know, is a build cookbook that is recommended to be used as  the basis for your build cookbook.  So you can include it and you can include those recipes.  And then you can add extra stuff in your recipes that you'd like.  And in particular, it's the provision stage of delivery truck that does all this version  management.  So you really, really, really want to use delivery truck, the provision phase at the  very least because that's how you get this.  So you're probably being like, yeah, I heard about delivery truck.  I mean, how many of you have heard of delivery truck and use it?  Okay, cool.  How many of you have heard that delivery truck is just for cookbooks?  Ha-ha, it's not.  So it also does applications.  And it was a total pain in the butt before, but we made it easy.  You just do that.  You just put that in your published face and delivery truck will keep track of what applications  and your version go with what project.  And we actually store it in the override attributes.  So if you need to be debugging, if you need to debug stuff, you can go into the override  attributes and actually see what all the versions are.  And of course, delivery truck can't automatically deploy your application, but you can query  and pull these version numbers in to figure out what you want to deploy.  And you can version your build artifacts, right?  And that's how it all ties together.  So there's more documentation about delivery truck here.  I know that's a tiny URL, but you're not taking notes anyway.  You're going to look at the slides later.  Also, if you Google for Chef Delivery Truck Doc, it's the first hit.  So in there, I talked about failed projects, right?  And things being related to a failed project.  And how you don't want things related to a failed project to promote.  So you understand what I mean by promote now, but what do I mean by related to a failed project,  right?  The most obvious thing is, well, if it's a dependency or a consumer, if there's a dependency  relationship with the failed project.  But what does that really mean, right?  If you just have this, sure, right?  You've got your failed stuff, you've got your healthy stuff, the healthy stuff can keep  shipping and will just hold the failed stuff back.  And I really mean this, right?  This will get stuck in union.  And this will go out to rehearsal and delivered.  Your union isn't a bottleneck, right?  You can have a failed project in union and still ship other things that are unrelated.  Your entire company doesn't have to come grinding to a halt, which it did before.  But I bet you're all thinking, that's not what my company looks like.  My company looks like this.  I never have completely unrelated projects.  That is not my life.  So say you have this again, you've got your failed projects, you've got some new stuff  that's related, that's trying to test against it.  Anything that tries to test against something that's blocked gets blocked.  That's the simplest way to put it.  So this means that if you have a union failure, you can ship completely unrelated things.  But you want to get on that union failure as quickly as you can because it's going to  grow like an amoeba consuming the universe until things that you would never expect are  getting blocked.  And you're probably wondering, why the heck would you do that?  Why is it this all-consuming blockadness?  And it's actually pretty simple.  So this changed, which broke the red one.  And then we tested those two green ones, and they're test-passed, but they tested against  that red one.  They tested against a version that's not safe to ship.  And we don't actually know how they would have tested against the version that's already  in rehearsal and already delivered.  It might break horribly against the version that's further along in the pipeline.  So we can't ship them until we have a chance to test them against a version that's actually  shipable.  So that whole freaking thing is blocked until you fix it.  Sorry.  We did what we can.  There's not magic, right?  So yes, fix your union fast.  Otherwise, people are going to get sad, and it's going to get confusing.  If you see that yellow square, if you go to the dashboard, you'll see what's broken in  union.  So you probably want this magic, right?  This sounds pretty cool.  You already have it.  If you're using a delivery that's less than six months old and you're using delivery truck,  you already have all this functionality.  All you have to do is go modify your config.json to add the dependencies array.  Add all you have to do, and you get all this power.  If you don't remember what I said, there's documentation that says it all, though possibly  with less giggling.  So here's the summary.  We're talking about API-level dependencies.  We don't mean compile time.  That's a completely different kettle of fish.  We mean cross-project at runtime.  You need to use delivery truck.  In particular, you need to use the provision phase.  If you don't, or if you use a really old version of delivery truck that you hacked for your  company, you're going to be sad because very old versions of delivery truck just promote  everything as a block, and your safety is gone.  So don't do that.  Use one that's less than six months old.  Keep union healthy because it's going to become a raging amoeba and block everything.  And that's where the docs are.  What questions do you all have?  Okay, so you're saying you have an application and a...  So you're saying you have a cookbook and you have an application, and you need the cookbook  to be updated before the application?  Sure.  Sure.  So if you have a dependency...  It's kind of long, can we hand it over here?  So basically, my understanding of your question is you have a cookbook and you have an application,  and they have to be in tight secrecy, right?  They could almost be in the same code repo, but you've decided to make them separate projects,  but they're really tied together, and they have to move in lockstep.  In this instance, yes.  So that's the case.  They basically have a dependency on each other, and there's actually nothing against putting  circular dependencies in, so you can just make it so whenever one of them changes, it  will run the test for the other one.  That'll break union until you get the change for the other one out there.  But if the cookbook can't deploy the application without its change, how will it get through  acceptance?  So you've...  How do you get them through acceptance now?  I'd rather not say.  Okay.  Why are they separate projects?  Because that cookbook is shared amongst a lot of...  It's the generic JBoss cookbook, and just this application needs a change to that to  be able to deploy.  And why can't you update the cookbook first?  Yeah, I think you can.  So yeah, just update the cookbook first, and then your project can't get through acceptance  anyway, you said.  So you don't even need to set up a formal dependency relationship.  What other questions do you have?  This is a ton, and I purposefully left a lot of time for questions because there are so  many freaking directions people can go in with this.  So if I've been using delivery a while...  Hold it close to your mouth.  If I've been using delivery for a while, and I've got a lot of projects not doing dependency  management, if I turn it on on some, what happens with all the other projects?  Sure, they keep acting the way they are.  Well, so back in January, when you updated delivery truck, something subtle happened.  It used to be that no matter what, all projects would be updated at once.  What happened instead is only successful projects would get promoted at once.  So what I mean by that is say you have a project foo that's broken in union.  A year ago, if you're using an ancient version of delivery truck, what would happen is when  you shipped bar to union, if it passed its test, foo and bar would go down the pipeline,  and your broken foo would go out, and you would be a very sad panda.  And this last winner, what will happen is foo will stay there, and bar will happily  go through the pipeline, but foo will stay in union and will not get promoted through  until it's fixed.  So that's the current state of the world before you add your dependencies in.  As you add dependencies in, it just increases the set of things that will get stuck in union.  But everything else is independent and can flow through.  Actually the assumption right now is all your projects are completely independent.  You've got one behind you.  So I'm fairly new to delivery.  I do have a question in your example where you had the two green ones that were depending  on the red one, and it kind of stopped everything, right?  So my question is...  This one?  Yeah, yeah.  So if the two one...  If the red one, the version of the red one in production is still valid, is there a way  for me to test those two green ones in this current state against the production version,  and if that passes, I can push those through?  Nope.  The kind of the fundamental vision inside of delivery is that you roll forward.  We don't really give a way to roll back.  If you decide that you can't fix that red one reasonably, the thing to do is to push  an older version through the pipeline, and then that'll unblock your pipeline again.  Right.  In that case, it will be the version that's already in production.  Yeah.  Yeah.  So if you can push one through, that'll make everything work.  That works.  But no, we don't have any way to say ignore this particular project and roll back without  putting a change through.  Okay, it makes sense.  Thank you.  Yep.  Keeps things simpler.  Chris?  So if I have some really terrible looking code that does my version stuff today, that  example that you gave, does it allow me to just basically set the project name, the version  number, and then just pass it in an arbitrary hash of things that I want to know about later?  Yep.  Oh, awesome.  So you can give it an arbitrary list of attributes.  Wow.  That's like 30 lines of code that just went away.  Yay.  Any other questions?  Cool.  So that's what I had put together.  I wanted to make sure there's a lot of questions.  I'm going to be out front if people have additional conversations they want to have.  Cool.  Thank you, Josh.  Thank you.  Thank you.  We'll back up in session.  Thanks for joining us.  Yeah.  Thanks,生애들.
Delivery_Dependency_Support_0_131.png Delivery_Dependency_Support_132_515.png Delivery_Dependency_Support_516_755.png Delivery_Dependency_Support_756_1043.png Delivery_Dependency_Support_1044_4259.png Delivery_Dependency_Support_4260_4439.png Delivery_Dependency_Support_4440_5003.png Delivery_Dependency_Support_5004_8207.png Delivery_Dependency_Support_8208_9479.png Delivery_Dependency_Support_9480_10319.png Delivery_Dependency_Support_10320_10475.png Delivery_Dependency_Support_10476_11771.png Delivery_Dependency_Support_11772_12263.png Delivery_Dependency_Support_12264_12779.png Delivery_Dependency_Support_12780_12995.png Delivery_Dependency_Support_12996_14483.png Delivery_Dependency_Support_14484_15815.png Delivery_Dependency_Support_15816_16583.png Delivery_Dependency_Support_16584_17471.png Delivery_Dependency_Support_17472_17675.png Delivery_Dependency_Support_17676_17915.png Delivery_Dependency_Support_17916_19799.png Delivery_Dependency_Support_19800_20159.png Delivery_Dependency_Support_20160_20831.png Delivery_Dependency_Support_20832_21107.png Delivery_Dependency_Support_21108_22259.png Delivery_Dependency_Support_22260_29555.png Delivery_Dependency_Support_29556_29603.png Delivery_Dependency_Support_29604_31739.png Delivery_Dependency_Support_31740_31787.png Delivery_Dependency_Support_31788_32764.png
So, as Nell said, my name is Jess Mink. I've been a tech lead on workflow, aka delivery, and we're going to talk about dependencies. So if you're not here to talk about dependencies, you are in the wrong talk. I will not be offended if you leave. But if you are, welcome! Thank you for coming. So let's step back. Why does workflow, why does delivery, why does that product exist? What are we trying to accomplish? We've got all these freaking stages. We do all these things. We run unit tests, we run lint, syntax. We make humans interact with it and make sure it's the right thing. What are we trying to accomplish? We're trying to make sure it doesn't break production. That's the point of this whole thing, right? We go through all these hoops to make sure that our changes are safe to ship, that we're not scared to push them to production. So all the things I just talked about are for one single project, right? You might get lucky. You might catch cross-project dependencies in acceptance. But in general, all of our tests are targeted around one particular project and not how projects interact with each other. And the reality of our ecosystem, right, is that so many of our really interesting bugs are where different pieces of code hit up against each other. Because that's where team boundaries are, that's where people are thinking about things differently. So when we talk about dependencies, there's a couple different types of dependencies, right? So one type of dependency people mean are library dependencies, right? But that's not what we're talking about here. You're going to catch those at build time. When you go and build your project as a second stage, you're going to catch your build time dependencies. Your thing will fail to build, so that's not very interesting. What I'm here to talk about is API level dependencies. So your project exposes some type of interface that another project, another application, is consuming. So the example I'm going to use here today is a tiny URL server. So we've got an API where you give it a URL and it gives you a little summary, right, or vice versa, and a UI to make it easier to deal with. So clearly they're interacting via an API. They're built, they're deployed, and then they interact. So let's say one day your product person comes to you and they're like, dude, your API, this design sucks. It's not restful at all. I need you to go back and make it restful. So you do. You update all the APIs. And then while you're at it, you update the UI to, you know, talk to the new APIs so that you don't break everything. But you didn't pay attention. The API gets to production first. So we have all these tests. We did all these things. How do we avoid this type of failure, right? And like you can tell your product person, no, you have to check every single page of every single thing in acceptance, but that just doesn't scale well, right? We're in the business of automating things, not making people's lives miserable. So what else can we do to help with this? So in terms of thinking about this, let's go back and look at all the stages in delivery and talk about what they're for, because that'll tell us where we need to change things. So we have verify, right? This is, is your code reasonable, right? Like, are you just throwing bugs in there? Does your code look awful? Does it make me cry, right? Do we want to take it into our code base? Is it going to get merged to get? So that's what that's about. Build, build time dependencies, right? Does the thing build? Can we use it? We've already accepted it, but like, let's make sure it can build. Then we get to acceptance. That's where we bring in our product people. Did you build the right freaking thing? Does it look really ugly because we're engineers and we don't always know about UI, right? This is where we bring the rest of the company in and they mess with what we have and make sure it's what we want to ship out to production. This is also an interesting place because it's the first time your project is dealing with its dependencies, right? It's runtime dependencies and API dependencies because we've taken all those from Union and pulled them over because if you're playing with that tiny URL, UI, right, you need the API to try it out. But when you get to Union is when life gets really interesting because you flip everything on its head. Suddenly that's when everyone else has to deal with you. So this is where we should be finding those API level incompatibilities. And historically you didn't have any way to do that, right? You got to Union, you ran your projects, smoke and functional tests, but if you just changed the API, you might not even know what UIs are relating to you, right? In the tiny URL example, sure. But in a real organization, do you really always know who all is depending on you, who all your consumers are? Are you going to bet me that you didn't ever forget one that no one put a dependency on your project you didn't know about? It doesn't happen, right? So we need some way to automate that. And then rehearsal, we're rerunning the tests from Union to make sure that they still work in a clean environment because Union may have had breakages that we fixed and delivered as your production environment. So as I alluded to, you want a way to programmatically declare your dependencies, your runtime dependencies. So here we've got an example. The top there is the code in the config.json that will actually make the UI depend on the API. It's that bottom line. It's pretty darn simple. And when you do that, when that change gets to Union, because Union is where we have to interact with other projects, we actually update the workflow UI. So it'll show your dependencies and who depends on you, which is cool, right? A new person on your project can go and be like, hey, look, this is the web. This is where that thing is happening. I understand now how these projects interact. So that has some value, but that still doesn't keep you from breaking production. So this is what keeps you from breaking production. Because what we do is we're actually running the tests. This is the API running, and we're running the UI tests because it has a dependency on us. Now in Union, we're going to run the tests of every single project that has a dependency on us. And that's how we're going to know we don't break things, right? This broke in the tests before it made it to production. Yes, that's what we want. So now we'll go and ship the UI, right? We can fix it. That's weird. You've probably never seen that before. The button is orange. Why is the button orange? The button is orange because things are broke, right? Your Union environment is very sad right now. And it's not just sad in general. It's sad in ways that relate to this project. So please don't be shipping changes if it's not going to make this better, right? Don't pile on to the problem. That's what that orange button means. It means things are broken. Let's go fix them. But in this case, we're fixing them, right? We're shipping that change we thought about. Same thing happens in acceptance. You get two warnings. Okay. And now we're in Union. We ran our tests. They passed. We had a bug. We caught it in our tests. We're good. So we're done, right? Everyone knows what to do, right? You just put that line in your config.json. All good. We can go home, right? No questions? Yeah, I didn't think so. So here I'm talking about delivery controlling promotion. And those of you who've used delivery a lot or workflow a lot are probably being like, hey, it's kind of? How does it do that? I wrote my deploy cookbook. I'm dealing with deploying my applications. And yeah, it's true. Delivery directly can control that orange button. But that just warns you, right? That's not actually controlling what goes out to production. So what's happening behind the scenes is delivery truck is actually managing a bunch of version pinnings for you. And this is a screenshot from Chef Server because that's where delivery truck puts them. Delivery truck, if you don't know, is a build cookbook that is recommended to be used as the basis for your build cookbook. So you can include it and you can include those recipes. And then you can add extra stuff in your recipes that you'd like. And in particular, it's the provision stage of delivery truck that does all this version management. So you really, really, really want to use delivery truck, the provision phase at the very least because that's how you get this. So you're probably being like, yeah, I heard about delivery truck. I mean, how many of you have heard of delivery truck and use it? Okay, cool. How many of you have heard that delivery truck is just for cookbooks? Ha-ha, it's not. So it also does applications. And it was a total pain in the butt before, but we made it easy. You just do that. You just put that in your published face and delivery truck will keep track of what applications and your version go with what project. And we actually store it in the override attributes. So if you need to be debugging, if you need to debug stuff, you can go into the override attributes and actually see what all the versions are. And of course, delivery truck can't automatically deploy your application, but you can query and pull these version numbers in to figure out what you want to deploy. And you can version your build artifacts, right? And that's how it all ties together. So there's more documentation about delivery truck here. I know that's a tiny URL, but you're not taking notes anyway. You're going to look at the slides later. Also, if you Google for Chef Delivery Truck Doc, it's the first hit. So in there, I talked about failed projects, right? And things being related to a failed project. And how you don't want things related to a failed project to promote. So you understand what I mean by promote now, but what do I mean by related to a failed project, right? The most obvious thing is, well, if it's a dependency or a consumer, if there's a dependency relationship with the failed project. But what does that really mean, right? If you just have this, sure, right? You've got your failed stuff, you've got your healthy stuff, the healthy stuff can keep shipping and will just hold the failed stuff back. And I really mean this, right? This will get stuck in union. And this will go out to rehearsal and delivered. Your union isn't a bottleneck, right? You can have a failed project in union and still ship other things that are unrelated. Your entire company doesn't have to come grinding to a halt, which it did before. But I bet you're all thinking, that's not what my company looks like. My company looks like this. I never have completely unrelated projects. That is not my life. So say you have this again, you've got your failed projects, you've got some new stuff that's related, that's trying to test against it. Anything that tries to test against something that's blocked gets blocked. That's the simplest way to put it. So this means that if you have a union failure, you can ship completely unrelated things. But you want to get on that union failure as quickly as you can because it's going to grow like an amoeba consuming the universe until things that you would never expect are getting blocked. And you're probably wondering, why the heck would you do that? Why is it this all-consuming blockadness? And it's actually pretty simple. So this changed, which broke the red one. And then we tested those two green ones, and they're test-passed, but they tested against that red one. They tested against a version that's not safe to ship. And we don't actually know how they would have tested against the version that's already in rehearsal and already delivered. It might break horribly against the version that's further along in the pipeline. So we can't ship them until we have a chance to test them against a version that's actually shipable. So that whole freaking thing is blocked until you fix it. Sorry. We did what we can. There's not magic, right? So yes, fix your union fast. Otherwise, people are going to get sad, and it's going to get confusing. If you see that yellow square, if you go to the dashboard, you'll see what's broken in union. So you probably want this magic, right? This sounds pretty cool. You already have it. If you're using a delivery that's less than six months old and you're using delivery truck, you already have all this functionality. All you have to do is go modify your config.json to add the dependencies array. Add all you have to do, and you get all this power. If you don't remember what I said, there's documentation that says it all, though possibly with less giggling. So here's the summary. We're talking about API-level dependencies. We don't mean compile time. That's a completely different kettle of fish. We mean cross-project at runtime. You need to use delivery truck. In particular, you need to use the provision phase. If you don't, or if you use a really old version of delivery truck that you hacked for your company, you're going to be sad because very old versions of delivery truck just promote everything as a block, and your safety is gone. So don't do that. Use one that's less than six months old. Keep union healthy because it's going to become a raging amoeba and block everything. And that's where the docs are. What questions do you all have? Okay, so you're saying you have an application and a... So you're saying you have a cookbook and you have an application, and you need the cookbook to be updated before the application? Sure. Sure. So if you have a dependency... It's kind of long, can we hand it over here? So basically, my understanding of your question is you have a cookbook and you have an application, and they have to be in tight secrecy, right? They could almost be in the same code repo, but you've decided to make them separate projects, but they're really tied together, and they have to move in lockstep. In this instance, yes. So that's the case. They basically have a dependency on each other, and there's actually nothing against putting circular dependencies in, so you can just make it so whenever one of them changes, it will run the test for the other one. That'll break union until you get the change for the other one out there. But if the cookbook can't deploy the application without its change, how will it get through acceptance? So you've... How do you get them through acceptance now? I'd rather not say. Okay. Why are they separate projects? Because that cookbook is shared amongst a lot of... It's the generic JBoss cookbook, and just this application needs a change to that to be able to deploy. And why can't you update the cookbook first? Yeah, I think you can. So yeah, just update the cookbook first, and then your project can't get through acceptance anyway, you said. So you don't even need to set up a formal dependency relationship. What other questions do you have? This is a ton, and I purposefully left a lot of time for questions because there are so many freaking directions people can go in with this. So if I've been using delivery a while... Hold it close to your mouth. If I've been using delivery for a while, and I've got a lot of projects not doing dependency management, if I turn it on on some, what happens with all the other projects? Sure, they keep acting the way they are. Well, so back in January, when you updated delivery truck, something subtle happened. It used to be that no matter what, all projects would be updated at once. What happened instead is only successful projects would get promoted at once. So what I mean by that is say you have a project foo that's broken in union. A year ago, if you're using an ancient version of delivery truck, what would happen is when you shipped bar to union, if it passed its test, foo and bar would go down the pipeline, and your broken foo would go out, and you would be a very sad panda. And this last winner, what will happen is foo will stay there, and bar will happily go through the pipeline, but foo will stay in union and will not get promoted through until it's fixed. So that's the current state of the world before you add your dependencies in. As you add dependencies in, it just increases the set of things that will get stuck in union. But everything else is independent and can flow through. Actually the assumption right now is all your projects are completely independent. You've got one behind you. So I'm fairly new to delivery. I do have a question in your example where you had the two green ones that were depending on the red one, and it kind of stopped everything, right? So my question is... This one? Yeah, yeah. So if the two one... If the red one, the version of the red one in production is still valid, is there a way for me to test those two green ones in this current state against the production version, and if that passes, I can push those through? Nope. The kind of the fundamental vision inside of delivery is that you roll forward. We don't really give a way to roll back. If you decide that you can't fix that red one reasonably, the thing to do is to push an older version through the pipeline, and then that'll unblock your pipeline again. Right. In that case, it will be the version that's already in production. Yeah. Yeah. So if you can push one through, that'll make everything work. That works. But no, we don't have any way to say ignore this particular project and roll back without putting a change through. Okay, it makes sense. Thank you. Yep. Keeps things simpler. Chris? So if I have some really terrible looking code that does my version stuff today, that example that you gave, does it allow me to just basically set the project name, the version number, and then just pass it in an arbitrary hash of things that I want to know about later? Yep. Oh, awesome. So you can give it an arbitrary list of attributes. Wow. That's like 30 lines of code that just went away. Yay. Any other questions? Cool. So that's what I had put together. I wanted to make sure there's a lot of questions. I'm going to be out front if people have additional conversations they want to have. Cool. Thank you, Josh. Thank you. Thank you. We'll back up in session. Thanks for joining us. Yeah. Thanks,生애들.
there's a couple different types of dependencies, delivery and talk about what they're for, because you really, really, really want to use delivery you need to debug stuff, you can go into the does that really mean, right? If you just have unrelated things. But you want to get on that