Hello, GitHub Discussions! Goodbye, Disqus...
Posted by Jason Bolden on Nov 02, 2021
In short, I don't like the free version of Disqus. Ads serve a purpose in this world, and they often allow us to enjoy a lot of valuable content at the cost of a portion of our attention. However, I don't want them on my blog. Instead, let's leverage some of the native functionality of GitHub and create a Discussion thread when a new post is published to the blog; all automated, of course.
Objective
Referencing the previous post on Documentation Automation, we intend to make a minor change to the existing flow. The reason why one would want to do this is to further consolidate the developer experience by adding a forum for collaborative communication linked to published content within the project.
The Breakdown
We'll start by explaining all the pieces necessary to add the new automation steps and tie them all together in the end.
GitHub Discussions GraphQL API
GitHub recently released their GraphQL API for Discussions. For our workflow, we want to create a new Discussion when a new Blog Post issue is assigned. To figure out how to programmatically do this, let's reference the docs and leverage the GitHub GraphQL Explorer.
The details behind GraphQL fall outside the scope of this post; however GitHub provides a nice overview on their docs site. The calls we need to perform are as follows:
query
for the repositoryId and categoryId we want to assign the new discussionmutation
to create the new discussion
1 2 3 4 5 6 7 8 9 10 11 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
|
The GraphQL explorer returns a JSON payload with information required for the next step. Without this step, The Mutation call wouldn't know which repository to create the new Discussion in nor what category to assign it.
1 2 3 4 5 6 7 8 |
|
1 2 3 4 5 6 7 8 9 10 |
|
Attention
On line 5 of the mutation snippet, we specified to return the value of the number
field for the new discussion. Having the discussion number will be useful in a later enhancement to this flow. I'll expand more on this at the conclusion of this post.
GitHub GraphQL Action
Now that we've establish what API calls we need to make the discussion and tested them manually, let's build out the automation to add this to our pipeline. The steps we want to inject into our workflow are as follows:
Octokit maintains a repo, graphql-action, that allows you to make calls to the GitHub GraphQL API via a GitHub Action. At this time, it's limited to only GraphQL queries, so we'll also explore how to make calls using cURL for the mutation portion.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
The octokit/graphql-action
allows us to basically copy/paste the query we developed in the explorer with the exception of defining the variables and their types being passed to the query; similar to a function definition. Lines 17 and 18 pull the repository name and owner login from the action event object rather than hardcoded values seen previously.
Attention
The octokit/graphql-action
documentation references the use of github.event.repository.owner.name
. That value is not present in the webhook event payload object. It should be github.event.repository.owner.login
The question now is, how do we pull the Id's from the json returned by the initial query? Introducing, jq. jq
is a handy command-line utility that makes processing JSON a easier. We're going to use it to extract the Id's and assign them to environment variables for our next workflow step.
1 2 3 4 5 6 7 |
|
At the time of writing, the octokit/graphql-action
action did not support mutations 😢. Luckily there's a fallback. The GitHub GraphQL API can be queried using http requests. Knowing this, we can instead form a JSON payload containing our mutation statement and send it via cURL. It's messy (lots of debugging escape-characters), but it gets the job done.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Conclusion
We'll stop here for the scope of this post. There are some other things that could be added to further enhance the automation:
- Inject the url to the new discussion in the
profile_builder
module so it can be added to the new blog post template automatically. Discussions urls match the pattern:/<owner>/<repository>/discussions/<discussion_number>
(recall that we purposefully captured that number after the mutation call) - Programmatically add the link to the new Blog Post to the Discussion Body.
- Assign different discussion categories or use a different body template based on issue labels
Let's take a look at the bigger picture for a second. Discussions were created to facilitate collaborative communication about a project. Assuming you're a maintainer for a project on GitHub and you have a project site for publishing posts, tying these posts to a discussion just makes sense if you value community around your product. The bonus here being, Discussions are built into the GitHub ecosystem and are tied directly to your project. Fewer dependencies, less context switching, it's awesome!
References
- GitHub GraphQL API for Discussions
- GitHub GraphQL Intro
- jq
- GitHub Webhook Events and Payloads
- GitHub GraphQL cURL
Comment
Continue the discussion here!