Using GitHub Issues to Hack Together A Feedback System
Boot.dev has been my side-project for the last couple of years now. Being a learning path for backend developers focused on quality over quantity, I knew early on that it needed to have a really tight feedback loop from students. We had (and still have) a Discord server where myself and the students hang out, and that worked okay at first. Unfortunately, Discord channels have a couple problems when it comes to issue tracking:
- Long conversations make it hard to keep track of individual reports
- There’s not way to “resolve” a “ticket”
- Not all students are in the Discord
- There is more friction to report issues in a different application
The solution that has been working splendidly for me so far was to add a feedback box directly within each coding assignment! Now students can easily report issues with near-zero hassle. Unfortunately, running SQL queries to get at those submitted issues is a giant pain… The GitHub API has entered the chat.
Using GitHub issues to track user feedback
I have a private GitHub repo where I store all the content for the Back-end Developer Path courses on Boot.dev in markdown files. It would be really convenient if user reported issues automatically manifested as GitHub issues on that repository! After just a few minutes of digging, I realized it was quite easy to do with the GitHub API. Given that my backend is a REST-ish API written in Go, I decided to use Google’s GitHub API client package and the official Golang oauth2 package.
I you’re interested in following along, first you need is a personal access token with “repo” permissions.
Next, I created a githubclient package in my project to manage interactions with the GitHub API. It exposes a Client struct:
// Client -
type Client struct {
githubClient *github.Client
}
// NewClient -
func NewClient(personalAccessToken string) (Client, error) {
ctx := context.Background()
ts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: personalAccessToken},
)
tc := oauth2.NewClient(ctx, ts)
client := github.NewClient(tc)
_, ghResp, err := client.Issues.List(ctx, false, nil)
if err != nil {
return Client{}, err
}
if ghResp.StatusCode > 299 {
dat, err := io.ReadAll(ghResp.Body)
if err != nil {
return Client{}, err
}
return Client{}, fmt.Errorf("status code: %v, message: %v", ghResp.StatusCode, string(dat))
}
return Client{
githubClient: client,
}, nil
}
You’ll notice that I added some logic to list the issues. We don’t actually do anything with those issues, and you can remove that code if you want. For me, it was useful to test that the token is working on application startup.
Next, I wrote a simple CreateIssue() method on the client:
// CreateIssue creates an issue in the example-org/example-repo repository
func (c Client) CreateIssue(exercisePath, fromUsername, userComment string) error {
ctx := context.Background()
const repoName = "example-repo"
const orgName = "example-org"
summary := userComment
const summaryLength = 20
if len(summary) > summaryLength {
summary = summary[:summaryLength]
}
title := fmt.Sprintf("exercise: %v, Summary: %v", exercisePath, summary)
body := fmt.Sprintf(`
Comment: %v
From: %v
`, userComment, fromUsername)
_, ghResp, err := c.githubClient.Issues.Create(ctx, orgName, repoName, &github.IssueRequest{
Title: &title,
Body: &body,
Labels: &[]string{"course-feedback"},
})
if err != nil {
return err
}
if ghResp.StatusCode > 299 {
dat, err := io.ReadAll(ghResp.Body)
if err != nil {
return err
}
return fmt.Errorf("status code: %v, message: %v", ghResp.StatusCode, string(dat))
}
return nil
}
As you can see, given an…
- exercise path (which is just the filepath to the exercise receiving feedback)
- username of the reporter
- comment from the reporter
…the CreateIssue method simply creates a new issue in the repo with a static label. I’ve split the inputs into a GitHub issue “title” and “body” that’s formatted to my needs so that I can resolve the issues as quickly as possible.
Why not use an out of the box solution?
I know there are a billion and a half issue tracking tools you can buy on the market, but I really liked this solution for a few reasons:
- It took about an hour to code from start to finish
- It’s free
- It’s integrated with the tooling I already use daily (GitHub)
If you need a simple issue tracker for your app I’d recommend looking into using GitHub issues via the API, at least until it stops working for you!
Related Articles
How Not to Ask for Help Online
May 20, 2022 by Lane Wagner - Boot.dev co-founder and backend engineer
I’ve spent an unhealthy amount of time online over the course of my life, and in the last couple years I’ve been managing a Discord server for people who are learning computer science. Like all online communities, we have ban, kick, and moderation policies so that we’re not overrun with spammers and other non-contributors. However, I’m not perfect, and I have realized recently that we get a decent number of members who at first glance seemed like a spammer, but it turns out they just have no idea how to communicate online in a way that’s useful to themselves and others.
Top 10 Communities For Learning to Code
Apr 20, 2022 by Zulie Rane - Data analysis and computer science techincal author
Why you need a coding community The one thing that every programmer has in common, whether they’ve only ever implemented a “Hello World” program or they’re considered a “senior” software engineer, is the need to continuously learn. New technologies, programming languages, frameworks, libraries, and conventions are constantly being introduced to the industry. As a beginner, it can be hard to suss out what you need to know to enter the profession, and once you’re a proficient coder, it’s tiring to constantly investigate trending topics in tech.
An Overview of Boot.dev's Full-Stack Architecture
Jan 10, 2022 by Lane Wagner - Boot.dev co-founder and backend engineer
Because I’ve had several inquiries on this topic, I thought it would be interesting to publish some information on how the boot.dev website and platform work, and how I’ve organized all the technologies I’m using. I’ll do my best to keep this list updated in the future as I migrate from older tools and technologies to newer ones, but assume that this might be a bit out of date by the time you read it.
The Best Product Managers Have The Worst Ideas
Nov 02, 2021 by Lane Wagner - Boot.dev co-founder and backend engineer
It’s hard finding good product people. That fact is really a tragedy because they are probably the most important part of any product-focused organization. I think there is a misconception in the software industry that product managers have a good sense of “what users want”, “what the next feature should be” or “ux design”. In reality, I’ve come to believe that the best product managers aren’t good at any of that, and they know it.