Using "modern" Ruby to build a better, faster Homebrew
Learn why Homebrew now ships its own Ruby, modern Ruby tooling we rely on, how to make Homebrew faster and how we are improving Homebrew.Presented at RubyKaigi 2024.
Show transcript
- 0:00 I'm going to do lots of things in the talk where I want you to put your hands in the air.
- 0:19 So first one, put your hand in the air if you use homebrew. Good. Put your hand in the air if you
- 0:29 have ever contributed to homebrew, made a issue or pull request or commit. Can we clap? Thank you.
- 0:37 Put your hand in the air if you love homebrew. Put your hand in the air if you hate homebrew.
- 0:44 So today I'm going to talk about using modern Ruby in homebrew to build a better, faster homebrew. First, some
- 0:58 background. This is not the right background. Put your hand in the air if you hate windows xp.
- 1:07 Good. It is too old. This is almost right. But this Mac version is also too old. Homebrew does not
- 1:18 support this. This also makes me sad. Ah, this is better. We have the right background. We can continue
- 1:25 the talk now. Homebrew supports this. Hello. I am Mike McQuaid. I have worked on homebrew for 15 years,
- 1:34 and I am the project leader. I am CTO of a startup, which is this little one over here,
- 1:40 called Workbrew, which is-- I'll talk a little bit more about that later, but we're doing stuff to make
- 1:46 homebrew better at work. I was at GitHub for 10 years, and I left as a principal engineer last year.
- 1:52 After the talk, I have homebrew stickers and workbrew stickers, and because I found my sticker
- 1:57 covered again, I have a bunch of GitHub stickers that you can have as well.
- 2:04 So today I'm going to talk about these three things. So first, homebrew and Ruby and our relationship
- 2:10 together. Next, homebrew's Ruby tooling that we use, and how that's maybe changed in the last four
- 2:17 or five years. And then finally, what we're doing to build a better homebrew. First, homebrew and Ruby.
- 2:25 Put your hand in the air if you knew that homebrew used Ruby already. Okay, some people, not everyone.
- 2:32 So this, the text is very small, so you probably can't read it just now. But this is the original
- 2:38 first commit of homebrew, which was 15 years ago, next week. Exactly, which is kind of funny. So
- 2:46 it was by a guy called Max Howell, MXCL, up here on May 2009. And the first commit was this readme file,
- 2:56 where he talked about how homebrew was going to work.
- 3:02 So the important bit for us, homebrew uses Ruby and some other stuff that is already installed on
- 3:07 Leopard. Just copy this directory somewhere. So right from the beginning, homebrew has relied on Ruby.
- 3:14 And in the beginning, homebrew always used the Ruby that was provided by macOS X, macOS 10, I guess. So
- 3:24 homebrew and Ruby have been very closely aligned from the beginning. In fact, homebrew in the very early days
- 3:30 it just looked a lot more obvious that it was using Ruby than it does today.
- 3:34 So it used to be to install homebrew. There wasn't a brew command yet. There wasn't a nice website with an installer,
- 3:41 but you just ran this Ruby command after having checked out homebrew on your disk.
- 3:51 But now it is the call to bash. I think homebrew might have been one of the first projects to do this.
- 3:58 Put your hand in the air if you hate call to bash.
- 4:01 Yes, some people. Put your hand in the air if you love call to bash.
- 4:08 Most people don't care it seems.
- 4:10 And installing wget, that's a nice example we have of a little simple homebrew package,
- 4:18 used to look a bit like this. So you would just run Ruby, and then you would pass the actual formula
- 4:25 file here directly and run that formula script with Ruby. Who knows what a formula is already? A few
- 4:32 people. Not everyone. So now you just type brew install Ruby, which means it's easier to forget
- 4:39 that you're using Ruby with homebrew at all.
- 4:44 So I'm going to talk a little bit more about the formula here. This is the DSL domain-specific
- 4:51 language that we use in homebrew for writing packages. In my opinion, this is one of the biggest
- 4:57 reasons that homebrew has become so popular is compared to maybe apt-get or maybe mac ports or maybe
- 5:05 Debian. It's very, very easy to write a homebrew package. And one of the big reasons it's very easy
- 5:11 is because of Ruby. So this is slightly simplified so that we can kind of fit it all in one slide,
- 5:21 but this is a nice minimal example of what a formula can look like. This formula is valid as it is,
- 5:27 but if you go and look at the actual formula, you'll see there's a few more things for
- 5:32 boring reasons I won't get into right now. In my opinion, this is extremely readable without being overly
- 5:38 verbose. And I still think, I thought learned so 15 years ago for the first time, and I still think
- 5:44 today that Ruby is the best language for writing beautiful code like this. So for this formula, we
- 5:51 see this is called wget. That's the name of the class and also the name of the package and also the name
- 5:55 of the file on disk. This is a type of a formula. We've got a description here, internet file retriever.
- 6:02 We've got the home page where we say, okay, this is where we're going to go if you want to learn more
- 6:08 about wget. We've got the URL where it's going to be downloaded from, or at least in this case, we're
- 6:15 simplifying it here. You would actually download it directly from Homebrew. We provide binary packages for
- 6:20 you. I'll talk more about that later. But this is where Homebrew will download it for on our CI systems.
- 6:26 We've got a checksum, making sure that this is what we think it is, the license, and then some commands
- 6:33 we run. Again, if you've written a bit of Ruby, the system command would already be familiar for you.
- 6:37 So we're just passing this through. The prefix is the special place that we're going to install the software,
- 6:42 and then we run make install. So even from this dev install, it's very easy to see what commands are
- 6:48 needed to install wget under Homebrew. And as a result, I've seen other people who don't even use
- 6:54 Homebrew who are trying to figure out how to build a tool go and look at the Homebrew formula because
- 6:58 it's often the easiest thing to read if you don't know anything about the package manager itself.
- 7:02 And then here we've got an example of a little test. We're saying we want to wget to dev null because
- 7:09 we don't care what the output is, and just see if google.com is up. And hopefully,
- 7:14 if it's not, then hopefully it's just Homebrew's wget that's broken and not Google that's broken,
- 7:19 because then we'll be sad. Although maybe this should be ChatGPT nowadays instead.
- 7:23 Raise your hands if you know what a cask is. This is even less widely known than a formula. Yeah,
- 7:31 even fewer people. So a cask in Homebrew, it used to be part of a separate project called Homebrew
- 7:38 Cask. But that was merged back into Homebrew itself, and now we kind of have them all in the same place.
- 7:43 So a cask is generally something where the upstream project, upstream meaning the people who make the
- 7:50 software, they're the ones who create the packages or the binaries or the installer file or whatever.
- 7:57 And we just download from them and then we install it. So it works a little bit differently. We're not
- 8:01 having to do build instructions. We're more concerned with what package we might get and then where we put it
- 8:07 and how we uninstall it and stuff like that. So I'm not going to go through this in as much detail,
- 8:11 because I don't think it's quite as interesting. But we've got we're saying we've got different things
- 8:15 for the different architectures. This is for one password. We've got different checksums for the
- 8:20 different architectures, because unlike downloading from source, we're going to use a different download
- 8:26 depending on what system we're in, whether we're on Apple Silicon or whether we're on Intel x86.
- 8:32 We've got the URL we're downloading it from. We've got the name, description, kind of like a formula,
- 8:39 home page kind of like a formula. We're saying that it auto-updates. And basically what this means is that
- 8:44 this version might not always be correct because after you've installed it, one password can then
- 8:49 update itself. We've got the version of macOS it depends on. And then we've got the app file that
- 8:55 it installs. Again, this is a little bit minimal. The actual thing is slightly bigger, but not by much.
- 8:59 Another thing that's worth noting with casks is Homebrew now fully runs on Linux. Most packages can be
- 9:07 installed and work nicely on Linux as well. But casks are for now only on macOS. We also write Homebrew
- 9:15 itself in Ruby. So this is a nice little modern example of what we're doing nowadays. So you can see
- 9:21 we'll talk a little bit more about this later. If you're familiar with Sorbet, you might know what type
- 9:27 strict is or this signature and stuff like that. So we've got this command. This is if you run brew docs.
- 9:34 Then we specify what the arguments are. This command doesn't actually have any arguments, but it does
- 9:38 have a description which is used for help output for the man page and all this type of stuff. And then
- 9:43 we're saying we want to run a browser and we want to go to Homebrew's website. Again, I think even if
- 9:48 you don't know much Ruby, quite nice and readable. So I mentioned Homebrew initially released 2009. Back then,
- 9:59 it was macOS 10 Leopard, and it came with Ruby on the system, which was pretty cool at the time.
- 10:06 So in 2009, that was Ruby 1.87, which I think was released in 2009, maybe 2008, something like that.
- 10:14 So it wasn't too old. It was about right. And it was nice to be able to use Ruby when building Homebrew.
- 10:18 And then it meant that Homebrew didn't have to figure out how to install Ruby or anything like
- 10:22 that to run on a Mac system before you could use it. Apple did that all for us. Unfortunately,
- 10:28 because we were relying on the Apple version, by 2016, we were still running Ruby 1.87.
- 10:36 And in 2016, this is what my face looked like every time I had to still write Ruby 1.8. And I go online,
- 10:44 and I'd find, oh, this is this lovely thing you can do in Ruby or some new DSL or technique or whatever.
- 10:50 And it was released ages ago in Ruby 1.9. And I would
- 10:54 every single time. Put your hand in the air if you still have to run Ruby 1.8 anywhere in 2024.
- 11:04 Oh, one, two, three people at least, my friends. I think we love to those people. And I'm sorry.
- 11:16 So by 2017, things were going a little bit better. I still have my eyebrow raised because I'm not quite
- 11:24 as happy as I would like to be, because 2.4 has already been released. But Apple released Ruby 2.3
- 11:31 with macOS. So we're like, okay, we can now use this version. We can rely on this now.
- 11:36 It's not too old. Things should be okay.
- 11:38 But by 2019, we're falling into the same pattern again. We're having to rely on older versions and
- 11:46 stuff like that. So the last Ruby Kaige I spoke at in Fukuoka, this is the version we were running.
- 11:51 Anyone still running 2.3 in production? I expect a few more people than 1.8.
- 11:56 No, actually fewer. That's interesting. I guess you get either stuck on the old ones,
- 12:01 or you keep running through the new ones. But by 2019, macOS came with a newer version,
- 12:07 so we could upgrade to then. But then again, the same thing. By 2023, we're still running Ruby 2.6,
- 12:14 and we're stuck. This is on my lovely Apple Silicon laptop running the latest version of macOS. Today,
- 12:25 you still get Ruby 2.6.10. This makes me very sad. But we have some people at Apple that we sometimes
- 12:33 talk to about these things in Homebrew. And we said, please, please, please, please, please, please,
- 12:37 can we have a new Ruby? And they reminded us that, I can't remember how many years ago now, maybe five,
- 12:42 they said, the Ruby on the system is deprecated. You shouldn't be using this anymore. And we said, yeah, but
- 12:48 that's not us, right? Like, the rules don't apply. We're cool homebrew people. I said, no,
- 12:52 you're not getting a new Ruby now. Go fix this problem yourselves. So with tears in my eyes, I had to say
- 13:00 goodbye to macOS Ruby entirely for now. So we'd asked Apple for a newer one. We didn't get what we wanted.
- 13:08 But I'll talk in a minute. We were able to get a slightly newer Ruby ourselves. So we just moved on to
- 13:14 Ruby 3.1. And during this conference, I heard some people talking about some cool things. There was a
- 13:23 Vernier, I think it was, Jay Hawthorne and Aaron Patterson worked on this new profiler for Ruby. It
- 13:30 looked really shiny. I tried to get it set up with Homebrew because we have our own like profiling
- 13:35 tools and Homebrew. And I was very sad to see that it needed Ruby 3.2. So I thought, hmm,
- 13:40 can I get Homebrew upgraded to Ruby 3.3 during Ruby Kygi? And I got the PR merged 48 minutes ago.
- 13:50 When you're going to do a talk on stage to a bunch of very lovely, knowledgeable people like yourselves,
- 14:03 put your hand in the air if you think the best thing to do is to try and get this PR merged before.
- 14:07 Some people. Some people. I'll try and make the talk better from now on so it doesn't seem like
- 14:15 I've done it all at the last minute. So we have this thing that enabled us to get to a new version now.
- 14:23 This didn't get updated in the last 48 minutes. We have this thing called portable Ruby in Homebrew.
- 14:30 So what that came from is back in the older days, I mentioned when we were on 2.3 or 2.6,
- 14:35 we had to support all versions of macOS which were still running an older Ruby, but we wanted to use
- 14:42 the newer Ruby. So originally our portable Ruby was created so that we could have a Ruby that could be
- 14:47 installed anywhere on any system on any macOS version that we supported in Homebrew. And it could be put
- 14:54 anywhere on disk and moved around and everything like that, but could run a version that matched the
- 15:00 one in macOS. But when we moved to Ruby 3.1, we decided that now was the time to move entirely to our
- 15:08 own portable Ruby. So now if you're on Linux, you can supply a Ruby from the system that's maybe Ruby 3.1,
- 15:14 but if you're macOS, then you are always running portable Ruby now, which is nice because we now
- 15:18 have a lot more control over the Ruby versions we're running in Homebrew. And without that, we wouldn't
- 15:23 be able to be running Ruby 3.3, and it would take a lot longer than a week for us to move across.
- 15:29 We build binaries for Apple Silicon, for Intel x86-64, and for Linux x86-64 as well. So now I've talked a
- 15:41 little bit about Homebrew's relationship with Ruby and how we moved around the versions and things like
- 15:45 that. I'm going to talk about some of the Ruby tools that Homebrew uses. So RuboCop deserves the
- 15:53 first mention here because in Homebrew we use it really widely and for more and more things and in
- 15:57 some quite cool ways. It's kind of hard to demonstrate these during the talk, but for example,
- 16:04 when we first started using RuboCop, we just used it for Homebrew's internals to try and enforce a few
- 16:10 little rules and try and have some code consistency and make it easier for us to review pull requests.
- 16:15 Because Homebrew has had, I think, I can't remember, maybe about a thousand contributors over the last 15
- 16:22 years to the package manager and I think over 11,000 at this point to the formula. So reviewing all those
- 16:29 pull requests with now a team of about 30 people, but in, you know, even five or six years ago I think
- 16:36 we were fewer than 10 people, it's a lot of work. So we try and do as much stuff with as much automation as
- 16:41 possible. So RuboCop is really helpful for that. But over time, we've built it sort of into Homebrew
- 16:49 itself. So if you type brew style, wget, for example, then it's going to check the contents of that file on
- 16:56 disk and make sure that that meets all our style guidelines. We also have a bunch of RuboCops that
- 17:02 we built custom ourselves, which will do things like enforce the ordering in a formula file or a
- 17:07 cast file. And a lot of them have auto-correction support, which means if you're using an editor,
- 17:13 like I use VS Code and I enable auto-correction so I can edit a formula file and then see inside my
- 17:19 editor, it will move things around and change things based on Homebrew's own style guidelines.
- 17:24 For those of you running other open source projects, I'd really encourage you to think about
- 17:29 how RuboCop and auto-correct can make life nicer for the people contributing to your project,
- 17:35 because it's really nice. We have a dash dash fix argument to brew style, which passes through to
- 17:40 RuboCop's auto-correct. And it's really nice to be able to say to our contributor, just run this command
- 17:46 and we will fix up as many of the style violations as possible automatically for you. We also use it on
- 17:53 Homebrew itself. So if you just run brew style, that's going to check Homebrew itself is up to date.
- 17:59 And we run this in our CI, but it's also we run it locally to make sure that we're using everything
- 18:05 the way we want it to. It's also nice because, as I'm sure most of you are used to with RuboCop discussions,
- 18:10 it stops as much discussion on an individual pull request about what the styling is and instead moves
- 18:17 that to a conversation about what should the RuboCop rules be for this repository.
- 18:22 If you're at my 2019 talk where I talked about some of the similar stuff here, you would have heard me
- 18:27 mention RuboCop already. But since 2019, we're now using Sorbet as well, which is the kind of Ruby
- 18:34 type checker that's come out of Stripe, I think. We initially sort of brought it in again using it for
- 18:42 a few files here and there, but then now we're moving more and more to using it more heavily. We're removing
- 18:48 some of our runtime checks in favor of Sorbet checks and we enable it by default for developers now.
- 18:54 We have this brew type check command, which again passes through to kind of Sorbet and checks things
- 19:00 that way with Homebrew. And we expect over time, we're going to try and get as much of Homebrew to be
- 19:06 type strict as possible because we've found that it helps catch a lot of errors.
- 19:11 It also provides better documentation for users for our Ruby DSLs when we can generate the typing
- 19:17 information that things expect. Also, our test suite. Who here has a test suite with 100% coverage?
- 19:25 No one. Whoa, what one person? And then they immediately went like this because they're not sure.
- 19:32 They don't want me to check off. I'm going to come and check your test suite afterwards. And if it has 99%
- 19:36 coverage, you're going to have to tell all these people that you didn't tell the truth.
- 19:40 But yes, our test suite is around about 70%, 75% coverage. It's pretty good. It catches quite a lot of things.
- 19:50 There's a lot of regression tests in there because Homebrew does some weird stuff and it's been around
- 19:54 for a long time. But it doesn't catch everything. And we're finding more and more that Sorbet helps to catch
- 19:59 some of the issues that Rubocop may have missed in the past. And it particularly catches a lot of typos.
- 20:05 So that's been very good for us.
- 20:07 Speaking of our test suite, we use RSpec for that.
- 20:12 Again, I saw there was one of the surveys outside in the booth area, in the sponsor area,
- 20:18 where they got people to say whether using RSpec or MiniTest. It seems like a lot of people are using RSpec.
- 20:23 Maybe a lot more than MiniTest, perhaps.
- 20:26 So if you run brew tests, that's what we're doing there. Shout out to the parallel tests gem,
- 20:31 which is letting this run in 10 processes, which makes everything a lot quicker.
- 20:36 And yeah, it's not too bad. It takes about six minutes on my two or three year old Mac.
- 20:42 And yeah, I feel like we've got a nice balance with Homebrew with testing for being able to
- 20:48 verify that things are working correctly without having a test suite that takes hours and hours to run.
- 20:55 So the final part of this talk today, I'm going to talk about what we're doing in Homebrew to make
- 21:00 things better. And particularly, I'm going to talk about what we're hoping to do better in the next
- 21:05 year. So if I'm at RubyKaigi next year, you can tap me on the shoulder and ask why these things aren't as
- 21:12 good as I said they were going to be. So the first thing in Homebrew is improving the performance.
- 21:19 Who finds Homebrew to be slow or too slow? Not too many people. Okay. Well, apparently Google disagrees with you.
- 21:27 So we talked a little bit about the bottom one. Why is Homebrew written in Ruby?
- 21:32 I can't help you with why it's not installing. Don't open an issue. That's not my job.
- 21:39 And then why is Homebrew so slow? So let's talk about this a little bit.
- 21:44 So I thought I would add this slide last night. And as we saw from the portable Ruby upgrades,
- 21:51 I'm quite bad at procrastinating. And any chance to not do my talk and instead write some code,
- 21:59 I do that instead. So I was going to just do this slide. But then I thought, hey,
- 22:05 let's click through. What is that saying here? Okay. So why is Homebrew so slow? Because Ruby is slow.
- 22:13 Oh, this is very mean. I can't put this on the screen at a conference where Matt's is here. I don't want
- 22:21 to make Matt's cry. I can't let this insult against Ruby stand. Ruby, I will defend your honor.
- 22:28 So I clicked through to here. And I saw someone was saying,
- 22:32 it's just annoying. Compare pip, which is three to four times faster. So there were two of these
- 22:38 things. It was comparing pip help and pip list. I didn't include the Homebrew output. I probably
- 22:44 should have done here as well. But I'll let you believe this person that it's three to four times
- 22:48 faster. I thought pip help. Okay, brew help. For reasons I won't go into now, that's probably going to
- 22:54 be a little bit hard to make really fast. But I was like, brew list, I should be able to make that fast.
- 22:58 So last night, during the writing of this talk, after midnight, because I'm an idiot,
- 23:08 I decided to open this pull request to make brew list much faster. And because I am very petty,
- 23:18 I did a direct comparison with pip list. And it's now 1.28 times faster than pip list.
- 23:23 And I also posted, we were meant to have a Homebrew hackathon in a couple of months. I said,
- 23:34 by the end of the hackathon, we need to make sure that brew help is also faster than pip help.
- 23:40 So we've had a lot of talks talking about performance optimization during this conference.
- 23:45 So I wonder, how do you make Homebrew so much faster? Do we port to Rust? I don't know.
- 23:54 Everyone likes Rust now. It's very cool. Obviously not as cool as Ruby, but you know, it's cool now.
- 24:00 People are using it for improving the performance of their Ruby programs. Maybe have some Rust code.
- 24:05 I don't know, like porting to C. Do I want to port to C? Oh, no. I've just looked at the next slide.
- 24:14 It's really bad. We ported it to Bash. Maybe one of the worst languages that ever existed.
- 24:20 So instead of beautiful Ruby, we now have this. Look, look at what I've done. Please forgive me.
- 24:31 So the reason for this is when you run brew the command at first,
- 24:36 it's running a little bit of Bash to kind of clean up the environment and stuff like that.
- 24:40 And then it goes and runs a bunch of Ruby code. And for reasons that are maybe a little bit Ruby's fault,
- 24:46 but mainly Homebrew's fault, any Homebrew command like brew help that has to be in Ruby
- 24:53 ends up being like quite slow because it kind of we have lots of requires. We used to use active support,
- 24:59 which speeded things up a bit by removing that. But you know, just going and printing a command from
- 25:05 a Homebrew Ruby command is too slow. So when we can, in a case like this, brew list is effectively just
- 25:12 shelling out to ls here anyway. That's what the Ruby was doing. So that's why I knew when I saw it,
- 25:21 I think this can be faster. And then if the input is too complex, if you pass some difficult arguments
- 25:27 or whatever, and we don't know how to do that in Bash, or we don't want to make our Bash any more ugly
- 25:33 than it has to be, then we just go and try in the Ruby version instead. So you may have seen some
- 25:39 people talk about this already. Who has used Hyperfine before? Not many people. So a few other talks
- 25:47 talked about this, and I'd like to encourage you, if you're ever working on stuff with, say, Ruby or
- 25:53 CLI or whatever, something that's not in a web request, then Hyperfine is quite nice. So I'm going to
- 25:59 compare the Ruby and Bash versions of these commands. So you can go and you run these little benchmarks,
- 26:05 and then you can see how long is it taking, what's the min/max time. So to do brew prefix in Ruby takes
- 26:10 about 400 milliseconds. To do it in Bash takes about 26. To do it brew command, which is another command I
- 26:18 sped up recently by moving to Bash, takes about 400 milliseconds. Again, to do it in Bash takes about 21.
- 26:24 So we can see Bash, you know, it has its place. It's a useful language. It's horrible to write
- 26:31 compared to Ruby, and I hate myself a little bit every time I have to do it. But in our case,
- 26:37 unlike a Rails app or whatever, the JIT doesn't help us very much because we're mainly about spin up the
- 26:44 process, do some operations, close it down. So we don't get the chance to get into really hot loops
- 26:50 where we can get lots of performance up with organizations. We do tend to try with each newer
- 26:54 version of Ruby to play around with JIT settings, but we've not really found any speed up yet.
- 26:57 Finally, we're building better security into Homebrew. So we've had some security audits in the last few
- 27:07 years. We've had one that's public that you can look at Homebrew's blog and learn about that. We have
- 27:11 another that's in progress that we're hoping to publish as soon as possible once we fix a few more
- 27:15 issues. Also GitHub Actions, which is our CI provider, they have this thing called Attestations now, which
- 27:24 is quite complicated. You can read more there, but essentially the short version is it will go and let
- 27:28 you know whether the artifact, the bottle, the binary package that we provide has come from GitHub Actions
- 27:35 and our CI servers, and you can verify it that way. This isn't enabled by default yet, but we hope it to be
- 27:41 soon in future, which will provide again more added security to Homebrew's already fairly good security flow.
- 27:47 And me personally, I found the work on Homebrew alone on the security side to be
- 27:53 hard because we can't get everything into the open source project to get security as well as
- 27:59 maybe big companies might want it to be. So I started this company last year called Workbrew,
- 28:04 where it's like Homebrew for home and Workbrew for work. So the thing we're doing right now is trying
- 28:10 to make Homebrew work better with MDM tools, say Jamf or Kanji or SimpleMDM or whatever, but we're hoping
- 28:16 to work on more engineering specific features in the future. We've got our own little installer that works
- 28:20 offline and provides portable Ruby and everything like that, and sets up Workbrew and Homebrew at the same
- 28:25 time. We've got a nice little Rails app that lets you see every device you have in your fleet of
- 28:32 MacBooks and see what is outdated and what is ready for upgrade and stuff like that. I could then say
- 28:38 this FB303, I clicked on this button here, and then I get a nice little upgrader to say I want to run
- 28:45 upgrade formula 303 and run on my laptop here, or I can run on everyone. So if you're interested in Workbrew,
- 28:52 then do get in touch. Either tap me on the shoulder at the conference, send me an email afterwards, or go
- 28:57 to our website and fill in our contact form. There's also a little demo video there where it explains what
- 29:01 we're doing. So during this talk, and there's a very small text at the bottom, but if you go to my
- 29:08 website, you can see all the slides if you want to follow along later on. We talked about Homebrew and Ruby,
- 29:14 how they've had a good relationship since the beginning, and about how we're getting onto newer versions. We
- 29:19 talked about the Ruby tooling like Sorbet and Rubocop and RSpec that we're relying on very heavily in the
- 29:26 Homebrew ecosystem, and we talked about how we're going to build a better brew in the coming years
- 29:30 in terms of performance and security. But because this is Ruby Kygi, and this room is filled with
- 29:36 genius Rubyists, please help us. As I said, we want Homebrew to have better performance and better
- 29:41 security. And one of the best things that you can do is join in with this effort and help us.
- 29:46 If you don't know how to get started with the Homebrew, or you get confused by our contribution
- 29:51 documentation, send me an email and I will help you out and get you started with being a Homebrew
- 29:55 contributor. Thank you very much for having me. If you want to get in contact or ask any questions,
- 30:00 you can get me on Mastodon, Twitter, or send me an email. Arigato gozaimasu.
- 30:11 Thank you.