pre-commit started as a framework for running linters and code formatters during git actions via git hooks. It’s grown and expanded and now supports an extensive list of languages and actions and manual running of actions. But even at it’s core, it’s great for letting computers nitpick about whitespace and formatting, so that code reviews can focus on architecture and design.

Anthony Sottile discusses pre-commit, for using locally by developers, and pre-commit.ci, which can run actions during merge requests.


Transcript for episode 157 of the Test & Code Podcast

This transcript starts as an auto generated transcript.
PRs welcome if you want to help fix any errors.


00:00:00 Pre commit started as a framework for running Linters and code formats during Get Actions via Git hooks. It’s grown and expanded and now supports an extensive list of languages and actions and manual running of actions. Anthony satelli discuss this precommit for using locally by developers and Precommit CI, which can run actions during merge requests. This episode is sponsored by PyCharm and configur.

00:00:27 Config.

00:00:27 Cat is a feature flag service. Easily used flags in your code with Config. Cat libraries toggle your feature, flags visually on a dashboard, hide or expose features in your application without redeploying code, set targeting rules to allow you to control who has access to the new features. It allows you to get features out faster, test in production, and do easy rollbacks with Config. Cat, simple API and clear documentation. You’ll have your initial proof of concept up and running in minutes, whether you’re an individual or a team. You can try it out with their forever free plan or get 25% off any paid plan with the Code Test Encode 2021 release. Features faster with less risk with configuration. Check them out today at configcat.com.

00:01:27 Welcome to Testing Code.

00:01:37 Let’s talk about Precommit.

00:01:38 Sure. So the idea behind Precommit is well, the original idea behind Precommit was that it was a GitHub runner, but you only had to manage a small set of configuration and it would install and run all those tools for you in a bunch of different programming languages.

00:01:57 So despite Pre commit being written in Python, it supports like eight or nine native programming languages at the moment. So Python, JavaScript, Ruby, Rust, Go, you can run Docker files. It has a portable Grep alternative.

00:02:14 There’s a whole bunch of languages and it’s really easy to plug into. It supports the. Net framework first here, which is like a Java Package Manager JVM package Manager. It has a whole bunch of language supports. And the big difference between other tools is Flaky will manage and install all these tools for you so your developers don’t have to worry about oh, do I have the wrong version of Ruby? And I have the wrong version of this particular Linter code for a matter of tool installed? Like, no, you don’t worry about that freaking it. Just manage it for you and you don’t have to think about it.

00:02:50 Okay?

00:02:51 It has spread a little bit beyond the initial Git hooks idea. You can use it without involving GitHub at all. Just as a printer and code formatter runner, you can also use it as a CI tool, which runs your code formatters and printers, and make sure that your code stays up to date with your particular style.

00:03:11 Because the configuration file is versioned, you can make lockstep changes to your renters and code formatters. You don’t have a situation where like, oh, we’re changing flight eight to 39 everywhere, and every repository of your company is suddenly broken because it doesn’t fit the latest set of Linch rules or whatever. But no, you can change that version with the code bumps that you’re making. So it allows you to keep things in line.

00:03:41 And so it doesn’t have to be just one configuration, right? You can have these pre commit snippets or something.

00:03:52 So it kind of works like that. So the way that you install tools is it uses git repositories as its lowest common denominator, because you can’t really have higher level representation than that. That works for every different programming language. And inside each remote repository there’s a small bit of configuration which sets up sensible defaults for that tool. So for instance, the Flaggate tool runs flight gate against Python files that is encoded in a little YAML file that sits inside flight Gate’s repository. And if you want to use Flake eight, you just reference Flakegate and a version number and the hook ID that you want to use from that, and it will include that base configuration. And then you could override it if you need it. So you can override it with inclusion or exclusion, or make it run on different file types, or have particular command line arguments, or whatever you need to do to extend that tool.

