 All right, so you guys found your way to Drush 12 modernized. Thanks for coming, thanks for getting to Pittsburgh and getting to our talk. The two of us put a lot of work into Drush 12 along with lots of contributors and we're excited to tell you about it. My name is Moshe Weitzman, an independent web developer, primarily working for Tag 1 as a consultant there. And this is my colleague Greg Anderson, senior lead engineer. Engineering manager, senior engineering manager. They call me Manjaneer. Manjaneer at Pantheon. Okay, so the first group of changes that I want to talk about have to do with authoring Drush commands. So hopefully many of you have written your own Drush commands. It's a rather easy thing to do, I think. And they're good for you and they're sort of self-documenting and they're really easy for other people on the team to use because of this self-documenting feature. So the first thing to say about Drush 12 is that it only runs with the newest version of Drupal, Drupal 10. So you'll want to adopt this when you start running Drupal 10 sites or if you are already, then great. This is a good time to adopt Drush 12. Since Drupal 10 is PHP 8.1 and higher, that's what Drush is also. And we really, you know, embraced that restriction and updated all of our code to be squeaky clean using all of the newest features of PHP. And that really helps us find, you know, bugs related to types that are changing. It helps us communicate what is extensible and what is not and so forth. So the biggest change for authoring is that we encourage the use of PHP 8 attributes instead of annotations. So I'll give you an example of the way Drush commands used to be and the way they are in Drush 12, right here. See if making a figure is helpful. Right now we're looking at the annotations way of authoring commands. So you can see right here this at command and then the command name XKCD fetch. It takes one parameter, two options, two usage examples and an alias. And below that, you have the actual method which takes a bunch of parameters and it does some stuff. When you upgrade to Drush 12, optionally you can start using attributes. You know, it's encouraged but in fact we wanted to have a nod to backward compatibility. So all of the existing commands that are out there are going to run fine on Drush 12. Appreciate that. Thank you. So here's the new way to upgrade at your leisure. If these look alien to you, that's okay. I think they look alien to everyone when you first look at this stuff but you kind of get used to it. The nice thing about PHP 8 attributes is that they're an actual language construct. So there's much better performance for using them. There's much better support for autocomplete and in your IDE for authoring these kinds of attributes. Annotations on the other hand are like completely separate from PHP. So the command attribute right here, you can see that the name is one named parameter and aliases are specified here. The argument, the two options, the two usage examples, most of this stuff is just one for one. Remember this was the annotation example. Most of these one for one get transformed into PHP 8 attributes. As for the method name and the method body, there's no required changes there. You can pretty much keep what you had. So going back to the presentation here, final, strict types, command name constant, typed properties, return types, parameter types. Let's take a look at that. What we have here, let's make this bigger, even much bigger, how do I do that? So this class here is called user commands. If we look at the top of the class, we're declaring strict types, which helps avoid type changes for variables. This is true of all of the Drush internals are using that. All of our command files are declared as final, which means that you can't extend them directly, or at least you have to do a little bit more work to do so with the reflection API. And so we're kind of communicating that our command files are not an API unto themselves. Usually with Drush commands, you have a service that does the actual work of the command. That's the API, but the command definition itself is not an API, so that's why these classes are final. Yes, people have tried. People have tried. One other nice change we made for our commands, encourage that for your commands, is that there's now class constants for each of the command names. So when you're writing scripts and you need to do Drush commands inside your scripts, you can use these constants and you won't make a typo, and you can tell kind of what's using what by linking back to this constant. So here's a quick look at a new feature. Greg's going to talk about this one later, but there's a new create method, and this is one of them, a static create method, where you can set up your dependencies for your command file. And just want to mention that for a while now, Drush has shipped with a generator called Drupal command file, DCF, and if you run Drush generate DCF, it can give you a skeleton command file. And that will help you get like your final into your class statement. It will help you with some boilerplate that's all updated for Drush 12. So that really is the sort of best practice for how you start creating your own custom command is to run our DCF generator. All right, so in addition to commands, Drush has a lot of generators. Remember generators are the thing that generates boilerplate for you if you're creating new Drupal services, you're creating new blocks, you're creating new access control plugins, like all these kinds of things, you can get a kickstart by using the Drush generate command. In addition to all the generators that ship with Drush, there's the possibility of having custom generators. And so the custom generator API has changed a bit. We upgraded to version three of the Drupal code generator. The Drupal code generator is a separate open source project that we wrap inside of Drush and that's what provides all the generators. So the net net is you have to slightly alter your generators for this new version of Drush. Here's what a new generator looks like. This is in fact the Drush command file generator that I just mentioned a minute ago. This also uses PHP attributes. Here we have the generator attribute and the generator attribute takes a bunch of name parameters, name description, alias, and so forth and so on. This class-based generator is new in Drush 12, so you'll want to extend that class. And this interviewer object is new as well. The interviewer is like a name that I think is fantastic, I didn't name it, but the maintainer of this Drupal code generator did. And the point of the interviewer is to ask the user a bunch of questions before the code gets generated. And so you can see that he's building an IR variable, that's the interviewer, and then the interviewer asks what machine name the class should get, what class name, and what services should get injected in. And then it's a matter of using the twig file that has shipped with this generator and writing to this path the result of all the variables in the twig file. So that's generators. Hopefully you'll find them even a little bit easier to use in Drush 12 with this new setup and happily using PHP attributes. Okay, I'm handing off to Greg. All right, so I'm just going to go over what it looks like a little bit more on creating command files for Drush 12. As most mentioned, we have a complete backwards compatibility layer, so you shouldn't have to change your commands at all. The layout for a Drush command is the same as it was before. There's a well-known location inside your module, Drush commands, where you put your command definition, and Drush is just going to find it there. You'll notice that the Drush services YAML file is gone. It doesn't have to be gone if it's still there. We have the backwards compatibility layer that will load it, but you can run without it now. And in addition to module command discovery, we also have a new PSR4 discovery mechanism. So any library that you add to Drupal through Composer is going to have an autoload section in its composer JSON file. And basically what Drush does is it uses this information from Composer, walks through all of the autoloader sections, and if it finds this well-known path, Drush commands, then it takes the base namespace from the beginning of your autoloader. You can see that are underlined in red, and then on the right underlined in red, your namespace is whatever was in the autoload section followed by Drush commands. And similarly, wherever you tell the autoloader to put your source, the source file is similarly located in Drush commands. And the other thing to notice about this mechanism is there's really no way to do a Drush services YAML type thing. There's no good place to put the YAML. We could have a well-known file in there perhaps, but we didn't do that. Instead, and Moshe has already given you a preview of this, we switched to a static create factory method. And this is the same pattern you're already familiar with in Drupal if you've ever made a form or a controller. So basically what happens is when Drush is instantiating your class object, it notices that the static create method is there and it just passes it the Drupal DI container and you can pull whatever services you want out of that to pass it into your constructor, following good practice, make your constructor public, I mean protected so that nobody instantiates it unless they're going through the factory. So porting from Drush services YAML to a static create factory is actually pretty easy. These things look quite a bit different, but if you open up your Drush services YAML, the first thing you're going to notice is it's full of all of these service names. There's a couple of them underlined in red here, the config manager and the config storage export. So when you write your static create, you can just use that same name, just drop the app, call container, get, pass it on in to your constructor. And then I'm going to back up one slide if you notice that that second underlined example from your Drush services YAML has a little question mark after the at sign and that means that this is an optional thing. The service doesn't have to be there and it might be null. Now in practice, if people have set up their services file like this, it's possible if you call that method, it's going to blow up because script type checking and et cetera. So the obvious solution is you just ask the container, does it have the service? If it does, then you call through. Much more readable, very PHP like. Drush also had a mechanism called inflection and maybe a lot of you in this room don't know what that is because it was sort of niche, but the short version of inflection is it's something you inherit when you extend the Drush commands class and basically inflection involves a marker interface that provides a set method and if your class has this, then Drush is going to notice that that marker interface is there and it'll do injection automatically during creation time. We're deprecating this. We really find that the static create is clearer. For now, most of the inflection classes still work if you're using them, but we just completely remove the really unusual ones that aren't really used anywhere outside of core. That's one thing you might encounter when upgrading commands because there's an OBC layer for the removed stuff. Installation and execution. For a really long time, we've been encouraging everyone to say, hey, there's only one supported installation method and that's through Composer, but for Drush 9 and 10 and 11, it just happened to work if you globally installed Drush through a number of different means and it would just sort of figure out what to do and it would even merge together the two autoload files if it really had to. It's not great because things can very easily catch fire. We're formally desupporting that. A lot of the Drush Bootstrap code has gotten way simpler. All of that code is going away and Drush 12 now requires that it be installed in the same site, in the same vendor as the Drupal site that is going to Bootstrap. It won't bootstrap any other site except for itself. The vendor is always there and it's always shared. The upshot of this is that the root option is now vestigial. You can pass dash dash root to Drush 12 and it'll pretty much just ignore it unless you pass a different root and it takes a good and error. But we again wanted to have that backwards compatibility in case you were using Drush 11 on one machine to remotely call Drush 12 on the other machine you might still have that root method there. But you don't have to type it in yourself any longer. If you just run Drush out of the vendor directory then you're going to Bootstrap whatever site this is. So that's really a lot more simple. So the result of this is that the launcher isn't really necessary. We changed the internals of how Drush starts up commands. Now we're taking advantage of some of the new variables that Composer provides to find the bin directory and little things like that. The launcher doesn't do these things which could lead to some strange edge cases. So we recently just desupported the current version of launcher. Maybe someone might resuscitate that in the future but it's not really necessary. Something that's worked for a long time is if you just add a relative path to the end of your bash or other shell path variable to vendor bin then you can just call Drush as Drush and if your current working directory is at the base of the Drupal project your shell is going to find it there. It's just already a bash feature. So why have a wrapper if the shell has that feature as sort of our policy? And similarly, if you only have one Drush on your system you could just put the full path to vendor bin Drush in your path and then you wouldn't even have to change the working directory because Drush always finds the Drupal that it's paired with regardless of what your current working directory is. There's a lot of different ways to manage navigating through your directories. I've just thrown up a couple here. I have a little shell alias called FD which is probably my most used shell alias. It just gives you a way instead of doing a CD to change the directory. You can do an FD to find a directory and just the same way that your terminal will search a path for executables the FD path will search a list of locations where you might have projects installed and this project also has a little startup FD installed that will give you a suggestion of places where you can find your projects and it supports type of tab completion so it's a fast way to navigate between different Drupal projects or any other sort of project. It's bash only. There's another thing out there in the open source universe called ZSHZ which is a little program that just remembers which directories you CD to a lot and then it sort of can't so maybe you want to go back to some places then before. So by using things like this and other bash utilities we don't need to overload Drush with all of these things that are already features of other programs that leads to better maintainability. Site aliases are still around. We're really encouraging people to think of site aliases as just being other environments of the site you're working on so keep your alias checked into your get repository in the site that you're working on preferably inside of the self.site.yaml file but regardless of that recommendation other sorts of aliases are still supported so you can have aliases that point out to all of your different sites wherever they happen to be posted. If you run an alias though the dash dash root option isn't passed anymore so dash 11 can still figure out where the site is without a root so this is okay-ish and vendor bin is assumed people don't relocate your vendor bin directory don't do that but if you do Drush is assuming that you're consistent in where you relocate it to and as far as aliases are concerned we're really finding that the community is moving towards wrappers like DDEV or Terminus or BLT people aren't using Drush aliases as much they just call some terminal some wrapper that will SSH on over to the final place and then get you to Drush so I don't know that we're necessarily going to remove aliases in the future from Drush but maybe if there was some other program that was like the launcher that also had aliases then core Drush wouldn't need to have it Alright, I'm going to pass that Okay In addition to helpful tweaks to lots of our existing commands that you guys are happily running we did add a bunch of new commands in Drush 12 and I'm going to talk a little bit about new commands that were added to Drush 11 since folks may have missed that this never ending pandemic that we went through So the YAML edit commands are brand new in 12 There's a wonderful open source project called YAML edit by Drupal developer Matt Grasmick and we decided to just bring in those symphony commands via Composer and so now you can run the YAML commands that are listed here and a couple more The main benefit of the YAML edit commands is if you are writing a script that has to do YAML stuff you need to change a key change a value remove a couple keys lint a YAML file you don't kind of have to figure out the said in order to do that you can just use these easy commands to do so So encourage you guys to reach for this tool when you're doing YAML stuff at the command line The entity commands are also present in 11 I want to highlight them The entity save command is pretty helpful I use it when I'm developing something Let's say I am developing a save operation in Drupal That can be like the insert and update hooks for nodes and I just need to save a node over and over again to make sure that my code is running and it's doing its thing correctly on every node save You can just quickly run drush entity save give it an actual entity type and entity ID, in this case node 12 and the command line will just save that entity and your hooks will fire you can keep working on your code and making it better and making sure that it's doing what it's supposed to do entity delete is useful once in a while you can delete all content with a given entity or just a given bundle from that entity This is really useful I've used it with PM uninstall You can't uninstall certain entity type modules if their content is still around Drupal's validators will say you're about to orphan your data that's usually not what you want to do so uninstall denied This entity delete is a way to get rid of data that you don't need and that will let the validator proceed with uninstall Encourage folks to use the entity commands The archive commands are pretty new Well, they're in a new iteration They existed in older versions of drush They went away for a while and now they're back So what archive dump does is that it creates a tar ball of your whole site and your whole site meaning the code, the files, and the database And so that's useful if you want to make a quick backup or a snapshot for some reason People use it also when you're switching hosting providers The hosting providers kind of know what to do with one of these tar balls and they untar it and commit stuff to get and you're on a new provider So the new iteration of the archive commands understands how we now build Drupal sites using Composer And so it archives the composer.json and composer.lock along with the database and the files and the code And so you're able to then run Composer install on the other side and you have your code base again We added three commands in the field definition category This is useful when you want to kind of introspect your Drupal site and you want to know, hey, what fields am I running on this site? Which widgets and which formatters am I running on this site? These three commands are there They'll let you know they provide a nice table of information where you can get the information you need The maintenance commands were recently added to solve kind of an interesting problem that people have been seeing on their Drupal sites and maybe you guys have seen it and been perplexed about it like I was Basically, during deployments what I was seeing was that once in a while I do a prod deployment and the cache had no idea what fields I was running and the deployment would fail And now prod is like in maintenance mode and it won't work and it's a whole race to fix things And so what looks like was happening is that the cron job was running every two minutes or five minutes wherever you set it up during the deployment and so the caches were getting populated while Drupal was in a state that it didn't it wasn't possible to know what was installed and what wasn't And so this last command I have written in here DrushMateStatus and DrushCron is an excellent way to avoid this problem So the MateStatus command will fail if maintenance mode is on So the first thing that you are supposed to do in a deployment is turn maintenance mode on and with this as your cron statement you will never get to the second half DrushCron if you're in maintenance mode and once your site's out of maintenance mode it's safe to run DrushCron this will run perfectly fine So hooray for MateStatus and hooray for this double ampersand that requires success on the left-hand side before the right-hand side will work So once you guys upgrade to 12 I encourage you to change your cron statement to something like this Okay, so a few more things to share with you guys that we've done recently The www.drush.org website is always getting better and better Recently we now have release specific documentation So if you're running Drush 11 or you're running Drush 12 you can look at the docs that are specific to your version and you'll see exactly what you can and can't do and how it works We expanded what's available there to include all of the commands that are core to Drush and all of the generators that are core to Drush The commands are listed along with their arguments and options and so forth In addition to regular command options the global options are listed there So you don't have to run a special Drush docs core global options in order to see those and learn about them And finally the Drush topic command just want to remind folks that's a way to read the documentation that's all authored right at the command line So let me just show you the website So release specific documentation right here So I said you can look at the 12 docs You can look at the 11 docs right here and you'll see exactly the information that pertains to you The listing of commands is over here Here we can look at a particular command Here's the cron command that we were just talking about And in fact here's the example that we were just talking about This command doesn't actually have arguments or options So you go right into the global options and these are like the most common global options that you need to know about so they're listed here And any topics that are relevant for your command are listed here along with the aliases and just want to call attention to the legend that's at the bottom of each of these command pages This will tell you how to interpret what you're seeing above with options and what it means if they have square brackets or don't have square brackets and so forth So that's the command listing It's kind of nice to have a URL for each command that you can share and you can ask for help and say here's what the command help is can you help me run this command and make the docs better So similarly all of the generators are now getting their own page on our doc site So troupel9 added bundle classes aren't using those, those are super cool You can generate a bundle class right here using this generator If folks haven't used the search feature on this site the search feature is fantastic It comes up immediately There's nine matching documents You can learn all you wanted to know about Cron stuff and Drush for example This website is a static website that gets generated by something called MK docs and material for MK docs If you guys are working on documentation related websites I would highly recommend that system You just write markdown files and they make it into an excellent documentation website I referenced the Drush topic command Kind of want to show you guys what that is Try to do that here You see that's still kind of small So I ran the command Drush topic inside my Drupal site And here you get 18 different choices that you can pick These are like all the markdown files that the community maintains around Drush and how each part of our system works So if you're a pure command line person you have this option for reading the docs If you're a web browser person feel free to read them on the web It's the same markdown files just made pretty for the web So the next topic is shell completion We took advantage of some advancements in symphony console in the latest version of console which is version six They have integrated completion So if you configure your shell correctly you don't have to type out argument names fully or option names fully You can say like Drush core and then it will give you the option of running core cron or core edit or the different things in that category So folks are encouraged to enhance their shells So you don't have to type that stuff out and option names can be long sometimes So it's a nice time saver The mechanism is documented in the installation page So go take a look at that on the web and you'll see how to configure each of these three shells bash, zsh, or fish This features largely inherited from symphony console So if you have experience with other console, CLIs, Drush configures the same as those do Completion on argument names is a little bit more complicated argument values rather We support some of those now and if folks want to get more arguments to be supported feel free to submit a pull request on that We noticed that the composer team added a great new feature in composer 2.2, yes And there's now a composer audit command and audit will look at all of your dependencies and it will tell you which ones you're behind on from a security perspective So which ones have outstanding essays and you need to take care of those ASAP So that was formerly the responsibility of Drush PM Security dash PHP We offered the same service looking at the same data set that composer does There's no need for the two tools to exist so we've dumped ours and Drush 12 use composer audit instead We kept a command that we've had for a while called colon security And that one specifically looks at your contrived modules and tells you which ones have essays against them and you're too far behind If and when the community gets the essays for contrived modules into the corpus that composer audit looks at then we will have no need for this command and we'll deprecate it and composer audit is the one tool you need but for now you need them both in order to assure that your PHP is up to date So that's the end of the formal slides part of the presentation I'd love to open up the floor for whatever's on your mind let's have a conversation about Drush and then we've got a special treat at the end Go ahead, right here on the front I mean, yeah, that security PHP that we just talked about is gone How many minutes left is that? Okay, ten Alright I can't think of other commands that are gone When we deprecate a command we actually keep it around just for the sake of telling you what to do instead of the current command Just run what you're used to and if it doesn't work we'll tell you what to do otherwise You're welcome Right over here Up in front We are using Drupal's API for deleting the entity so we do an entity load and we entity delete I'm trying to remember now I don't think there's any multiple handling in Drupal for deletion to delete them one by one You load them many at a time but you delete them one by one Now you asked about batch handling I think there is batch handling So we'll load up 50 of them We'll delete one by one then we'll load up 50 more and we will delete So yeah, I think there is some batch handling The command line doesn't tend to do as much batching as the web does So I think it all runs in one process still Yeah, you can still restore it It's not going to run, but you'll get the code It's going to use the Drush SQL commands to load the database If your database server is running you'll get the database Yeah So the question was about archive restore just in case people didn't hear the question Can I run that on a site that isn't functional like a non-bootstrapping site and you can You'll have to make it functional after Everything is restored but you can Right here So the question was Is there any thought to making a command that will take a bunch of entities and transform them in some way Yeah, so that's certainly one good way to do it is you can run a Drush command or a Drush script that will load up all the entities and do the transformation that you want You can certainly write like a hook implementation of insert and update temporarily or forever, whatever you need and then run the entity save command or just run it through all of those So I think that would work too in the middle, yeah Yeah, so the question was is there a way to export all of the config related to a feature, I think and that's not part of Core Drush, I think that people have tried stuff like that The features module sounds like it's like that and there's like the config community has quite a lot of innovation there So I would look to config devel and config manager and like I can't even keep track of all of the different synonyms for config commands but I would look to that stuff, I think that's sort of a little bit outside of the purview of Core Drush so we haven't quite gone there three minutes, okay, yeah Alright, so I just want to thank everyone for coming and hope we can have a little celebration here as I tag 12.0.0 release right here at the end of our session This is all it is If you thought there was more to it and then this magical button gives some content, I will go through and make these even better than what happened here Oh my gosh Somebody converted a lot of commands Yeah Well, let's continue and I'll keep refining This is no longer a pre-release This is the real release It's the latest release Now it's published Alright everyone, great talking to you We'll see you in the hallway