Laravel Creator Spotlight

We talk with Len Woodward about his project Whisky. 

Whisky is the simplest, framework-agnostic, CLI tool for managing and enforcing a php project's git hooks across an entire team.

Show Links: 

* [Len's GitHub](https://github.com/ProjektGopher)
* [Len's Website](https://LenWoodward.com)
* [Len's Twitter](https://x.com/ProjektGopher) 
* [Len's YouTube](https://www.youtube.com/@ArtisanBuild)
* [Whisky](https://github.com/ProjektGopher/whisky) 
* [Laravel ffmpeg tools](https://github.com/ProjektGopher/laravel-ffmpeg-tools)

Creators & Guests

Host
Eric L. Barnes
Creator of Laravel News
Guest
Len Woodward
Founder of ProjektGopher Multimedia

What is Laravel Creator Spotlight?

Interviews with creators making cool things in Laravel

So today, welcome back to the Laravel

News Creator Series.

In this episode, I have with me Len

Woodward, who is the

creator of quite a few projects,

but today I wanted to

talk to him about whiskey.

So Len, as far as introduction,

anything, any other

projects you want to mention are

off the top of your head that you're

doing a lot of work

with that is not whiskey?

Yeah, I got a couple.

So one that got a little bit of traction

on Twitter a couple of

weeks ago was Conductor,

which is basically NPX, but for PHP.

So it allows you to run composer packages

in an ephemeral way.

So if you've got stuff like just one

rector or a shift from

the Laravel shift that

you want to run, you can do that on the

CLI and it doesn't

necessarily need to be installed.

I'm putting a lot of work into community

prompts, which is an extension of

Laravel prompts,

which allows you to do

some interesting things.

I've worked on an async prompt that lets

you unblock rendering to the terminal and

reading from the file system and

everything so that you can trigger

renders at any point

in time.

And then it's open to community

suggestions as well.

So if you had a prompt that you wanted to

submit to Laravel

prompts and it got closed

because he doesn't want the maintenance

burden, we're open to taking that on.

Other projects, I've got some stuff for

FFmpeg, managing on demand disks.

Yeah.

I think that's a few.

I think that's probably enough packages.

I got enough on my plate.

Yes.

I know because I think, I mean, this is

going back maybe one of

the first times we spoke

was on the FF, is it FFmpeg?

Yeah, FFmpeg.

MPEG.

Yeah.

Because you were doing

some cool stuff with that.

But today let's talk about Whiskey.

So Whiskey is a project you created, I

think it's been out about a year now.

Is that sound about right?

Yeah.

I started it out as a package just called

Laravel Git hooks.

And that would register a couple of

commands that you

would bring into a package.

And then I went to

Chicago for PHP tech last year.

And Nuno suggested to me that I write it

as a standalone CLI

using Laravel zero.

And by the end of the conference, I had a

working proof of concept.

And then I just kind of

kept improving it over time.

I still haven't hit 1.0 yet.

There's one more little

thing that I want to squash.

But yeah, I mean, it's useful.

It's being used out in

the wild in projects.

It's been great for my own projects.

And I love not having to rely on Husky in

my node dependencies.

That's nice.

So as someone that's never used it, don't

know anything, say that

they're just listening

in.

What is the, basically what is Whiskey

and what is the selling

point on why you would

want to use it?

Yeah.

So we, at a client I was working at, we

had a need to manage all

of our Git hooks across

the entire team.

Previously I've used Husky and like it

worked fine, but it's a

little bit higher friction

to install than I was hoping for.

And so my goal was to just build

something that's only PHP

that only depends on the PHP

version and no other dependencies and

something that would be

the lowest friction barrier

to entry possible.

So the name Whiskey is

kind of an homage to Husky.

But yeah, I went through this, tried to

make it as easy as possible.

It's easy to disable.

It's easy to update.

Well, I was going to say, so let's say

you're a developer and

you've not really used Git

hooks before.

What's the selling point

to even start using those?

Like what are some common scenarios where

you'd want to use Git hooks there?

Yeah.

So Git hooks are kind

of a controversial thing.

It's a really useful tool in certain

scenarios, but it's

really easy to go overboard.

So when you're doing your commands and

push and pull and merge

and all that sort of stuff,

each time that's called, Git

is going to trigger a hook.

And if you've got something registered in

that hook, it's going to run it.

If you don't have anything registered,

it's just a no op and

it's going to keep going.

So for myself, every time that I make a

commit, I want to run the linter.

And so I've registered that I've got my

composer lint command.

And in my Git hook, it just calls

composer lint on push.

It's going to run composer lint, composer

types, composer stan, composer test.

If that's too slow and it's slowing you

down, you can always

just tack on the dash dash

no verify flag and it'll skip it.

But that's what it is.

So it can slow you down.

You don't always have to use it.

It is easy to go overboard.

So I would warn people against going with

a Git hook that ends up

being like two minutes.

Try to keep it fast.

Yeah.

I was thinking like so, like in a team

environment, if you have a

ton of like, say you have a

two minute Git hook and does it, is it

blocking for the other person?

Like if you push and it's running and

then I push, that's not,

it's still going to push,

right?

It's just going to,

it's just going to rerun.

On the client.

So this has nothing

to do with Git at all.

So this will, if any of your Git hooks

return a non-zero exit

code, it's going to stop the

process of going to GitHub.

So this is a way to save minutes on CI

and stuff like that,

because you know that when

you're pushing, it's already going to

pass the lint check.

So you're not having to push your code up

there and it's like,

oh, I missed, I missed

my spacing on this.

I had all my stuff on one line when it

should have been split

up and it, and it doesn't

pass.

So then you need to have

another commit going in after it.

That's just tagged linting.

And then you have it run and sometimes

you've got multiple,

multiple checks on GitHub.

So you're pushing these things up.

You're still running your test suite and

then you've got

multiple things running at the

same time.

It's just, it's a bit of a pain.

And then for an organization, you've got

a limited number of

minutes in your, your GitHub

actions as well.

And so if you've got a lot of stuff going

on, you kind of want to

minimize that by offloading

that burden to the client first.

Gotcha.

Gotcha.

And, and then now as far as like whiskey,

it's, it's all, you

know, the way you build,

I guess, build, create the way you

implement everything.

It's just straight normal things, right?

Like I know you were comparing it to one

called Husky, but this

one's designed just to be

simple so that way you can define

everything you wanted to do

sort of in a normal fashion,

I guess is the right word.

Yeah.

So the, the big issue with git hooks is

that in your dot get

slash hooks directory that,

that doesn't get

committed to your get tree.

So you can't really

track things that way.

What whiskey does is it registers its own

git hooks directory

and then that's committed

to, to the repo.

And so that's what your, your native get

hooks are going to be calling.

That's a little bit more complicated to

set up than, than whiskey.

I mean, it's not, it's not a huge

difference anyways, but I

was just curious about what

it would look like to build this tool.

So I built it and then I just kind of

kept going and it was

like, Hey, this is cool.

So I was going to release it.

So my goal was to just have it be you

require the package and

then you just run whiskey

install and it does

the whole thing for you.

I've structured it in a way so that if

you've upgraded whiskey

and you're trying to install

it again, it's going to look for all the

legacy ways that I've

ever installed it and

it's going to replace those as well.

So you're usually not going to have to go

in and modify these things manually.

So it's a, I'm trying to have it just be

really, really smooth,

really smooth, straight forward.

Is this something you run on all your

projects, even for like

your personal stuff or do you

kind of think of more of like these get

hooks and, and whiskey

being more in like a team

environment?

I run it on most of my projects.

Yeah.

And I didn't know this until recently,

but apparently, uh,

verbs from, uh, from thunk,

they have it installed in there too.

So that's kind of cool.

And yeah, they told me that they like it

because it just works.

It's one of those things where you just

kind of set it up once

and you can forget about

it.

And you don't need to, it's not one of

those things that's

constantly blocking you from,

from getting your stuff done.

So it's nice to know that

at least it's tolerable.

Yeah, that's true.

That's funny.

Um, so, so what is like, um, this was

sort of off the wall, but

what is sort of the most

advanced thing you've

ever done with the package?

Like are you doing anything crazy in any,

in any of your other

projects that, uh, so

I don't do a whole lot of crazy stuff

with, with whiskey

because normally, normally I

just register all my

scripts as composer scripts.

So I just do like composer, Len,

composer types, composer

coverage, composer, all of

this.

And then in my whiskey dot Jason, Oh

yeah, that was the other change.

I don't register a get hooks directory.

I just have a single composer dot Jason

in your directory route.

So that's where you do it.

And every time you make an update in

there, as long as you're

not adding a new hook, you

don't have to update whiskey.

Um, so that's usually the

only stuff that I'm doing.

I'm not doing crazy stuff.

Like a lot of people will add in like a

scripts directory where

they can have lint staged.

So it'll only lent

anything that's been staged.

I usually try to avoid that.

My biggest suggestion with whiskey and

get hooks in general,

do not let your get hooks

modify the, um, the, the files, just have

it do checks because

if it's modifying files,

especially if you're doing patch commits,

then it's going to

overwrite the, it's going

to recommit the whole file instead of

just that patch section.

So I try my best not to do anything

ambitious and a get hook.

I try to just keep it simple and fast.

Do you, um, I, since you want it simple

and fast, do you run

tests through there too,

or do you kind of keep those for only

like sort of the sea outside?

Uh, I mean, of course running them

locally, but do you also

do that as part of this or,

or how do you usually run

the tests before pushing?

So my, my pre-commit hook is usually just

a linter and then my

pre-push hook is usually

like the, the linter again, um, static

analysis and the test suite

and sometimes type coverage.

Nice, nice.

Um, and then of course, you know, like if

anybody's listening or

watching and they want

to, um, just sort of see what you do, I

assume you, you have a

sample set up there, um, with

the package to kind of get them started

or is it best to look

at, like, look at one of

your other projects just to, just to see

how you're doing things?

Um, yeah, I mean, there's, there's not

really a whole lot to it to demonstrate.

The read me I spent a lot of time on, so

it's pretty descriptive of it.

So it goes through a couple of scenarios

where, where you might

want to skip using whiskey

and stuff like that.

Um, yeah, I don't think there would be a

whole lot of benefit in

showing how it's used in

a project just because it's such a small

narrowly targeted tool.

Um, one thing that I did want to include

in there though, was

there's certain actions

in get that aren't

compatible with the no verify flag.

So if you're doing something where

someone used the no

verify flag to push something

that wasn't passing the linter and then

they skipped the CI step

and they merged anyways.

So you've got changes in your main branch

that don't pass the linter.

You're going to bring that down into your

local branch and then

you're going to merge

from main and then as you're merging,

it's going to fail

because it doesn't pass the

lint stage because we're not, we're

running the pre-commit hook.

So if you try to run get merge dash dash

continue dash dash no

verify so that you're skipping

the hooks, it's not going to work because

that function doesn't

work with the no verify.

So I added into whiskey, uh, just a

whiskey skip once command.

And so if you do that, it'll skip it.

You can merge from main,

uh, or rebase from main.

And then at that point you run the linter

on a separate commit

and then you can keep

on going with your work.

So there's some, there's some edge cases

and everything, but I try

to, I try to demonstrate

those in the read me.

Yeah.

It's funny.

Like, yeah, I was going to say, like get,

get in general, like,

um, you know, I'm sort

of this old man developer now.

You know, we started off with no version

control and then it

was a, what CVS or CSV

and then Mercurial and

then, uh, SVN at one point.

Uh, but I love that like sort of get

seems to have won the

space of, uh, of, uh, version

control.

It just seems so much easier now.

Um, then, you know, way back in the day

when it was sort of the,

you know, the merges and

stuff were just terrible and all that.

But, uh, um, I was sort of a random

tangent, but, uh, so going

back to the name, you said

the name came from sort of,

uh, uh, a call out to Husky.

Yeah.

And the name was like a hundred percent

credit to Nuno on the name.

I don't know how he just like pulled it

out of thin air

because, uh, he suggested, why

don't you make it a, into a CLI instead.

And like, yeah, geez, I

wonder what I would name that.

He was like, why not whiskey?

It's like, it was perfect because it's

pretty similar to Husky

and that's definitely how

it was inspired.

I don't know where he got

that name from, but props to him.

Well, so Husky, I'm, I keep thinking of a

dog, like a Husky dog.

Um, and then I assumed you were drinking

whiskey the night you

created this and that's where

the name came from.

No, I haven't developed

my palette for whiskey yet.

I've still got a very unrefined palette.

But uh, but you do have the logo there

with a little whiskey

glass, um, with a little

ice cube.

So that's pretty sweet.

Yeah.

And then I just, I just spell whiskey the

correct way, much too much to the chagrin

of J Mac.

He thinks I should be spelling whiskey

the other way, but it's,

it's just not the right

way.

I will die on this hill.

What's funny though, is if you Google

like Len Woodward

whiskey, like there's actually

like whiskey that comes

up, not the, not the project.

And you keep, you would think that like,

you know, that would be

sort of random, but it

was like, cause cause when I was doing

research, I was like, Hey.

And then it was like all these, I guess

Woodward and then Woodford

and you have all these other

different whiskey actual brands, um,

which is kind of funny.

Uh, but, uh, but who

did, who did your logo?

Did you design that one yourself or?

Yeah, I just, I just went in Figma and

tried to do something

a little bit stylized.

It was just a really

quick and dirty thing.

I think I was, it was me anyways.

Did I steal it?

I don't think I stole it.

I'm pretty sure I did it myself.

I'm not even sure anymore.

I don't know what I

have and haven't done.

If I stole your artwork, let me know.

I will give you money.

I was going to say it all, it all runs

together in the end on it.

But how's the, um, you know, as far as

the usage and stuff is,

is the community picking

up and using it or, um, yeah, I mean,

it's been a slow and steady grind.

Um, I think I'm up to like 38,000

installs or something like that.

And I'm up to like 160 stars on GitHub.

So it's not like a super smash hit, but I

think get hooks are

kind of a niche thing.

So not everyone is looking for it, but

every once in a while open Twitter and

someone's like, Oh, I

found this cool tool.

And I'm like, Oh shit, that's awesome.

I wasn't expecting that.

It was just a nice little surprise.

That is also, I've actually, I don't, I'm

trying to remember if I use get hooks

that often and I don't, I'm trying to, I

don't, I'm not pulling up anything out

of my mind that where

I've been using them lately.

Um, so may I need to actually research

more on, you know, setting those up and

give them a try cause I

get, just seems so useful.

Um, especially like the running tests,

like, well, you said

that was a pre-commit

hook, but, um, just even

the linter and all that stuff.

I mean, it seems super useful to have all

that just set up once.

And then everybody just, you know, has

the same stuff all the time.

Yeah.

It's funny every once in a while, I got

this little uptick and installs too.

Cause, uh, I think like every six months

or so, um, Roman Pronsky ends up writing

like a little tiny blurb about it in the

PHP foundation newsletter.

Like people are talking about this again.

I wonder what happened

and it's always Roman.

That's great.

That's great.

Um, so they, they do, well, I guess they

pick up that's on like the official PHP

news there, is that

what Roman writes that?

Or is that on the, um, I can't remember

if he does it through

the foundation or if

he does it through the jet brains.

I think it's jet brains, but yeah, every

once in a while

there's something on there.

And then, uh, and then yeah, every once

in a while there's another project too,

like FFmpeg stuff or a conductor was on

that people are really excited about.

But I still got some heavy work to do on

that before it's, before it's ready to

properly announce and release, I've got

my proof of concept in there, but it's,

it's gross.

Well, so I think you alluded to it

earlier, whiskey, you,

you think it's pretty much

feature complete or you got one, one or

more, one or two more things you want to

do to it before jumping over.

So there's one bug that's still, that's

still annoying me and

some GitHub, uh, some

git hooks will accept parameters and I'm

not set up to handle that.

And I just haven't been able to sit down

and properly crack this, this problem.

So where that becomes an issue is if

you're using an extension or a plugin,

like, um, Oh, what's it called?

It's like lint commit message.

So if you have a certain style that you

want your commit

messages to abide by, um,

it'll, it'll look at the actual message

and we'll do that, but I'm not sure how

to handle that yet.

The other thing that, um, that I had

fought with for a while was just an

architectural thing where it was really

gross the way I had to register

everything.

So I had a, like a shell script in my, in

my vendor folder that the

get hook would call that shell script

would then ask the Laravel CLI from

Laravel zero for a list of

the, the commands to write.

Then it would bring that back.

And if you're supposed to skip it, that

list will just come back empty.

But the reason I had to do that, that was

so that I was getting the

output as it came out.

Um, I ended up discovering the process

for sad has this TTY mode.

So it basically attaches the input and

output to the, to the actual

currently running terminal.

So it had a benefit of

being able to be interactive.

So if something stops and asks for user

input, you can do that, but it also

maintains the colors in the terminal.

And that was like a really

unexpected, nice side effect.

So you still get all like the, the green

checks and the red X's.

So that brought me like way

closer to feature complete.

I've just got that one

last little thing to do.

I'm pretty sure we're

even windows compatible.

It's been a while since I've tested that

out, but I'm pretty sure it works.

Well, I guess kind of eluding into that,

are you looking for sort of community

help on any of these things?

Or you think you're just going to knock

them out one day when you get some time?

Yeah, there's been, there's been like

three other people that just pop up

every now and then with a PR and like

most of the time they're, they're great.

Like they're just this really narrowly

targeted banger of a PR and like they

list the, the issue, they list why it's

an issue, how to fix it.

They got the fix in there.

And then every time I tag a new release,

I try to tag them so that I can show them

out and thank them and yeah, it's been,

it's been fun having a project that

other people care about, even if it's

just like this tiny little bit.

Yeah.

And, and to have people that commit and

do what you just said is,

is pretty impressive now.

You know, it's always great when somebody

does all that and it's really isolated

to the one thing that they're having the

issue with, you know, so, you know, that

was where I was going to, like, if, you

know, if you're listening or watching

and you know, you've not made commits or

pull requests to any projects, keep it

small, keep it contained and focused on

one thing, and then it's your likelihood

of getting it merged is way greater than,

you know, if you're

trying to tackle 50,000

files or anything else like that.

Yeah.

And if you are trying to develop a thing

and you're not really sure why, why

certain things aren't working, I do have

some hidden commands in there as well,

which you can usually find in the not in

the read me, but in the source.

So I've got like a whiskey audit command,

and that'll just give you a table that

prints out a whole bunch of the variables

that I'm using within all these different

classes, like where the composer home

directory is, where the project directory

is, where vendor things are being kept,

like, and then ways to determine the

platform and all that type of stuff, ways

to determine if whiskey is being run

globally or locally.

So if you're trying to add in a little

feature or a bug fix and things aren't

working, you got some

tools like that built in.

That's awesome.

That's awesome.

Well, I guess we'll kind of any other

sort of highlights or anything else,

you know, that we didn't, uh, why I

didn't ask you about

as far as whiskey goes.

Not that I can think of no.

And it's a pretty small tool.

So it's not really,

those are the perfect ones.

Yeah.

Yeah.

It's, uh, um, I forgot what I was trying

to say there, but yeah, the, uh, I like

the little small, well-defined tools, you

know, and you just pull them in and they

work and you don't really have to think

about them too much.

It just seems to,

seems to make life easy.

Yeah.

That's kind of the theme that my buddy Ed

and I are trying to take where we're

building a suite of

tools called scalpels.

And so there's meant to be just very

narrowly targeted sharp tools.

So each one just does

one thing and does it well.

And we're just going to try to have a,

like a suite of these ready to go for

a Laracon and see if

people are interested.

It's not going to be like this giant

revenue generator, but if we can pay our

AWS bill, I think that'll be fun.

Hopefully you don't get the dust.

But yeah, I like those

kinds of tools, just very small.

Um, there's, you're not having things

interacting with all

sorts of other stuff.

Limited complexity.

Yeah.

It's a good way to do it.

That's awesome.

So this scalpel tool you're planning

launching sort of right around

Laracon or sort of before or after.

We're not quite sure yet.

We don't even know if we'll have enough

tools finished yet, but, uh,

putting you on the spot there.

We got about four or five tools that

we're trying to get done in time.

I don't know if we'll be able to.

Um, so we'll see what happens.

Yeah.

That's great.

Well, um, or any, any other thing, you

know, maybe anything I miss,

anything else you want to say before we

close out this, um, this

creator series spotlight.

Um, yeah, go to get hub and

give me a star on whiskey.

It makes me feel good.

And then follow me on Twitter.

Um, follow me on YouTube as well.

I started making a couple of videos.

So if you just go to YouTube slash

artisan build, that's, um, that's

where I'm putting those videos out.

And yeah, just seeing those numbers go

up, it gives me the warm and fuzzies.

Yeah.

So those are wonderful.

And we'll be sure we'll have all those in

the show notes as well with links to

the repos, his Twitter, his YouTube and

sort of everything else.

Um, I think this is going to conclude

this, uh, episode and we want to thank

everybody for tuning in and watching.

And, uh, we will see you next time.

Thanks.

Thanks, Len.

Yeah.

Cheers.