Using Github actions to send Tweets
Tags: automation, node, github
Published: 2020-10-15 13:04:30

---
title: 'Using Github actions to send Tweets'
published: true
description: Before deactivating my old Twitter account I wanted to notify all my followers about the new account. In this post, I document how I used Github Actions to send that message automatically.
tags:
  - automation
  - nodejs
  - github
layout: layouts/post.njk
cover_image: https://skippednote.dev/img/gh-build.png
---

Recently I deprecated my Twitter account which I have been using for more than 12 years. As of today, the deprecated account is still running I just have updated the handle to [\_skippednote](https://twitter.com/_skippednote) and created a [new account](https://twitter.com/skippednote). In the early days, I tweeted a lot about a lot of things that I don't believe in now and I don't want to carry that baggage. The implication of moving to a different account is that I have to start afresh which means 0 followers and 0 credibilities. So before I deactivate my account I wanted to send reminders to the followers on the older account notifying them that I have changed my account.

To run time-based jobs the most common solution available is cron (or cron job), however, we need a server to schedule and run these jobs. Setting up a server was too much work for my use case which is just _sending a tweet once a day_ and so I opted for the next best thing: [Github Actions](https://github.com/features/actions). Github Actions is primarily used for CI/CD where we set up jobs to run when based on various Github events or a cron schedule. For our limited use, we can schedule jobs to send exactly one tweet every day and this costs nothing as it's within the free use limit.

I wrote a Node.js script that when run sends a tweet with a message that calculates numbers of days till 25th October which is when I plan to deactivate the account.

```javascript
const Twit = require('twit');
const {
  CONSUMER_KEY,
  CONSUMER_SECRET,
  ACCESS_TOKEN,
  ACCESS_TOKEN_SECRET,
} = process.env;

const T = new Twit({
  consumer_key: CONSUMER_KEY,
  consumer_secret: CONSUMER_SECRET,
  access_token: ACCESS_TOKEN,
  access_token_secret: ACCESS_TOKEN_SECRET,
});

const daysToDeletion = 25 - new Date().getDate();

const message = `👋 Hey there folks!.
This is an automated message 🤖 to remind you that this account has been renamed to @_skippednote and will be deactivated in the next ${daysToDeletion} days.
I've moved to @skippednote, you can come follow me there ♥️`;

(async function main() {
  try {
    await T.post('statuses/update', { status: message });
    console.log('Successfully posted the tweet!');
  } catch (e) {
    console.log('Failed to post the tweet!');
    console.log(e.message);
  }
})();
```

I'm using the [Twit](https://www.npmjs.com/package/twit) node module which use with Twitter v1.1 API and supports both promise and callback-based methods. The interesting bit here is how and where are the environment variables defined, we don't put them in the file as it then becomes a security risk. Similar to other CI/CD systems, Github Actions allows us to add Secrets (environment variables) via repository settings.

![GitHub Secrets](https://skippednote.dev/img/gh-secrets.png)

To set up a Github Action, we need to create a `.github` directory at the root of our repository and within that, we create a `workflows` directory which contains jobs that would be run based on various Github Actions. The name of the file under the `.github/workflows` directory doesn't matter as long it's a yaml file. In our case we want a job to run on a schedule so I named it `.github/workflows/cronjob.yml`.

```yaml
name: Twitter message

on:
  schedule:
    - cron: '15 6 * * *'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v2
      - name: Setup Node.js
        uses: actions/setup-node@v1
        with:
          node_version: '12'
      - name: Install Node modules
        run: npm i
      - name: Tweet message
        run: node tweet.js
        env:
          CONSUMER_KEY: ${{ secrets.CONSUMER_KEY }}
          CONSUMER_SECRET: ${{ secrets.CONSUMER_SECRET }}
          ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
          ACCESS_TOKEN_SECRET: ${{ secrets.ACCESS_TOKEN_SECRET }}
```

The `name` attribute appears on the Github Action page to help you easily find the job. Since we called it Twitter message, you can see in the screenshot below in the left sidebar we have a workflow under the same name.

![GitHub Workflows](https://skippednote.dev/img/gh-workflows.png)

`on` key here allows us to run the job on a cron schedule. We till Github actions to run it every day once at 6:15 am. It's important to note that Github Actions is configured to use UTC timezone.

In the `job` section of the file, we set up the environment to use the latest release of Ubuntu and then use preconfigure actions to:

1. Checkout the repository
2. Setup Node.js version 12
3. Run the script we created earlier to send out the tweet.
   1. Here we are exposing the secret we defined on the settings page to the task using `env`

![GitHub Build](https://skippednote.dev/img/gh-build.png)

Once the build run, the tweet is sent with the generated message.

![GitHub Tweet](https://skippednote.dev/img/gh-tweet.png)
[https://twitter.com/\_skippednote/status/1316629984685981696](https://twitter.com/_skippednote/status/1316629984685981696)