00:04:48 And so what your configuration file? What your pre commit config tends to look like is it’s a list of repositories that reference remote tools to run all the things that you would want? There’s also an escape patch. If you don’t want to reference remote repositories, you can use what’s called the local repository. It’s kind of a special schedule that lets you escape from the repository based installation. And there you can leverage the package managers for each project or for each language. So if you wanted to use Pip directly, you could set up a local hook.

00:05:23 Of course, you don’t get all the niceties of the default base configuration. You have to specify every bit of the configuration yourself.

00:05:30 You can also set up just like system hooks or script hooks, which either live in a repository itself or are externally managed tools. So you can still have the old school systems team that manages your tools on your machine and upgrade those auto band with your configuration. You just reference them globally using pre commit.

00:05:51 Okay, in that case, it’s mostly good for standardizing all of the weird edges around git that are encoded in pre commit code base for like managing merge conflicts resolution Linter running that one’s a common problem when working with other Get frameworks like the naive approaches just run against everything in the merge conflict, which most of the time isn’t the code that you touch. You don’t care about that other file that someone else introduced to Linter, and you’re really concerned with the files that conflicted the files that I touched.

00:06:26 Another thing that it deals with, it’s kind of tricky, is applying patches to partially staged commits. You want to make sure that you’re only lifting the stuff that’s about to be checked in and not the stuff that’s not going to be checked in. You can have both false positives and false negatives based on those unstaged contents. Recommend is careful to stash those changes out and only check the ones that are about to be checked in.

00:06:54 Of course, you end up in a whole different set of complicated problems, because what if the stash then conflicts with the changes that were made?

00:07:03 There’s clever roll forward and roll back cases for those.

00:07:09 That sounds complicated. I’m glad you came up with it instead of me.

00:07:13 I’ve learned so much about Git and different programming languages, package managers, and how to bootstrap all these things from nothing, and I found close to ten or $20 and get so far just from the crazy edge cases that have come up as part of this project. I’ve learned a ton building this, and there’s a lot of knowledge that’s encoded in the tool.

00:07:41 This episode is sponsored by PyCharm. I write a lot of code. Pycharm saves tons of time there, helping with code hints and being able to quickly jump to any file or any function super fast. And tests, of course, great for writing and running tests, but I also write a lot of markdown files in PyCharm. I love the preview pane when I need it, but what I really love is that PyCharm automatically turns on a grammar and spell checker for markdown files. This isn’t just a convenience or an ego thing. Pycharm is helping me communicate more effectively. Thank you, PyCharm. Avoiding miscommunication saves tons of time. Go to testandcode.com PyCharm, try it out and see where PyCharm saves you time.

00:08:28 So a lot of people will probably run this tied to some get events, though, right?

00:08:37 And from its name, the first one you thought of was precommit.

00:08:42 Yes.

00:08:43 But there’s other places you can tie in code. Where can I run code in different parts of my work?

00:08:49 Yeah. So I think there’s something like eight or ten giths that are configured right now, and there are some that have not been implemented yet. It’s really been if somebody has a use case for this, they’ll come along and implement that additional get hook.

00:09:03 Okay.

00:09:04 And the most popular ones are precommit. Of course, there’s also pre push which runs as you’re pushing a branch.

00:09:13 There is Commit message and Prepare Commit message, which are fired when you’re making the message for a commit. So it allows you to make sure your ticket numbers and their auto format the ticket in or things like that, or enforce your messaging style declarative sentences, blah blah blah.

00:09:32 You can run linters and stuff off on your messages.

00:09:35 Yeah, it’s actually pretty popular. I find it really annoying, but it’s pretty popular. People do it.

00:09:44 What else is there? There’s some for repository States, so there’s post checkout, which runs after you switch branches or after you merge a particular change or do something like that, which people often use to synchronize a generated file in the workspace or like, make sure that IDE metadata is up to date or stuff like that.

00:10:11 What are the other ones?

00:10:13 Let me just look at the docs really quickly.

00:10:15 I mostly just use the pre commit stage and don’t really worry about the rest of them, but other people use the rest of them. Okay, so there’s commit. There’s merge commit, which handles during merge. We talked about push check, the prepare commit message, commit message. We talked about post checkout. Oh, post commit.

