β¬… home

An Issue with Issues

May 6th, 18
What's Locking πŸ”’? Β· Maintainer's Burden πŸ€— Β· Automate it? πŸ€– Β· Probot Β· Installation πŸ”§ Β· Made some Pull Requests! Β· Use in `babel/babel` Β· Todos Β· Other Ideas Β· Extra: Related Features

Here's a short story about discovering the Lock Threads Probot!

So you find yourself looking at GitHub notifications (yet again πŸ™‚).

github notifications page

Whether you're doing it out of obligation, or because you're doing it full-time, you may find it overwhelming to look through it all (every few months you do a "Mark all as read" but you just did it last week).

You start looking through some of these again, one by one.

closed-issue-notification

You already realize that it's for a closed issue, but you click it anyway.

You notice that someone has commented on an issue that was closed over a year ago.

Enter the maintainer's dilemma: Do you start helping them right then and there, by triaging it or trying to figure out the solution? Do you just say: "Please make a new issue, because this might be unrelated or out of date"? Do you shy away because you don't want to offend? Do you just ignore it and realize you probably shouldn't be looking at notifications anymore?

It's these kinds of notifications that make you question whether it matters if an issue is closed at all?

I think Dan puts it well here:

Maintainers are unlikely to want to look at closed issues (both in terms of time and how they try to help via the interfaces they use), and it can seem lazy on the part of the commentor if they think they can just add a "it still doesn't work" at the end. We need more context not less.

It's understandable; as a user, you find a bug or issue with how you use an open source project and you think, "hey instead of making a new issue, I can search through the repo and find something similar and figure it out from there!" However it doesn't match exactly what you want (since you might be looking for more of a Stack Overflow type thing) so you leave a comment saying "+1".

But as a maintainer, you might end up finding yourself wanting to click that "lock" button.

What's Locking πŸ”’?

lock-button

Locking was added on GitHub in 2014 (old discussion here).

In my experience, locking issues is something that isn't done very often, but it's really useful when needed. When a conversation is just getting out of hand or not constructive, you might temporarily/permanently lock an issue.

I just realized that in the process of writing this and checking the GitHub help articles that you can lock PRs and even commits?

I'd probably argue we should probably lock/remove comments on commits by default? Or make it easier to link/comment on associated PRs? I guess this related how we do changelogs as well, and maybe a way to response to a specific release about questions/bugs.

commit-comment

Actually, this makes what I'll be talking about next more relevant!

Maintainer's Burden πŸ€—

If you are using GitHub and checking notifications, you might notice a pattern: you may randomly get comments on items that were closed over two years ago. Maybe the codebase has long been rewritten, maybe the issue was fixed in a later version, maybe the issue is actually unrelated.

This is another case when a maintainer may want to prevent any additional comments on a particular issue: not to prevent discussion in general, but to have a clear distinction between issues. Unfortunately, the maintainer has to lock each issue manually. And even then you might feel bad, because "locking" to some users is perceived as "hostile" because it prevents further discussion (but only in that thread). And you're already overwhelmed by newly create issues let alone old ones.

To be clear, this is different from closing/locking an open issue or PR since that might just be a valid bug/request but low priority or just that no one is able to get to. Determining what to do with "stale" (or even what defines "stale") has pretty varying opinions (never close vs close after x days).

Automate it? πŸ€–

Your next thought might be: shouldn't we automate this?

I decided to look into this after seeing @mjackson's Tweet since I remember wanting a similar behavior and didn't recall an API being available for locking at the time.

I searched again and found GitHub added it as a preview API in 2016 and also added a lock reason in a preview API in 2018.

So has anyone done this already?

Probot

probot

Probot is a cool framework for writing bots (as a GitHub App) by @bkeepers and company at GitHub. It's a perfect use-case for this kind of issue.

Personal plug: if someone wants to do a contribution to Babel, I made an issue for converting our own custom bot to Probot 😁.

The Lock Threads Bot is a Probot app written by @dessant_ that automatically locks closed issues and pull requests after a period of inactivity.

lock-threads-bot

Installation πŸ”§

