 All right. I think we can get started. Welcome, everyone. We're talking about Drush 9 today. This is the latest and greatest version of the Drush command line tool. My name is Moshe Weitzman. I'm a longtime Drupal developer, one of the maintainers of the Drush project. You can see that I'm an independent consultant available for hire on architecting big Drupal websites, specializing in developer workflows. And you can see that I'm also the maintainer of the DEVEL Contrib project. Right here, Greg Arenderson. He's going to be the other speaker today. Greg is the Pantheon platform engineer and open source engineer at Pantheon and three of the projects that he maintains are listed there. There are more, but those are three you might have heard of. So here's a quote from our founder, Arto Bendikin. He gave Drush its slogan. It's a veritable Swiss army knife designed to make life easier for those who hack at the command prompt. So I bet we have a lot of people in here who hack at the command prompt. And I hope you like our latest version of Drush. So Drush has been around for a long time. It's 11 years old. And Drush 9 is the first time we've done a ground up rewrite since Drush 3, I believe, the year 2008. So really, this is a monumental change. And we're really proud of where we've gotten to and what it is. And we hope you guys love it as much as we do. Some of the principles that guided the rewrite of Drush are listed there. It's object oriented. It's symphony based. It embraces the composer workflow. And it embraces Drupal 8. So there's been lots of change in PHP land since 2008. And Drush 9, I think, really brings us up to speed. Drush has always been a pleasure to use in that it does what you want with little fuss. But right now, we have a situation where authoring commands is a modern sort of activity, as well as all of the guts of Drush are object oriented and really nicely decoupled. So we have two main sections for the talk today. I'm going to be talking about using Drush 9. And primarily, Greg is going to be talking about all of the APIs underneath that make it do what it does. So getting started with Drush 9. There's typically two things that you have to do. You have to start your project. And by this, I mean your composer project. For the moment, I'm assuming you're starting completely fresh on a new project. The way you start fresh is you go to a specific GitHub repo called a Drupal-composer slash Drupal-project. And you follow the read me there, and that will give you all of it. It assembles your code base. For your Drupal-8 project. And in addition to a Drupal code base, it gives you the Drush command line tool right there in your project. The second thing you have to do is install a tool called Drush Launcher. This is a small composer-based tool that's distributed as a far, drush.far. You go ahead and put that in your path, anywhere in your path. And so when you type the word drush, the launcher fires up. And then that hands off control to the site local drush that came in with the Drupal-project. So just to re-emphasize, here's a screenshot of the Drupal-project's GitHub repo. Here's where you want to go to get started, OK? And just follow the read me instructions. Basically, there's one composer command you need to run called composer create project. And it will go ahead and get you started. You get a copy of Drupal in there. You get a copy of drush in there. You get a copy of Drupal console in there. So just about everything you might need for your project is right there. And then in order to be able to call drush from anywhere on your system, you need the drush launcher. So this is a screenshot of the drush launchers GitHub repo. Just follow its read me for how to get that installed. All you really have to do is grab the far, put it anywhere in your path, and you're good to go. If you need to update it later, it has a self-update function. So that's the process if you're starting a new project. If you already have, let's say, Drupal-8 site and you want to use drush9, your best bet is to make that into a composer-built project. That's really what drush expects. And to a sense, that's what Drupal expects to. Otherwise, you're going to have a really hard time managing your dependencies. So I just want to mention two projects that help you convert from a bare Drupal site to a composer-built one. MakeConvert is a command that's in drush8. If you are a drushmake fan, this command takes your drushmake file, loads it up, and emits equivalent composer.json. So with that, you're well on your way to having a composer-built project. And the next thing is a drushcomposer generate. That's a contrib project that you can check out with a drush command in it. And that will take a bare Drupal website, look at the modules and projects you're using, and create a composer.json for you. Saves you a little time. In general, your goal with either of these tools is to have a codebase that gets assembled by composer install. All the other ways of assembling your codebase, like drushdl, like drushmake, like grabbing tarballs and sticking them in directories, all of that is legacy at this point. You really want to be using composer. And of course, people ask, I don't want to. Why do I have to? I think the two-word answer is dependency management. More and more of the modules you want to use in your Drupal sites have dependencies. And they have dependencies on composer libraries that are not part of Drupal. Those libraries have other dependencies. And it gets to a point where you can't keep all your dependencies compatible with each other without using a tool like Composer. So for people who have been resisting it, I sympathize with you. I resisted it also in the very beginning. But there's a happier life on the other side. So please go ahead and embrace Composer and help out your friends in getting there. But there is no turning back on the Composer wave. Thanks. So I mentioned that Drush 9 is a huge rewrite. And there's a lot of changes, particularly under the hood. I want to emphasize that a lot of things haven't changed. And you can still run the commands you have been running. Drush pm-enable. Drush pm-uninstall. Unchanged, OK? Uli, rsync, SQL sync. It's all there. It has the same options it always has and works the way it did. The config commands. I mentioned their Drush at foo status. The at foo is a site alias. Those are used identically to how they always have been. Drush pml, pm-list is the long name. Dash-formin equals JSON. That's an example of an output formatter. Drush has had these since Drush 5 or so. They still exist in Drush 9. From the command line, they work exactly the same. And just one plug for the Drush topic command. The topic command has lots of documentation about how you do things in Drush. OK, so just run topic. You'll see about 20 different topics that we've written. If you read one a night, it only takes 20 nights. And I encourage you to do that. So some things have changed in Drush 9. And I want to call out the dearly departed for things that you can't do anymore. Drush make is gone. The archive commands are gone. And the quickDrupal command is gone. pm-update and pm-download are gone. So these were good friends to a lot of us. And I thank them for their service. But they are deprecated and gone right now. One little note. People may have been used to using dash n to mean no. It doesn't mean no in Drush 9. It means non-interactive, which really means accept the defaults. So please don't keep that habit if you are using dash dash no. A ton or five tons of procedural code is gone in Drush 9 to be replaced by shiny new object oriented code. Drush 8 and prior versions supported multiple versions of Drupal in one Drush. That is no longer supported. So you'll notice that Drush 9 only supports Drush 8 and doesn't support the prior, sorry. Drush 9 only supports Drupal 8 and doesn't support Drupal 7 and Drupal 6. If you are still running Drupal 7 and Drupal 6 sites, I encourage you to keep on using the Drush 8 the branch. And that will stay maintained for a long time. And why did we lose all of this dearly departed stuff? Because there's only a few people maintaining Drush. And it got too big to maintain this like multiple version thing and lots of procedural code that was calling into Drupal 8's OO code. It really became a bear to maintain. And so we went ahead and overhauled it. I think it's going to be more pleasurable for the maintainers to work with and more pleasurable for the people who are authoring Drush commands to work with. There are a few things that have left Drush 9, but we think they're going to come back soon, either in 9.0 or 9.1. Shell aliases, the site set command, and bash completion are things that we had in prior versions and we don't have right now. They're pretty ancillary features of Drush, so I don't think anyone's going to cry too many tears. But hopefully they'll come back soon. We did pick up some new tricks in this version, and I want to make sure people know about them. The first one is the config split project. So config split is a project you can put in your composer file. And once you have it, you gain some real super powers with respect to the Drupal 8 configuration management system. Specifically, the main use case is if you have a dev environment and a stage and a prod environment, you can have different configuration in each environment, but they don't interfere with each other. They don't cause differences when you are trying to do imports. So you can have your develop module and other debug modules installed in development, but they will not be enabled in your prod environment. So essentially, you're maintaining different config.extension.yml files in different directories, and config split knows how to put it together before a config import happens. So config split is a different project from Drush. If you have a need for this, just go ahead and add it to your composer, Jason. And it takes over the services it needs to in order to achieve that feature. In Drush 8, you had trouble running commands from your composer root. You had to CD into Drupal's doc root and run commands from there, or use site aliases, and then maybe go back up a level in order to do composer operations. That's been cleaned up, so now you can run Drush just from the composer root, and you don't have to CD back and forth all the time. It's a small thing, but it really is a bigger convenience to do it that way. Config files and alias files are now YAML instead of PHP, which is nice. There's still an alter hook if you want to go ahead and make changes dynamically. And Drush Generate is a new command that we added in Drush 9. And I'm going to talk about that and give a demo now, since it's a pretty big piece of new functionality. OK, so Drush Generate is a scaffolding tool. It generates code. I have some examples here of commands that it understands. The alias is GEN, GEN. So Drush GEN module standard, you'll see that in a second. That builds a whole new module for you, and some of the introductory pieces that you usually have to build. It goes ahead and puts those in your module. If you're trying to create a new content entity, this is going to be a really fast, convenient way to do it, Drush GEN content entity. Drush GEN DCF, that's short for Drush Command File. So naturally, if you're trying to write new Drush integration for your module, this is the fastest way to do it. Use the Drush Generator for it. If you are writing contrib modules, you can add generators. Those are command files. You can look at Drush's documentation for how to do that. And just want to give a shout out to a composer project called Drupal Code Generator. Drupal Code Generator is the smarts and muscles behind this feature. This is something we bring in via Composer. It's a library that's maintained by Cheetech, and Drush really does a thin wrapper around it. So we are able to quickly add a lot of awesome generator functionality without maintaining that within Drush proper. So that was really a huge win. We're going to talk about Drush APIs in just a second. First, I want to demo the generator stuff. OK, so can you guys see that OK? Saw a couple of nods. I ran the command SUT gen module-standard. Now, you can see that I'm running SUT and not the word Drush there. Please don't focus on that too much. SUT is a useful alias for us to run commands in another Drupal site. It's like a site alias. So imagine the word Drush is there instead of SUT. We're using the new generate command, and we're passing the argument module-standard. It asks me what module name I want to create, what's the machine name, the description, the package, the dependencies, and now what features of modules do I want in this initial creation of the module? You can see I want a libraries file, permissions file, event subscriber, controller, settings form, boom. So what we have now is that Drush Generate has told me that it has gone ahead and created a whole bunch of files in the modules pastry directory. So I did it. I knew I would do that. The in command is still available and works as it always has. Actually, it works better than it always has. Both Ian and Uninstall used to prompt you. Do you really want to enable? And do you really want to uninstall? They no longer do that unless there are additional things that it needs to tell you about. So if you're trying to uninstall something that depends on C tools, and you didn't mention C tools, before it uninstalls C tools, it will say you're going to install X and C tools. Is that OK? But it won't prompt you if you gave it the permission already to uninstall what you're doing. Same thing with enable. So I now have a pastry module. I've enabled it. If I want to add to it, let's say I want to add some menu links. You can see there's autocomplete there on the module names. Generate asks, well, what module do you want to put the new menu links in? And I say the pastry module. It went ahead and created the pastry.links.menu.yml. So I want to show you all the things that Generate can do. They take more than a screen's worth of stuff. Here we go. Three different kinds of forms. JavaScript file, configuration entity, content entity, plugin managers, lots of different plugins, access checker services, breadcrumb builder services, route subscribers, twig extensions, templates, browser-based tests, kernel-based tests, themes, and lots of different kinds of YML files, routing, services, et cetera. So there's already a ton of stuff that Generate can do while you're building a module. So really encourage you guys to use the new Generate. If you find something missing or you find something broken, encourage you to look up the Drupal code generator and submit your new templates there for what can be generated. If it's something specific to your module, go ahead and put it in your module. Let's just look at the code that got generated. OK, so this is pastry.info.yml. That's not particularly interesting. Here we have libraries, pastry.libraries. This is ready to be customized by you for whatever your module needs. You remember, we did menu links. There's a child link and a dynamic link and external links. So there's lots of great starter code here, so you don't have to remember and look up how everything works. Permissions and their keys are all there. Routes and the different ways those work are ready for you to customize here. So that's what generating a module looks like and adding new things to a module. So really excited about this new functionality in Drush 9. OK, so moving into Drush APIs, the format for authoring commands has changed pretty dramatically. You'll recall that in prior versions of Drush, you had something like Ctools.drush.inc in your module called Ctools. And inside that file was a hook drush command, ctools underscore drush underscore command, with an array that defined your command and then a function in there, which was the command callback. That's a little bit different now. We've moved to object-oriented, so we have classes. Those classes can have their dependencies injected, and those classes are referred to by tagged services. So this is very much the symphony Drupal 8 model for how you create commands. In addition to commands, there's lots of drush hooks, which is the mechanism for hooking into other commands on your system. Those also are annotated methods in a class. And I'll give you examples of these now. And just a note for contrib authors who already have Drush integration, you can keep your Drush 8 code the way it is. For people who are running Drush 8, they'll be running that code. For people who are running Drush 9, you'll want to create a class just like what I'm going to show you. Sorry for this delay. I'll start talking about the classes. OK, so I'm going to show you image commands.php. That's a class from core Drush 9. And in it, you will see that it extends a class called Drush Commands. So Drush Commands is a base class that all your Drush commands are going to extend. Risky, OK, good. All right, class image commands. Here's the namespace for it. It extends Drush commands. Then all you have to do is make one method in your class. Here we have the flush method. It takes an argument called style names and an argument called options. Options is something that you always put at the end of your argument list for your method. And in this case, there's only one additional argument here. So the way you tell Drush what arguments and options are available for your command is just by documenting it with annotations. So it's very annotation-based, sort of like Drupal content entities or Drupal plugins or PHP unit tests, annotation-centric. So here's the command description at the top. The command name comes in with an at command annotation. The argument style names and its description is declared here. There is one option for this flush command called all. And there is its description. Here we have six lines that all are example usages. So Drush help shows you examples for how to use it. So definitely encourage you to use the at usage annotation. And moving along, there's two special annotations that are used by this command here. Validate entity load and validate module load. There are hooks that look for this annotation on any command. And if present, they go ahead and run their custom code. In this case, validate module enabled, image as a parameter, this command will fail to run if the image module is not enabled. So that's a good way to avoid bad exceptions for the user if they try to run this command without the image module. Image styles are the things that are getting flushed. Of course, they depend on image module, so that would be an appropriate annotation. And a similar one, we want to make sure that the image style content entity is still present. So that's what that other annotation is about. The at aliases annotation, put as many aliases as you want. Here we have IF is the short version. Image dash flush is the sort of prior version of Drush. Use dashes. So all of the prior names are in here as aliases. So your muscle memory will still work if you do PM dash enable or image dash flush. The canonical name has changed to image colon enable and PM colon enable, or image dash flush rather. And then just the body of the method is the work that you need to do in your command. A little bit more about hooks. Hooks are annotated methods also. Here we have a hook that wants to interact with you before the command callback is or the flush method is called. And it wants to operate on just the image flush command and not lots of image commands or all commands. And here it's just going to prompt you for which of the many image styles do you want to flush. So if you didn't specify, you get this interaction. All right, I'm going to hand it over to Greg now. Vienna, thank you. My mic is on, so I'll give you my welcome again. Welcome to Vienna. I'm glad you could come and join us in the session today. So most gave you a great overview of what we're doing in Drupal 9. And I'm going to dive down a little bit into the internals and talk about what's inside of Drush and how you use it. So at the top of this hierarchy, we have the Drush application itself. And Drush adds facilities such as bootstrapping Drupal site aliases that allow you to easily select which site you want to operate on and remote execution. And on top of this, we're building on a project called Robo, which is a task executor for PHP. If you haven't seen Robo before, I'd suggest you check it out. It's very useful for building continuous integration and other sorts of build tools. It allows you to build tasks with a lot of different building blocks that you can put in collections. And it does nifty things. A lot of the features that we had in Drush historically, we pushed down into Robo. So they're generically available. And Robo has a facility where you can use Robo as a framework and really quickly make your own symphony-based command that has all of the capabilities of Drush, included quick command generation with annotated commands and all of the things you see below the stack. So this is brought into Robo in the consolidation suite of libraries, which provides annotated command support, output formatting, and some nifty configuration facilities that I'll show you later. And of course, all of this is built on top of the symphony framework. We're not any different than symphony. These are ways to build actual symphony commands. And if you're used to using symphony console, you'll find that those APIs are available to the commands you build. So I want to take a quick diversion and talk about the two-autoloader problem. This is a problem that not a lot of people are going to encounter unless you're writing a command-line tool such as Drush or Drupal Console. And the problem you have is your primary application, the one that enters. It has the real front controller in this example, Drush, has to bootstrap another application, Drupal. And Drupal has its own auto-loader. So if you have two auto-loaders, two different sets of classes, you have to make sure if those are going to operate together, that they have exactly the same version of classes. And this diagram shows that Sember compatibility is not sufficient for two different auto-loaders to work together. And the reason is, if you have some fancy library and one application has version 1.0.1 installed and the other has version 1.0.2 installed, it's just gone up one patch version. It's entirely possible that this dependent library may have changed its implementation slightly. In the example here, we have a class called sub that extends a class called base. And there's a function foo. And inside the function foo, it formerly called the protected method in the base class called bar. But someone decided that bar wasn't a great name, and they renamed it to baz, or baz, or whatever they wanted to call it. And if you're using these classes together, Sember hasn't changed at all. The API is exactly the same. Both of these different versions work equivalently. If you have two auto-loaders, though, PHP is kind of indiscriminate about where it gets its files from, well, it's not quite true. The auto-loaders are hierarchical, and it will load them in order. But if you only load half of one library, like, say, you take in the base class because you've called some command, and then you load another auto-loader on top of that, so you end up with your subclass from version 102 and the base class from version 101, it's going to try and call a method that doesn't exist in the base class. And this is really annoying to try to debug. And the reason I wanted to go into some depth about describing why we have this problem is in the Drupal community right now, we have a lot of people talking about why don't we just keep the global drush? Why don't we go back to the island and not have to have the dependency resolution? And it's this sort of problem that can create really difficult to manage situations. They're hard to resolve, so I want to make sure everyone understands the background there. So as Moshe said, we are very firmly in the camp of saying you have to move forward for Composer because if you have a Drupal module that requires dependencies, we don't have a good alternative on how to do resolution of those dependencies. And the more of these modules that appear, the more of a problem this is going to be. So if you're not using Composer, your Drupal boat is taking on water and you have to either bail or go back to the island. And we're saying that going back to the island isn't the right solution. We're going to try and bail and get into a new boat that floats. But in the meantime, we still have a lot of people using global drush. And the global drush isn't really supported for all of the reasons that I just mentioned, but we're going to try and keep your boat afloat for a little while while you're bailing because it's taking some people a little while to get onto the Composer boat. So the Drush pre-flight takes some pains to try and make sure that this process does not immediately catch fire if you're still trying to use the global drush. And I'm going to describe how this works today in Drush 9. And we're hoping to get this same mechanism backported to Drush 8 shortly so that people who are still using PM Download for now will have more of a chance of being able to interoperate with Drupal 8.4 when it comes out in just a couple of short weeks. So the stages of the Drush pre-flight starts with pre-processing the arguments. We need to do this because symphony doesn't understand site aliases, so we bring those out and then prepare a pristine set of environments that we're going to pass on to symphony later. Then we load all of our configuration and aliases, and this has to happen right up front because the configuration and aliases are going to determine which site you're operating on, which is what happens in the next step. We look at the config and the aliases, identify our Drupal route. Then once we know which Drupal route we're definitely operating on, we load the Drupal Auto Lodo right up front. And in the past, this wouldn't happen until later in Bootstrap, which gave you a much greater chance that you would load some base classes that later a Drive class might cause a conflict. Finally, we do our dependency injection, which brings all of our classes online once we already have the Drupal Auto Loder loaded, and then we hand off to symphony with an application run, and from there, various hooks are going to come in to bring your site up and make it usable so these magical Drush commands will actually do what they're supposed to. So in this list, steps one through five is what we call the preflight, and then six and seven is what we call the Bootstrap and Execution. So in the early phases, Drush goes to some panes to only use a limited number of classes in the preflight. And in this diagram here on the very left, it says that we're identifying the Drupal site. So we've loaded the Drush Auto Load file, and all of the Drush sources in that green box are now available and loaded. These are unique, they can't conflict with Drupal. All of the Drush vendor is available through the Auto Loder, but only some of the classes that we need get loaded. Then we proceed to the next step, and we load the Drupal Auto Loder. At this point, the Drupal sources and the Drupal vendor are available, but not all of them have been loaded. Anything in the Drush vendor directory at this time that also exists in the Drupal vendor directory is going to be masked and you won't load it ever at all, which is good. So the Drupal version is going to take precedence. If a module is expecting a certain version of a class, it's gonna get that version of the class. And finally, we Bootstrap Drupal, and you can see the little red box is still there. Anything we loaded really early on is still going to be active in the runtime, but everything else is going to come from Drupal and the Drupal dependencies. Now, if you're running Drush and Drupal as the same application with the site local Drush, then the dotted line around those two vendor directories indicates that those two vendor directories will be the same thing. Composer will resolve Drush's dependencies together with Drupals, and everything will come out right and which is what we recommend. But if you're still bailing, then you'll find that Drush 9 is gonna work a lot better and shortly Drush 8 will have that same improvement. This has been a big issue in the issue queue about the problems with Drupal 8.4 and Drush 8, and we've been working hard to try and keep that better for the 60% of you who are still using the PM commands. We're here to tell you your time is limited, but we're gonna give you a little more time to get on the other boat. So once we call application run, Symphony is going to take over and start doing stuff. And the first thing that Symphony does is it runs the command event, which prepares the command to run. And then once the command has been prepared, it goes into hook in it where the command itself has an opportunity to initialize its variables. And then we step into hook interact, which Mush showed you later earlier, which gives you a chance to prompt the user and fill in any arguments that they didn't pass in on the command line. We have no control over Symphony's validation of args and options. It just does the right thing and throws an exception if you passed in some arguments that weren't correct. And then we continue along to hook validate where your application can take a look at what options were provided and figure out if the command can run or not. And those validate annotations that Mush showed, those happen as part of the hook validate stage. Finally, the command execution happens where you do the needful. And after that, if your command returns a set of a rowable collection, then robo is going to be hooked in as well and it'll run all of your tasks for you. And finally, the final result of the execution is going to be passed to the output formatters, which are going to display and render the information for you. So during the command event hook, the alter options hook will run and this is where output formatters has a chance to hook in. And output formatters will take a look at your command and says, aha, you do output formatting with tables. So I'm going to add, the output formatters is going to add additional options where you can select the fields and anything that's needed. So if you wanna hook in and add new behavior across multiple commands, the options can be injected for you. You don't have to keep adding them to every command that does output formatters or whatever other aspect oriented hook you might have placed in there. The next thing that's going to happen in the command event hook is configuration injection. And I'll show you that a little bit later. We have a cool configuration component, which is consolidation config. It's been extracted from Drush and is used in Drupal and a number of other applications. If you are familiar with Grasmesh's BLT tool, he is using Robo and Robo configuration to configure his build tool. And so with this application, you can have a YAML file with configuration and the configuration is pulled out and injected into your options. If you have the same option on the command line, it'll override what comes from configuration. In the init hook, Drush adds a couple of default operations that will happen for you before your command execution starts. The first is the redispatch hook. This is the part that detects whether your alias is a remote command or not. And if it is, it'll redispatch to the remote machine. Otherwise, execution continues and the bootstrap hook brings Drush up to the right level of bootstrap. So every command doesn't have to have a full bootstrap. It just bootstraps to the level that it needs for the APIs that it needs to operate. So if you have a lightweight command that doesn't call all of the APIs and just needs the database, it can run a little faster. So this is all stuff that Drush has done since version one or two brought forward to the object-oriented symphony world. This shows you a very simple example program. It shows a command called try formatters. And if you take a look at the output data there, what it's returning is a very simple array of arrays. And every row of the top level array has a collection of fields, and every row has the same set of field keys in it. Now, up at the top, there's an annotation called field labels. And there's a mapping in the field labels from the machine name, which is for second and third, to the human readable name for that field, which in this case is given as Roman numerals one, two, and three. And then at the end, all you do is take this data and return it. You wrap it in a data class called rows of fields, which is really no more than a marker class that says that this array can be displayed in rows and columns. Because if you had a big array that was just like a nested YAML structure, you couldn't show that in a table. So based on the fact that you've returned this marker class, the output formatter is going to inject into your command help that says these are the formats that I know I can format tables into and make those available through the dash dash format equals table or dash dash format equals YAML. And the nifty thing about that is later someone comes and adds a formatter and injects the formatter into your application, then that new formatter is available to all of your commands. You didn't even have to know about it. Your users can start using it. So on this screen, you can see on the left, we've got an example of what that data looks like when you format it as a table. It's a symphony console table output. And on the right, you can see if we specify format equals YAML, it shows it with the machine names instead. In addition to selecting what format you want, you can also select which fields you want from any fieldable output. And on the left, you can say we've selected fields three and one. And so not only have we cut out field two, but we've also reordered the fields. And on the right, we've done the same operation, but we're also specifying that we want the output in JSON. So we've trimmed out the rows we don't want, converted it into JSON, and this kind of manipulation will make your life a lot easier if you're using Drush in some sort of tool suite where you want to pipe the input into some other command, various commands, like different formats of data better than others. And it's super useful to have output formatters because you don't have to deal with that as a command writer. You get all of the power without any of the overhead, without having to write the overhead. So as Moshe mentioned earlier, we've switched our config. In the past, we had drushrc.php, and you could just write any old PHP you wanted. If you wanted a command-specific option, you would put it inside of a well-known variable called command-specific, and that would all get parsed by Drush. But now we have the equivalent in YAML in the command element. There's a site install namespace. So this is for the site install command. The options for site install of account name and account pass are specified here, and the config module is going to take this configuration and inject it into your command line options, as I mentioned before. Now, you'll notice that site install, it appears on two different lines. It's not listed just as site install, and there's a couple reasons for that. One is the pragmatic reason that site colon install, well, colon is the separator for maps in YAML, and you could escape that, but that would be ugly. So for one, it reads a little bit better by splitting it up into the two different lines. The other is there's actually some facility here in that immediately under the site element, if you list options there, then the configuration under command site options will apply to all of the commands in the site space. So if you have common options amongst one group of commands, you can separate it that way, or you can have configuration just for your specific commands. Aliases are config and they look a lot like a config file. In the past, we had aliases drushrc.php, and you could do anything you wanted in these files. You could define a bunch of different aliases, and your alias names were usually separated by dots, and the different components didn't mean anything. In Drush 9, we've become a lot more opinionated. If you have a file called example.alias.yaml, this represents a single site called example, and that single site always has multiple environments. In this case, we're showing a dev environment and a live environment, and you can't do anything with this site other than have the multiple environments of the example command. In addition to example alias.yaml, we also have group aliases.yaml, and in this case, you have a group of different sites that all have some relationship to each other, and each of these different sites always must have one or more environments, and so there's just an extra level of nesting in your yaml configuration. Finally, Drush 9 has a very robust new set of unit tests and functional tests, and these tests are actually pretty much the same tests as we had before, but they were massively rewritten for the massive rewrite of the architecture that we redid in Drush, and the Unish functional tests create this thing called the SUT, the site under test. So the site under test is a Drupal site that's managed with Composer, and Unish is the unit testing for Drush that will build the site and take the Drush that you're testing and inject it into the site under test so that the operating environment for the unit tests are the same as what we're recommending that you do to make the Drush application part of your Drupal site. And in addition to the functional tests, we also have new unit tests in the isolation area, and I mentioned at the beginning that we take pains to isolate which classes we use, so the isolation test actually has its own Composer JSON that only includes the dependencies that we want to use during the preflight and all of the unit tests pass functions in, read the function value that comes out exactly the way you want your functional tests to be that don't have any dependency on Drupal, and we verify them that way. So I think that is about the end of what we have to talk about. Before we take questions, I would like to remind everyone that there's contribution sprints going on on Friday. There's a mentored course sprint in the room Stoltz 2, and the first time sprinters workshop is in layer one and two, and the general sprint is in the main mall room. If you like the session, please come up to us and tell us how much you liked it, and if you didn't like it, go ahead and fill out the application survey. I'm just kidding. Give us whatever feedback you have in whatever form, but we do have this survey that we would strongly encourage you to fill out, and with that, I'll welcome Moosh back and we can take some questions. Yeah, we have time for a couple of questions here. So there's a microphone up front. Regarding the Dress launcher, what I've been doing all the time is just adding vendor slash bin to my path. Is that wrong, or should I know about the Dress launcher? It's not wrong. You can do that too. You can just call vendor bin Dress directly and skip the launcher. That works great. Yeah, I do the same thing. I have vendor bin in my path, so if I CD to any composer project, I can run anything in vendor bin from the local directory, and that works great for Dress too. That's probably because I use virtual machines. I have one Drupal site. Okay. Yeah. Hello, my name is Boris, and I have several questions, in fact. Okay. The first, can you tell us something about the core compatibility things? There are rumors, and it's stated on the docs Drush site that Drupal 8.4 will require Drush 9. Drupal 8.3 won't work with Drush 9, or there's an inofficial version of 8.3 of Drush 8, which will work with 8.4, and such things. That's the one point. And the other question, what was the motivation to integrate a code generator in Drush, which is already a domain of Drupal console? I think it's better slowed down as you've got two very different questions here. Two different questions. Yeah. Okay. Just to end the second one, do you happen to know whether Drupal console has the same code base, this code generator you mentioned, or is it something totally different, and the resulting code will be different too? Okay, that's a third question. You want to take two and three, and I'll take number one after you're done. Okay, sure. Okay, so the generate command, it was an opportunistic move by Drush to add that. We found a library that was super clean, super independent, maintained by someone