00:10:32 Despite the tool being called precommit, there is a post commit hug that is also supported. Post commit. You can’t really do any validation, but again, you could generate metadata or do whatever you need to do afterwards.

00:10:44 There’s also post merge. And then there’s a special stage called Manual which allows you to invoke precommit invoke a tool that doesn’t run at any get stage, but you might use it as a one off execution.

00:10:58 And that’s where pre commit becomes more of an execution engine and less of like a kit hooks tool.

00:11:04 Well, that’s actually going to be my next question if I just have like, this sounds interesting to me. So there’s times where like in a post commit or maybe a post merge or something like that where it might make sense to me to kick off like a notification message or something to people. Can I write my own tool and hook it into precommit then?

00:11:29 Yes, absolutely. So there’s the classical repository based tooling where you would set up a get repository, write an executable, write a little precommit hooks, YAML file that says I provide this hook, and then you can plug that into your consuming repository. This allows you to have a reusable tool. If it’s a one off tool, it probably makes more sense to write that code directly in the repository that you’re worried about and use a local hook to reference that. But yeah, anyone can write their own set of hooks, basically just providing the necessary metadata to make that happen.

00:12:05 And I can mix and match in the configuration. I can have some tools that are get based hooks and tools and then others that are just my own and stuff. Yup.

00:12:17 Yeah.

00:12:18 And you can mix and match what hooks you’re targeting as well. So you can have your pre command on pre push hooks live side by side. You can have commit message hooks configured directly as well. And pre commit smart about finding just the ones that satisfy that particular stage and running them.

00:12:35 Now for Python projects, let’s say I want to try this out on a project and I just, you know, I’ve listened to this episode and it’s kinda I kind of understand what’s going on, but I don’t know the formatting or anything. Is there a good bootstrap way to just like, hook up a couple of these tools to my project and try it out yeah.

00:12:59 There’S a quick start guide on Precomment.com. That’s Precomment.com, the other website is owned by some weird construction site that I’ve been trying to Ping the owner about for a while and pay them good money to take it, but we’ll see what happens with that. But yeah, there’s a quick start guide on Precommit.com, which walks you through setting up a basic pre commit configuration that this particular configuration is very simple. It includes black and some white space fixers, and it guides you through setting up the basis to get started. What I would actually recommend is finding another repository which already configures precumit, figure out what tools they’re using, and copy paste their config. There’s also a list of supported hooks on the pre commit website as well, which is basically just a large catalog of things that you might want to use for Python projects. What I recommend is kind of three or four tools, one an import sorter. So either I source or reorder Python imports a code formatter, things like black, auto, Pep, eight, or Yapf and a checker Flake, usually.

00:14:08 And you can also layer in your white space, checkers your YAML, checkers JSON, checkers, whatever you want to do. But that’s usually what I recommend for getting started. And if you want to look at any one of my repositories, they’re all configured with free commit and have a whole bunch of other related tools as well. So one example is High Upgrade, which is a tool which takes old syntax and upgrades it to newer, nicer syntax. So for instance, it will take format calls and upgrade them to F strings. If you’ve told my upgrade that I want Python three, six plus, for instance, or it will take like four loops that can be converted into yield from things like that.

00:14:54 Okay, well, let’s drop I picked a bad example, I think, because I thought, well, I know that itest uses Precommit. Let’s see what theirs is. And it’s a little over complicated. Yes, but it is kind of neat. It has some of the common ones, but then it also has some local tooling. They have some local hooks, yes.

00:15:17 So we’ve set up an Rst Linter because I’m terrible at writing Rst. I don’t know about you, but I find it really hard to write correctly.

00:15:25 We also have some stuff that makes sure that the change logs are in a good format.

00:15:31 Again, this is a me problem. I would type those file names pretty often, and that would cause them to not end up in the release. And so we made a little filter to make sure that you match the exact file name format and we end up in the right place. We’re also deprecating some internal stuff. So like Pilot, we’re trying to excise from the code base, and so we’re working through making sure that that doesn’t exist anywhere.

