Having Coffee with Deno - Automating All the Things
Welcome to the final installment of our Deno series, where we build a script that pairs up people for coffee.
In the last post, we added the ability to post messages into a Slack channel instead of copying from a console window.
The current major problem is that we have to remember to run the script. We could always set up a cron job or scheduled task, however, what happens when we change machines? What if our computer stops working? What if someone else changes the script, how will we remember to get the latest and run it?
It'd be nice if we had a centralized location that could run our script on a schedule. When it ran, it'd grab the latest version of the script and execute it. No more need for it to be on our machine.
Wait a minute; we have a tool for this, our Continuous Integration (CI) server. Whether you're using tools like Jenkins, TeamCity, Azure DevOps, GitHub Actions, or CircleCI, at the end of the day, these tools are doing the following:
- Start when the trigger happens (e.g., changes are merged or when a certain time happens).
- Get the latest version of code from source control.
- Run one or more steps.
The fun thing about this is that no one said that CI couldn't execute side effects like kicking off scripts. In this post, let's take a look at how we can setup a GitHub Action to execute our script.
The Approach
For the script to post to Slack, we'll need to make the following changes:
- Add our secrets/variables to the repository so that our Action can access them.
- Creating the Action.
- Setup a schedule for when the script should run.
Adding Secrets to the Repository
In our .env
file, we have two secrets, our GITHUB_BEARER_TOKEN
, which is used to get members of the organization and SLACK_WEBHOOK
, the URL to post our messages to.
Since these values are secrets, we'll need to follow these docs to add them to the repository level.
There are additional places we could place these secrets (in an environment or at an organizational level). For now, we'll keep at the repository level.
While adding your secrets, you'll note that we can't have a secret start with GITHUB
(this is forbidden according to the docs). We'll rename this to GH_BEARER_TOKEN
for now (we'll see later why renaming isn't a big deal).
Once we've added our secrets, we should have a screen that looks like the following:
With this done, let's work on creating our GitHub Action.
Creating the GitHub Action
In the root of our repository, let's create the .github
folder followed by workflows
inside of it. From there, we'll create run-script.yml
with the following:
With these changes, we can go to our Actions and kick this off manually. If everything works correctly, we should see our message get posted!
Troubleshooting
- If you receive a 401, it's most likely the GITHUB_BEARER_TOKEN is not being set. Make sure that you added your bearer token as a secret for the repository and that you're using
${{ secrets.GH_BEARER_TOKEN }}
to refer to it. - If you receive a 404, it's most likely that the SLACK_WEBHOOK is not being set. Make sure that you added your webhook as a secret for the repository and that you're using
${{ secrets.SLACK_WEBHOOK }}
to refer to it.
Creating the Schedule
Now that we have the script working, our last change is to add another trigger so that our script runs on a schedule.
GitHub uses cron syntax for scheduling, so the times will be in UTC (consider this when determining your time).
I live in the Eastern Time Zone, so let's schedule our message to run at 8 am on Mondays.
(If you're not familiar with cron syntax, I highly recommend checking out crontab, an online tool to help validate your syntax, it's terrific!)
Since we want to make sure that our heroes have time to meet up during the week, let's schedule this for 8 am on Mondays.
Nice! At this point, our script will run at 8 am on Mondays (and sometimes at 7 am on Mondays, yay, Daylight Savings Time!). With this final piece, we've completed our Random Coffee script for the Justice League.
Wrapping Up
In this series, we created our first bit of automation using Deno and TypeScript, pairing up the members of the Justice League. We learned how to make web requests, how Deno's permission scheme works, creating a Slack Webhook, and how to execute our scripts on a schedule using GitHub Actions.
You can find the full working version of this repo on my GitHub.