 Cool. OK, since it's a lightning talk, I'm going to just get started. Start on time. Hopefully I have time for questions at the end. I'm going to go kind of fast through most of my slides, but mostly the demos are the interesting part, because this is weird hackery with multi-buildpacks. So I'm told for I work at Pivotal. I usually work on concourse and some occasional cloud foundry stuff. But the origin of the stock, because I'm not on the buildpacks team at all, is really come from me playing around with Bosch and trying to get this little weird game called Dwarf Fortress running on Bosch. So then I needed to install this X window system to have graphical applications actually run in VMs on Bosch. So then I made a Bosch release for it, and I was like, cool, this is fun. And then the first issue that someone opened was, how do I get this running in CF? And I was like, oh, no, I don't know how I'll get any of that running in CF. Like make a build pack for it, I guess. And then CF Summit happened in Silicon Valley earlier, literally the day of that GitHub issue. And I was like, how would they add X11 to a build pack and use it? And then multi-buildpacks came out. And I was like, great. Now they don't need to fork some build pack and add all these dependencies into it. It's all great. So let's just review what build pack steps actually are and how build packs work. So there is the detect, the supply, and finalize, and release. This is a new thing they've split it up into to support multi-build packs. What we're really going to focus on, though, is what happens with multi-build packs? There's no direct step for these individual build packs to go through. So how do multi-build packs work? Well, now you can have multiple supply scripts run for multiple build packs, and then eventually you have the last build packs finalize and release, running for actually producing a droplet for your app. So this is the new CF push with multiple build packs. But why would I actually want these multiple supply scripts? Well, in the docs, it says the supply script provides dependencies for the app and runs for all build packs. So you can specify this array of build packs to your CF push command using the new support for it. Then you provide dependencies to your app. So I thought about, OK, what kind of dependencies would I want in an app? Maybe I want to make a build pack that has a bunch of images in it of Puppy's GIF images, exactly, because GIF images are great, and everyone should have a build pack to just throw GIFs into their app. So I'm just pushing with my Puppy build pack and using the static file build pack. And so it goes through, and you can see here in the logs, it's supplying Puppy's. It's got a little dog emoji there. Great. So once this actually runs, it's pushed my app. So I see in the logs, it's actually running the static file build pack and my Puppy build pack that just prints out supplying Puppy's. So now I have an app that has just a static file app. It's just an HTML page, and it loads some JavaScript and puts these Puppy images in there now that they've been supplied to my Droplet for my app. So this build pack is really just a bunch of images that get dumped into my application's build directory by this Puppy build pack supply script. So there's just one script inside of the bin. And oh, there's actually multiple, one that actually does anything. So this literally just dumps a bunch of images into my build directory, which you're actually not supposed to do, but don't worry about it. It's fine. This is a demo. It's called Hacks, whatever. But you might be sitting there like, OK, you've got GIFs, but why would you even do that and don't? But I think you can really replace any sufficiently advanced computing with GIF images. You can just think of all the things that you can now put into your application and provide to your application as a dependency using this new multi-build pack support. You don't need to go and somehow get the files in there using some other weird fork of this build pack. You can just use multi-build pack support to supply dependencies to the later build packs and to your application to eventually use when staging your application and deploying it. So they all get pulled into the Droplet. They get put into your build packs dependency directory. And then every build pack supply script can dump files into this dependency directory and dump files into the cache directory to be used by later build packs. But what about all this stuff that's going into my app now? I'm just dumping all these GIFs in there. Are they safe? What about malicious cats in my app that I don't want there? Well, the supply script can also observe the dependencies for the app and for other build packs. So I made another build pack. So I'm just pushing a really simple static file app again. But now I'm putting a cat in that images directory. And I'm going to push it, but I'm going to use my cat scan build pack as well. So it takes the three build packs now and runs their supply scripts. And the first one that's going to run is the supply script for the cat scan build pack. And staging's going to fail. And I'm like, oh, gee, what happened there? And then it's going to say, warning, malicious cats located. Now, again, this is super simple. It literally just looks for files named cat. It just uses find. But you can replace this very simple, very hacky example with any other kind of scanning for vulnerabilities, security faults, CVEs, anything that's wrong with the dependencies that not only your app is providing, but the build packs that run before it are providing. So this is really useful for providing more resiliency to the things that you're deploying and just giving you more abilities to control the droplet that gets created and control what actually gets into your app. So you can look at the app directory. You can also look at the other build packs dependencies. And so a build pack can then build off of what other build packs have supplied. Time check here. So my initial plan was to get x11 working by dumping all of this stuff into the dependency directory for some build pack that goes to app and downloads all of the x11 stuff. And it turns out that's super hard. So I was like, OK, I need to come up with a cool demo because this is multi-build pack hacks and I'm talking about weird hacky things to do with this stuff. So I was like, OK, what if I forget what I called this file? Ah, CF push and a CF push. Great. I kind of gave away the reveal here. So now I've made a CF build pack that has the CF CLI in it, which logs into CF. I provided some credentials inside of my application that just goes and registers a few environment variables for a following build pack to use. So it logs into CF using the CF build pack, a different cloud foundry. And then this is going too fast. So I'll just scroll up and go through the actual staging process here. So my CF build pack provides me the CF CLI and logs into run.pivotal.io, logs into my space. And then I have a CF push build pack that the staging for the supply script there will actually CF push another app that's inside of my application directory. So it looks into my app directory and CF pushes from there. So now the staging of my app involves CF pushing an entire other app. So this is another thing where you're like, why? Why are you doing this? What is wrong with you? And I'm like, why not? I have the technology. We have the technology. And this is the spirit of the talk. And I'm so bummed that I didn't get my cool demo of, if you looked at the program really closely for this talk, I was going to try and get all this stuff working. It was going to be so cool. But multi-build packs is a great addition to CF and to the ecosystem. And really what I'm getting at is everyone should go forth and really explore what you can do and explore the weird, crazy stuff that you can do with this. If I can put CF push inside of a build packs supply script, I think we can pretty much do anything now. That's it. Do we have time for questions or any questions? There's documentation on where did I find the resources for this? Understanding build packs? Yeah. There's a thing for understanding build packs that talks about the new build pack scripts. This is super small and not readable. But it basically talks about what the purpose of all these new scripts are. And if I go back in my slides, that's kind of where I got this slide about what all the different build pack steps are and what all the scripts are. Build packs kind of seem like this weird magical thing. But really it's just a set of four scripts that let you basically define all of the bits and files that get dumped into your application droplet and lets you dump files into this dependencies directory for your final build pack that runs in the new way of things to finalize and actually release and deploy your app. Cool, one more question? You mean the compile, I think it was? So actually what happens now if you try and CF push using the multi-build pack support with one that doesn't support it, it will fail? I'm sure Steven, Levine, and Kiti are better resources for talking about build pack stuff because they're actually on the build packs team. I can't speak to the desire to support that. But basically the split between these exists mostly to support this finer-grained ability to have multiple supply scripts putting their files into their own dependencies directory and just making sure that the contract is really clean there. And I think the one thing that's really key about this is that this feels like a first step. This feels like a step towards even greater things. So I think splitting them up and having it in a different format is almost giving us more. Yeah, the old build packs will still work if you aren't trying to multi-build pack deploy with them because it will try and find the supply script and I'll just be like, oh, there's no supply script, so I don't know what to do. And some of them also expect to be run as a finalized script so they are looking in different directories and doing other weird things that they shouldn't do. Yeah. Oh. OK. I was in the multi-build pack from the build pack team and I said, for the multi-build pack thing, in the old style, there's another multi-build pack doing that, which you seem to adopt a hierarchy style. Oh yeah, there's the multi-build pack build pack. Yeah. Yeah. Yeah, so in my examples, I was using the CFV3 push command and then you can specify any number of build packs on here. So the last one that you specify is the one that actually runs the final two steps there, the finalize and release. So yeah, so that's the last one is just like whatever the last one you provide to this command is the last one that it will actually run the supply script for. So because I didn't run any or the finalize script for, sorry, because I didn't write any other scripts other than the supply script for my custom build packs that I was using to dump CF into the dependencies and actually be able to use the CFCLI, I have to run these as the first steps because they don't have any of those scripts. So they'll actually just fail if I try and use them as the last build pack. So I'm just using the static file build pack, which just starts engine x and serves all my files. Yeah, so that's what's cool about this is even just the built-in default build packs that come with CF. You can use those to supply all the dependencies for running a Java build pack and a Go application so you can run those two together. So they provide all the dependencies for each of the build packs. There's a little bit of stuff you have to do to tell it, OK, the Java build pack knows to run a Java app. And there are specific things that it looks for to know what app to run. You need to also tell it how to run that Go app because the final script doesn't actually, like, the release script doesn't run until, like, the release script only runs for the final build pack as well. So it won't tell the runtime how to run the Go app unless you explicitly, like, kind of help it along and say, oh, I'm also supplying this other build pack that has the dependencies to run Go apps. Here, run this Go app. So you have to kind of change the run script that you provide when you're starting your application. But other than that, it just provides all the dependencies and installs Go for you. OK, I'm just pushing from the directory that contains my app. So for the static file app, I just have a static file file here and just the HTML. Just to indicate that this is a static file app. You could imagine that this is a Java app and I'm just CF pushing from this Java directory. But what you would want to supply CF push, there's a startup command. So you can either use a manifest to supply a startup command or you can use this dash C flag, which one you're pushing. You'll just tell it how to run your Java application and your Go application. Yeah, you could structure your source code like that. You could have, like, a kind of wrapping. Like the whole package. Yeah, you could push that from that whole application directory, yeah. That I don't know. I don't know whether there's plans for that. This is really just like a v3 push command right now. So it doesn't support manifest right now. I don't know whether there's plans for that yet. Again, the real built-back steam might not work. This is just my messin' around. I believe there's plans to be able to support that. Thanks, everyone. Thanks, everyone.