00:15:54 And those are kind of our special one off things there.

00:15:59 So Where’s a different example that might be easier.

00:16:03 Precommit has a very straightforward look at GitHub precommit.

00:16:10 Yes, pre commit, pre commitment.

00:16:12 I guess it has a few things that you wouldn’t necessarily use in another project.

00:16:17 The first precommit hook was actually pre commit itself a little self referential, but it does the self reference there. So maybe Precumentpregmenthooks is a good starting point, because that’s a very straightforward one.

00:16:37 It, of course, includes my particular preferences for style, which may not be in line with yours, and so feel free to swap out whatever tools you want. Like, I prefer Auto Pep bait over Black. Personally, I guess my Black equivalent is called Ad trailing. Comma, which existed several years before Black and encodes a very particular calling construct. But it doesn’t do all the other stuff that Black does.

00:17:02 Yeah.

00:17:03 Okay, so I had a relationship with Black.

00:17:09 Now my first reaction is I think I like almost everything it’s doing, but it’s the almost part that caught me. And I particularly kind of like single quoted strings instead of the double quotes.

00:17:23 But it really wasn’t a mountain that I really wanted to battle for.

00:17:29 Yeah, I usually find that I think Black is an overwhelmingly good thing for the community.

00:17:38 I don’t use it myself because I don’t like some of the minor things, but I think the goal of eliminating conversations around style preference is great.

00:17:52 The jury still out on whether it saves time because it should save time by avoiding these conversations. Of course, it seems to trigger more conversations about like, why I don’t like Black, so we should use something else and then, like, that whole rabbit hole.

00:18:05 Okay, let’s talk about your tools, though. So Auto Pep Eight you use instead of Black? My concern would be, is Auto Pipe Eight maintained as well as Black is? So is there decent maintenance on Auto Pay?

00:18:19 Yes, I know the maintainer of Auto Pippa. They’re very good about keeping things up to date. That said, Auto Pipe Eight does a lot less than Black. It is mostly responses to error codes that Pi code style emits. Okay, unless it’s an error in the Pi code style tool. Auto Paypate tends to avoid changing your code.

00:18:40 But that might be a good starting point. So to start with, Auto Pep aid on like a project that’s already existing that would be fairly non political to add that to something.

00:18:53 Yeah.

00:18:53 Like, usually when I talk about adoption of Eight, my recommendation is like run Auto Peppa on your code base just to start with, because it’s going to save you a lot of time worrying about individual lens rules. It’ll solve like 80% of them for you.

00:19:07 Okay. And then what’s the import sorter you use?

00:19:13 I wrote my own import sorter called Reorder Python Imports.

00:19:16 That’s what Amen.

00:19:18 Yeah, I like non silly names. I tend to prefer like, this is what it does. Of course, Pre Commit is a terrible name, so I’m not exactly perfect about it, but Reorder Python Imports was written mostly with pre commit in mind. The original idea was that it would notice the structure of your repository and know which things are system, third party and first party imports.

00:19:45 And at the time I want to say Isort was GPL, so I didn’t want to contribute to it because I wouldn’t have been able to use it at work. So I wrote my own clean room, unrelated implementation of Fab.

00:20:01 Okay, but Iceor is another common one though, right?

00:20:04 Yes, iCERT is another import sorter. It has a lot of configuration options, so it’s a very configurable import sorter. You can pick a number of different styles and a number of different options for it.

00:20:18 And at the time it didn’t support discovering the structure of your repository, so it didn’t really know what was first party versus not. So you have to manually configure all that.

00:20:29 But the latest version of Ice now does essentially the same work that Reorder pipeline Imports does, so it figures out your repository structure and can order things properly.

00:20:41 Funny coincidence. I actually work with the maintainer of Icehort at Stripe.

00:20:53 Have battles on this.

00:20:54 I mean, no, I use my own thing. He uses his own thing. We did talk a little bit about some of the strategies there.

00:21:03 My initial reason for writing we ordered Python and Prints was due to licensing. I sort of actually relicensed since that happened, so a lot of my original reasons for forking off my own project are no longer super relevant.

