Automating your development with Dependabot, Auto Assign, Merge Freeze, Husky and Scheduled reminders.
The idea of this post is to introduce some of the tools and integrations that made our development life easier.
Most of these are pretty straightforward to implement into your workflow but for the ones that have a couple of gotchas I might write an extended introductory version for that tool alone.
1. Dependabot
Automated dependency updates
Dependabot creates pull requests to keep your dependencies secure and up-to-date.
Dependabot is dead simple and their punchline clearly states what it does. We started using it a couple of years back, a bit before Github acquired it.
The main reason was that, at the time our current team took over the Front End division, there were a lot of outdated dependencies which we wanted to update and wanted to keep up to date. We found Dependabot, added it to our projects, and let it do its magic ever since.
Now it's natively a part of Github, so adding it is even easier than before. You can check out how to set up Dependabot, but in the end you'll end up with a dependabot.yml
in your .github
folder.
Ours looks like this:
version: 2
updates:
- package-ecosystem: "npm" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"
open-pull-requests-limit: 2
commit-message:
prefix: "BleedingEdge"
The only thing that differs from the default settings is that we:
- chose npm as our package-ecosystem
- limited the number of open PRs to 2
- added a prefix for the default Dependabots commit message (you'll see later why)
Four years back we had 3 frontend repos, now we have around 14 active ones. Manually keeping every dependency up to date would be extremely time consuming. Dependabot helps a lot, but it still takes time to review and merge all the PR's. We usually take a day, after our weekly release, to merge Dependabots pull requests.
Writing this got me wondering if we could set the bot to open PR's only on major, minor or patch versions and indeed the feature was requested in 2018 and got released a few months ago and now you can ignore SemVer updates of your choice. Check out GitHub's blog post for more.
2. Auto Assign
Add reviewers/assignees to pull requests when pull requests are opened.
So you opened a pull request, you need at least two approvals and you need to add reviewers to your pull request. Every single time.
Things are pretty obvious, let the bot do it.
Setting up is easy, go to probot.github.io/apps/auto-assign hit the Add to Github button and don't ever worry about manually adding reviewers!
Similar to Dependabot, you will end up with a auto_assing.yml
file:
# Set to true to add reviewers to pull requests
addReviewers: true
# Set to true to add assignees to pull requests
addAssignees: false
# A list of reviewers to be added to pull requests (GitHub user name)
reviewers:
- teammember1
- teammember2
- teammember3
- ...
# A number of reviewers added to the pull request
# Set 0 to add all the reviewers (default: 0)
numberOfReviewers: 0
# A list of keywords to be skipped the process that add reviewers if pull requests include it
skipKeywords:
- BleedingEdge
We have nothing out of the ordinary here. We are utilizing the skipKeywords option with the BleedingEdge keyword that if you remember Dependabot prefixes to each of its pull requests. We handle the pull requests Dependabot opens a little bit differently and don't want to burden all the reviewers with them.
Once the Pull request is opened the bot kicks in and you see it in the timeline requesting reviews:
You can also try and use the default settings Github provides for Code Review Assignments. Just go to your team page, in the top right hit Settings and you'll find the Code review assignments tab. We tried it but it didn't work out for us.
3. Merge Freeze
The code freeze tool to block merging and deployments
The reason for adding merge freeze originated from a simple question:
Can you tell all the developers to stop merging since we are starting regression?
We could announce it in our team's channel in hopes that everyone reads the message in time. Or we could integrate a tool that allows the QA team to issue a command on Slack that freezes/unfreezes merging to the repository. Merge Freeze to the rescue.
Again, setting up, nothing too complex. What we did find Merge Freeze is missing is the ability to bulk freeze. It worked well when we needed to freeze a couple of repos. But once the number of our repositories increased to over 10, manually entering the command more than 10 times... you get it.
For this we used Slack Apps and AWS Lambda.
We created a custom Slack App for our workspace called Deployment, that has two Slash commands: /freeze_all
and /unfreeze_all
. Both commands have the Request URL set to our Lambda url, and pass the freeze value as a query parameter: ?freeze=true | false
.
Using it on Slack looks like this:
The Merge Freeze tool exposes an API endpoint for each repository you add to it, which you can use to freeze or unfreeze it. That makes the Lambda rather simple, it just makes a POST request to each of the endpoints provided by MergeFreeze.
const https = require('https');
exports.handler = async (event) => {
const freezeValue = getFreezeValue(event);
if (!freezeValue) {
return {
statusCode: 400,
body: JSON.stringify('BOOM! You need to provide a freeze value as a query param, either true or false'),
};
}
const userName = getUserName(event)
const baseOptions = {
hostname: 'mergefreeze.com',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': 0,
},
};
const appOneOptions = {
path: `/api/branches/your-organization/your-repo/main/?access_token=${process.env.ACCESS_TOKEN}&frozen=${freezeValue}&user_name=${userName}`,
...baseOptions,
};
...
/** Removed the rest of declaration to keep the preview short */
await Promise.all([
doRequest(appOneOptions),
...
doRequest(appElevenOptions),
]);
console.log("I'm done with all your promises!");
// Text that gets return to Slack that is only visible to the person entering the command
return {
statusCode: 200,
body: JSON.stringify('You have such power!!!'),
};
function doRequest(options) {
return new Promise((resolve, reject) => {
const req = https.request(options, (res) => {
res.setEncoding('utf8');
let responseBody = '';
res.on('data', (chunk) => responseBody += chunk);
res.on('end', () => resolve(responseBody));
});
req.on('error', (err) => reject(err));
req.end();
});
}
function getFreezeValue(event) {
let freezeQueryString;
let freeze;
if (event && event.queryStringParameters && event.queryStringParameters.freeze) {
freezeQueryString = event.queryStringParameters.freeze;
}
if (freezeQueryString === 'true' || freezeQueryString === 'false') {
freeze = freezeQueryString;
}
return freeze;
}
function getUserName(event) {
const bodyQueryParams = new URLSearchParams(event.body);
return bodyQueryParams.get('user_name') || 'Web API';
}
};
After entering the command, MergeFreeze lists all the repos that got frozen or unfrozen and you get a confirmation message from Slack, making your work day a bit better!
After the regression is done, everything is pushed to Production and is smoke tested, the lead QA issues the unfreeze_all
command and life goes on.
4. Husky
Modern native Git hooks made easy
We use Jira as our work management tool so we have to prepend the ticket ID to our branch names and commit messages in order to utilize both the Development panel when viewing an issue and VSCodes extension GitLens:
Jira ticket Development panel:
This means that each time you create a branch you have to remember to include the Jira issue ID, eg: task-ND-123-add-authentication. That alone was not a big deal as it quickly became a habit. But what was a PIA was prepending it to every commit message. The 1st automation round was just setting up the git prepare-commit-message
hook on your local machine, but as the team grew larger we needed a better solution which Husky provided!
Husky in combination with jira-prepare-commit-msg is what worked for us:
...
"private": true,
"husky": {
"hooks": {
"prepare-commit-msg": "jira-prepare-commit-msg"
}
},
"jira-prepare-commit-msg": {
"messagePattern": "$J $M",
"jiraTicketPattern": "(\\w+-\\w+-\\d+)"
},
"dependencies": {
...
"devDependencies": {
"husky": "^4.3.8",
"jira-prepare-commit-msg": "^1.5.2",
...
The JIRA ticket ID is taken from a git branch name. Now you could just write commit -m "Fixing a typo"
and you would get a commit message looking like task-ND-123-Fixing a typo.
In case you did not name your branch correctly eg: missing Jira ticket ID you would get an error:
my-application git:(main) ✗ git commit -m "Add authentication methods"
husky > prepare-commit-msg (node v14.15.0)
JIRA prepare commit msg > start
JIRA prepare commit msg > Error: The JIRA ticket ID not found
JIRA prepare commit msg > done
This came in nicely as everything was set up in package.json
and a new developer would do npm i
and she/he is pretty much set, no need to manually configure hooks.
But the Jira Ticket ID in the commit message in combination with GitLens is what really made this super useful.
GitLens with Git blame annotations:
There were a lot of times where we had to, for various reasons, open up and read the Jira issue associated with the code change. Having the ticket ID at each mouse click throughout the codebase saved us a lot of time. (opening it in the browser is easy as well, just take the Jira ID and add it after .../browse/ + ND-123 e.g., https://your-organization.atlassian.net/browse/ND-123)
GitLens is a cool tool which I personally use on a daily basis. It helps you to visualize code authorship at a glance via Git blame annotations and code lens. You can also very easily navigate back in history to see past commits which is useful as well.
5. Scheduled reminders for Pull Requests
Scheduled reminders help teams focus on the most important review requests
This is something we added not too long ago, just a bit after we moved to Micro Frontend Architecture. One of the reasons for adding it was that the number of repositories increased from 4 to 14 so having a dedicated channel for open pull requests made sense. Prior to this we would post a link of the PR in our team's main channel, or would hope people would see it in their email. This way we moved the noise to a dedicated channel, and the devs know the team will get automatically notified.
We get notifications on every working day each full hour from 8-16. It ignores approved pull requests (in our case when 2+ ppl approved it) and we also have ignore terms for BleedingEdge so it ignores pull requests opened by Dependabot.
Setting up scheduled reminders is straightforward and you can find the github docs here. This is how it looks like once its up, in our case it posts messages in a private frontend-pull-requests channel:
...
There are a lot of improvements that we could include on top of what we have, like creating branches directly from Jira would ease up on having to remember the naming convention. Or maybe we could have chosen a merge freeze tool that has bulk freeze built in. But usually we had limited time for investigation, or it was good enough at that time, and later on we just tried to improve the process instead of replacing the tool.
If you have any suggestions, please do post them in the discussion below!
Feel free to connect 👋
Top comments (10)
hey Petar, awesome post. i'm actually the new owner of Merge Freeze (your #3 reco) and wanted to see what you think of all our new features. :)
mergefreeze.com/news
Hey, sorry for the late reply, somehow I missed your comment.
Congrats on acquiring Mergefreeze :).
I see that there are a lot of improvements, I love the Mac users menu bar options!
Keep up the good work!
Great and helpful post
Also remember to automate your development environment with gitpod.io so you never have to check out any of your code locally or change branches or stash changes etc.
thanks for the tip, I'll give it a try.
this is very helpful, thanks!
Wonderful list, I was not aware of some of these and now intend to try them out. I do like the idea of the freeze and automated dependency updates. Thanks.
Thanks, appreciate the comment. The need for merge freeze depends on the project, team and how the deployment is done, but dependency updates I turn on on every project, even its only my small home project :)
Very nice.
Thanks
Great post, keep up the good work.