Installation is as easy as going to the install page and adding it to your organization or repo.

Currently, there is no real easy way to make this apply across all your repos, though you can use Probot's extends feature. I think for this bot-powered action it makes sense to just have the same config/behavior across all repos instead of needing repo-specific configs.

Now all that's left is to create and configure a lock.yml file inside the .github/ folder.

Some options (at the time of this article) are as follows:

# Configuration for lock-threads - https://github.com/dessant/lock-threads

# Number of days of inactivity before a closed issue or pull request is locked
daysUntilLock: 365

# Issues and pull requests with these labels will not be locked. Set to `[]` to disable
exemptLabels: []

# Label to add before locking, such as `outdated`. Set to `false` to disable
lockLabel: false

# Comment to post before locking. Set to `false` to disable
lockComment: This thread has been automatically locked.
# Limit to only `issues` or `pulls`
# only: issues

# Optionally, specify configuration settings just for `issues` or `pulls`
# issues:
#   exemptLabels:
#     - help-wanted
#   lockLabel: outdated

# pulls:
#   daysUntilLock: 30

Made some Pull Requests!

I was able to make two contributions! (Shoutout to Armin for being so responsive! 😁)

In dessant/lock-threads#3, I added a new feature so that when locking, the bot will automatically add resolved as the lock reason. This should give more context to anyone that stumbles upon the locked issue and might be confused why they can't comment anymore. I also pinged a friend at GitHub about adding outdated as a lock reason in the future.

In the meantime, I got a suggestion to use a label which in hindsight, is such an awesome and obvious idea! So dessant/lock-threads#4 implements just that: the ability to an outdated label after locking before the new lock reason is implemented.

lock-threads-babel

Use in babel/babel

For Babel, I didn't want to use the lockComment option because sending a comment would send an email/notification to anyone watch the repo or subscribed to the closed issue. As we enable this on the repo, the thought of sending 5k emails to my own "inbox" (or anyone still watching) seems totally unnecessary.

While it makes sense to do this silently for all the old issues, it may, howver, be a good idea for new closed/stale issues?

# 3 months is a pretty long time
daysUntilLock: 91
# Don't want to notify/email
lockComment: false
# Only issue with PRs are fixed
only: issues
# Give context into what is being locked
lockLabel: "outdated"

Todos

There is currently an issue regarding locking PRs, so I've only enabled it on issues in Babel for now: https://github.com/dessant/lock-threads/issues/5.

outdated-babel

At the time of this article, we have ~4.5k closed issues with about ~1.5k of them marked as outdated/locked, since the bot only does ~30/hour due to rate limiting! There's probably some improvements to the way it tries to filter out issues so please try it out and contribute back!

Other Ideas

Auto-lock "heated" discussions: You could probably also make a bot that auto locks a thread (with a lock reason of too heated) if there are too many comments from different people in a short amount of time (say 24 hrs). It shouldn't be too difficult to differentiate between a regression where people complain vs. something like a name change given the nature of the issue (created by a collaborator, can filter by labels, etc).

GitHub has recently added a few tools to help maintainers that you may or may not have used yet!

Hiding Comments: While editing and deleting comments has been around for some time, it can sometimes be perceived as antagonistic. Hiding Comments was just added as a new feature to help make looking at issues/PRs easier by keeping the discussions relevant.

Temporary Interaction Limits: Instead of locking an issue temporarly, you can now do this across the whole repo. So even if a single issue is blowing up and you want to prevent spam/new issues until it dies down you now have a few options. You can it to only existing users, only prior contributors, or only collaborators.

Archiving a Repo: There comes a time when you may want to deprecate a repo, move a repo into a monorepo, or just not want any further activity. Previously, you had to decide whether to just unwatch the repo or just delete it entirely. Archiving a repo now allows you to make it read-only so that links to previous issues/PRs still work and people can still view the readme/docs/etc but it's clear that it's frozen.


Thanks to Brian, Nadia, Tierney, and Michael for reviewing!

If you like this kind or writing and want to support that or my open source work, check if you'd want to donate to my Patreon. I'm trying to to this full time now!