00:21:23 Okay, one of the things is the configuration. I can use Isort without any configuration.

00:21:27 Also, you can. However, it won’t necessarily play nicely with the rest of your tool. So like I sort out of the box doesn’t play nicely with Black reorder by then, imports does.

00:21:37 I don’t know of any incompatible tools with it at the moment, other than I sort.

00:21:43 Okay, well, that’s a benefit. And then checkers. You’re using Flake, is that right?

00:21:50 Yeah, I’m using Placate. I’m also using Mypi, which is a type checker. And I’m using a bunch of one off checkers. Like I have adjacent checker. I have a checker for large files. I have a checker for YAML. I have a checker for checking and debug statements. How many times have you shipped an import, PDB or a Breakpoint to prod? This will check prevent that from happening.

00:22:14 I also have a thing that enforces a naming convention on my tests.

00:22:20 What’s that called?

00:22:21 This one is called Name Tests Test. Again, like my very convenient naming of tools, that one comes from pre commit hooks directly. So if you use precumit precomit hooks, you’ll have that one. But it enforces. Like you can either force having test at the beginning or having test at the end of your file names. I prefer test at the end because then tap completion works, but teach their own.

00:22:46 Do you write the name test at the end of it.

00:22:49 Yeah. Well, otherwise I’m in a directory and I go to type, like the module name and it’s. Oh, wait, it starts with test. I have to Backspace type test, press tab twice, then type the module name. I find that really annoying.

00:23:01 Okay.

00:23:07 No, it’s all good. It’s interesting. And I think it’s neat that I definitely want to grab some of those because we have a few JSON files that we use for various reasons during testing, and we check them into the ticket.

00:23:23 Yeah. The number of times we broken Prod from shipping a bad YAML file at Yelp was way too high. So we added a bunch of these hooks to validate YAML syntax before deploying.

00:23:35 Now one of the concerns might be, let’s say I’m running on this stuff a lot. Like people are hitting this, a team is hitting this a lot.

00:23:46 Is there any caching going on?

00:23:48 Yes. Premium cash pervert. Well, it’s actually a complicated caching scheme because it’s really hard to get correct, but it uses, I think, a five couple of things. So the repository itself, the version it’s at, the language it’s using, the language version it’s using, and any additional dependencies that you’re pulling along into that, and it’ll catch that across a machine. So if you’re on a single machine, well, I guess it’ll cash it per user on that machine. So if you’re using check YAML from pregnant hooks, you’ll have one version of that on your host per version.

00:24:27 And it’s pretty good about deduplicating. And my recommendation is to just continually auto update to the latest version, which will minimize your cash size, because everything will be on the latest.

00:24:38 What do you mean by that?

00:24:40 Prickman has a convenient command for upgrading the versions of everything. So you can run precommitted auto update, and it’ll just take the versions that you’ve encoded into your config file and dump those to the latest tag.

00:24:51 Okay?

00:24:53 Right. And then one of the other things is so I install pre commit. I configure it with something. I copy somebody’s other YAML file, which I don’t think anybody actually writes YAML. I think everybody copies YAML from somewhere else.

00:25:10 Human writable, aka human copy pasteable.

00:25:18 But normally, like, let’s say I hook it up to a commit hook, for instance, or push hook.

00:25:27 It’s only going to run on stuff that changed, right?

00:25:30 Yep.

00:25:30 So I really want to run it once, at least against everything.

00:25:35 Yes. So there’s a pre commit run allfiles, which I recommend whenever adding or removing a tool.

00:25:41 Okay. And that’s listed in the quickstart.

00:25:45 Yes. That’s the optional last step of a quick start.

00:25:50 Run it against your existing code and make sure that you’re already adhering to it.

00:25:56 I like to hook up a handful of tools that I don’t really need, and some that I do, some that I don’t, and then so that I can run this whenever I want to. When things are not going well during my work day. And I can run this and I go, well, this works.

00:26:11 Still, you can also run pre commit through talks, which works well as well.

00:26:17 You can get talks to run pre commit.

00:26:19 Yes.

00:26:20 Okay, well, I guess you could, right? It just calls it, right?

00:26:24 Yeah.

00:26:25 Before pre commit CI, which we haven’t got to yet. Before pregnant CI, I would run a talks job that ran pre commit, run destroy files and desktop show diff on failure as well, because that would be easier to debug at CI.

00:26:40 But yeah, that’s how I used to do it.

00:26:42 Let’s do precommittee CI. Sure. What’s this?

00:26:45 So the idea behind Premci is it takes all of the good parts of pre commit. So installing and running tools and all that part and build the CI system around it. So previously I would run pregnant in talks in CI and it would tell me a past fail about whether things adhere to code style correctly.

00:27:08 Wait, I got to back up a little bit. Why do I need that? If I’m running it before I commit it, how could it break in the CI server?

00:27:16 So get hooks are all optional opt in client side hooks. So there’s nothing that actually enforces that. All of your users are using this. And especially when you’re working with open source projects, you don’t really expect to drive by contributor to set up all of your developer tooling. Like they might not even run the test, they might even write any tests, they might not run the Winters or code formatters, they might just commit their change from the GitHub UI and move on with their life.

00:27:45 And so premium CI is kind of aimed at two types of users. One is like ensuring that in every case the code base still adheres to all the style, and to the set of individuals that don’t run the developer tooling that would do this stuff for you.

00:28:03 Okay.

00:28:04 And it’s kind of just like an actual gaining mechanism to make sure your code stays up to style. There are also situations where like resolving merge conflicts you run to verify. Sometimes there are some cases where you would intentionally avoid as part of your workflow the developer tooling. I mean, another one is like you’re on a work in progress branch and you’re just trying to commit something you don’t really care about whether it appears to style. But when you finally go to integrate that branch, you want to make sure that it does inherit a style. So there’s cases where you wouldn’t run the tools.

00:28:36 But pregnancy, it basically takes what I used to run in talks in GitHub, Actions or Azure Pipelines or whatever, and builds an app around that. And it also provides some much nicer things than that. So if your code was not formatted properly, which happens a surprising amount in open source pregnancy, I will take that and just commit it directly to your pull request. So it’ll auto fix a pull request that’s not formatted properly.

00:29:07 I talked about that cash before. It’s really good about sharing that cash across all the users so that you can get really, really fast runs just because someone else uses that tool. Whereas if you’re using sorry about that. If you’re using a kind of classical CI tool, you would manage caches per repository and you wouldn’t get to share stuff, and it would be way slower and way more work and way more data storage to maintain that. So what Premier CI does is it shares those environments across all users, so it’s much faster.

00:29:43 Also, it’s optimized for this specific workflow so it can do a lot of stuff that makes running much speedier. So the average time to start is under 2 seconds for pre commit CI, whereas with get up actions it’s like five or 6 seconds and get labci it’s three minutes or something. Ridiculous. Travis CI it’s a minute or so, but pregnant CI can be very, very quick about this. Sometimes the two year runs I’ve seen runs where I push a pull request and precommit CI completes before GitHub actions even starts.

00:30:20 So if I’ve got a project that has a precommitaml or something, do I need to set up a different one?

00:30:27 No. It works completely off of your existing precommit config, so you need zero configuration to get started. You really just set up the GitHub appointment a repository and it does the rest. There are some CI specific configurations that you can set up if you need to make changes, although the default should be reasonable for most use cases.

00:30:46 Okay, but I’m still being dense, but let’s say I’ve just set up hooks to go to my pre commit as a pre commit or pre push hook. Those two events aren’t happening on CI. I’m doing merges and stuff.

00:31:01 So currently pre commit assumes pre commit it by default. When you run pre commit run, it assumes the pre commit stage, and CI basically takes that same approach as well. So anything that you’ve hooked up for the pre commit stage will run in CI.

00:31:20 Okay, good.

00:31:23 It essentially runs precommit run all files.

00:31:27 It’s a little bit different behind the scenes, but that’s essentially what it does.

00:31:31 Okay, that’s going to catch everything and it’s good. And then does it report to the person that tried to commit?

00:31:39 So what it does is it’ll report a GitHub status, so your pull request will be green or red based on that, but it will also push to the branch if it needs to auto fix it. So if there’s a change that needs to be made from a code format or whatever, it will just auto fix the pull request for you.

00:31:55 Okay, again, sorry, I’m being able to.

00:31:59 No, that’s fine.

00:32:00 Confused.

00:32:02 Somebody does a pull request, does it run on the pull request branch.

00:32:08 Then or so it merges the pull request branch with the main repository and checks that.

00:32:13 Okay.

00:32:14 Yeah. Because your branch might be out of date.

00:32:17 Okay.

00:32:18 And GitHub does that merge automatically for you. So I just wait for that merge to be successful and then precommittee I will run across that.

00:32:26 Okay. And so let’s say somebody does something that breaks that. And so the person trying to do the merge request will they can check it to see if it finished or something.

00:32:38 Yeah. The other thing that pre commit CI does, we mentioned earlier that you encode the versions of tools in a file and there’s a developer tool to run precommit auto, update and upgrade those versions to the latest.

00:32:50 Precommitci will run a periodic task that does that auto updating for you, similar to like a Dependabot or something. And it’ll send you a currently weekly pull request to make sure those are up to date. It actually ran, I think 30 minutes ago.

00:33:08 In a bit, I’ll make sure that my phone going off isn’t a page for error, but I’m pretty sure there’s a text message, so I should be fine. Yeah, I think we’re good.

00:33:18 Do you need to go?

00:33:19 No, I think I’m fine.

00:33:20 Okay.

00:33:21 Worst case, like, there isn’t an SOA. So within like 15 minutes, I’ll check on it. Anyway, I can always rerun any failed runs, so that’s easy. How do people find precommittees so they can go to precommit CI kind of fancy international domains?

00:33:38 Nice.

00:33:40 And then I can run it against any repo.

00:33:44 So it currently only supports GitHub.

00:33:48 There are plans to add other version control providers in the future, but for now the first version is entirely GitHub, and right now it is only public repositories.

00:33:59 I’m currently working with GitHub to enable a paid version that would work on private repositories.

00:34:04 Okay.

00:34:05 But soon, maybe by the time the podcast comes out, it will be available.

00:34:09 Well, I hope so, because I want this to be I can’t imagine not you running this. It just makes sense.

00:34:17 Yeah. It’s also stupid easy to set up.

00:34:21 You’re already using pre commit. Just. You might as well enable pre commit CI.

00:34:25 Okay, so let’s say I do, but then I like for some reason don’t want to anymore.

00:34:31 Yeah, you can just uninstall the app and then that’s done through.

00:34:37 There’s a little Manager pausitories button on pregnancy I, which will take you to GitHub to add or remove repositories.

00:34:45 Yeah, a lot of this stems around.

00:34:50 I mean, it’s making sure your code is correct, but also things like style and you broke the tests and that isn’t covered by this. But you did something wrong. It’s way easier to get a computer to tell you you did something wrong than the person, I mean, emotionally, don’t you think?

00:35:12 Yeah. Let me read the tagline that someone in my Twitch chat actually came up with that I really like. And I think it encapsulates this idea perfectly.

00:35:22 Developers spend a fair chunk of time during their development flow on fixing relatively trivial problems in their code. Precument CI, both enforces that these issues are discovered, which is opt in for each developers workflow via precommit, but also fixes the issues automatically, letting developers focus their time on more valuable problems.

00:35:40 Wow, nice copy.

00:35:42 Yeah, I really like that. The big selling point that I’d use when talking about this tool, both pre commit and precumci is like, you can spend your time in a code review, nitpicking white space and commas and operator positioning and all that other stuff. Or you can set up a computer which is very good at identifying these things and spend more of your time in code review, focusing on architectural and design problems instead of nitpicking style.

00:36:11 I think that’s like the big selling point of Linter’s code formatters and this entire genre of tools.

00:36:18 Yeah.

00:36:19 And also it just is pleasant.

00:36:23 I’ve had style guides that are like, there’s no way you could write a tool, or maybe there is a way to write a tool for it, but they’re so specific to a company and just have it’s actually refreshing in the Python world to have a fairly limited number of options.

00:36:43 Essentially, most people don’t care. Just tell me how you want me to style the code and I’ll do it.

00:36:50 And then actually some of the defaults that we’ve chosen in Python are just pleasant to use anyway, like snake case and stuff.

00:37:01 And then there’s like 10% of us that actually care about code style and we all have our own style and it just doesn’t make sense for all of us to be writing our own style guides, for sure.

00:37:12 Yeah. The thing that I often bring up in code reviews, like if I encounter someone else or myself reaching towards like, oh well, this could be if you adjusted the spacing or something. If I’m ever like, even starting thinking about that thought, I’ve instead shifted to saying like, how can we write an automated tool to enforce this style? And if we can’t, then I just don’t even mention it at all.

00:37:36 If it’s not important to the architecture of the change, it’s not worth my time or the author’s time for bringing up something like that.

00:37:44 Okay, I’ve got one. I’m making this long, but actually I am part of the 10% that cares about this.

00:37:50 I am too one of the things that violates all of these style guides that I still do sometimes and I don’t really know how to turn off the reformatters from doing it.

00:38:06 Let’s say I’ve got like, what is essentially a bunch of maybe a list of lists or something, and it really is easier to read if I align all the commas up so that it looks like a table. Yes, but that violates all these black and all that stuff. So is there a solution to this? Or should I just stop liking to make things tables.

00:38:36 Yeah, I don’t have a good solution for that.

00:38:38 Okay.

00:38:38 I also understand the idea of lining stuff up and it does look nice when it’s manually formatted that way.

00:38:46 I have not found a good combination of things that allow something like this. I mean, with black, you can do format off, but that doesn’t prevent your winter from saying, oh, your white space is messed up.

00:38:59 I’m actually kind of pondering some ideas inflict to enable something like this which would allow it would allow a plugin to filter error codes in the output such that you could, say, inside format blocks, ignore white space change or format off blocks. You could ignore white space based things and so that would give you a way to opt into that sort of idea. But I don’t have any solutions today. Okay.

00:39:27 Well, I mean, it’s not a common thing. It’s not like all over the place. I’m violating this.

00:39:33 And it’s not just because I think it looks nicer. It’s really intended to minimize human error.

00:39:39 Yeah, it’s a maintainability improvement. I agree with that. Another thing you could do is sequester it to a particular file. So if you have, like a data tables file or whatever, I mean, that’s probably poured in for a file. But you could put your particular thing in a particular file and both pre commit and flight eight have exclusion options. So you could say, like in precommit you would just say exclude and then it wouldn’t run the particular tool at that. In flankate, you can use profile ignores to ignore particular error codes in particular files. So if you have one file that violates one rule that you want to enforce everywhere else but not in this file, you can turn off on a per file basis if it’s one line saying you can use no QA, but putting no QA on 20 lines is not the best.

00:40:28 Okay. Thanks a ton for talking about this again. So people want to check out normal precommit it’s at precommit.com and precommit. Ci is your CI tool and then people can just look Google all the other stuff like eight stuff.

00:40:47 Yeah, sounds great.

00:40:49 All right. Well, thanks a lot for joining the show and I hope you have a great day.

00:40:53 Yeah. Thanks for having me on and I hope your day is great as well.

00:40:57 Thanks.

00:41:04 Thanks, Anthony, for all you do, for the Python community, for awesome tools, and for coming on the show. Thank you, Patreon supporters join Them at testandcode.com support. Thank you, config cat for sponsoring check them out at configcat.com. Thank you, PyCharm. Check them out@testincode.com, PyCharm. Those links, of course, are in the show. Notes@testandcode.com 157 that’s all for now. Now go out and limp something.