GitHub Actions are a way to automate tasks in your GitHub repository and are most commonly used to automate CI/CD workflows.
Having the ability to create custom software development life cycles (SDLC) right alongside your GitHub can be extremely powerful and convenient. While repository owners can create their own custom actions step by step, GitHub Actions has a built-in marketplace where users can find actions created by other developers and organizations, providing a very low barrier of entry to get started.
In addition to using GitHub Actions for automating CI/CD workflows, there are many other use cases such as:
- Providing build-status notifications to Slack
- Optimizing images and assets
- Performing static analysis on code
- Updating the status of an issue
- Creating and updating the application changelog
At its core, a GitHub workflow is a series of steps that are executed in sequence. Each of these steps is a GitHub Action. Here's some basic syntax and terminology:
- Workflow: a series of steps that are executed in sequence
- Event: an activity in GitHub that will trigger the workflow to execute
- Job: a single step in a workflow
- Step: either a shell script that will be executed or one or more actions that will be run
- Action: the primary subset of a step that is executed in a job (every step consists of one or more actions)
More information about GitHub Actions and workflows can be found in the official documentation.
In this article, we'll walk through how to leverage scheduled tasks in GitHub Actions and explore some of the limitations with the native functionality. Then we’ll take a look at using Airplane schedules instead and discuss the advantages of Airplane over using the GitHub default scheduler approach.
Note: All the example code for this article can be found in this GitHub repository.
The basics of GitHub Actions scheduled events
For example, if you wanted to schedule a GitHub workflow to be executed at 5:30 UTC every Monday to Thursday but skip the “Not on Monday or Wednesday” step, you could use the following syntax:
For a more practical example, consider that you’re running some static analysis on a project’s code, which could potentially be a heavy operation to perform. You could schedule a GitHub Action to run this analysis on a nightly or weekly basis:
The code above runs GitHub’s code-quality analysis tool, CodeQL, on a repository every day at midnight, performing static analysis for typescripts against the latest version of the master branch.
Note that you can set up a GitHub workflow to respond to multiple triggers—e.g., push, pull request, or schedule.
Implementing scheduled tasks in GitHub Actions
Now that we've covered the basics of scheduling GitHub Actions, let’s go ahead and walk through an example use case. Let's say we want to create a simple scheduled workflow that will check for stale issues and pull requests (PRs).
Start by creating a GitHub workflow called .github/workflows/stale-issues.yml and add the following code to it:
Now, let’s break down the contents of the workflow and what each of the steps do.
The first part of the code defines the name of the workflow that will be visible in the GitHub UI:
name: "Close stale issues and PRs"
Then, this section of code specifies the schedule that the workflow should run on—every day at midnight:
schedule action uses a cron expression that specifies the time of day that the workflow should run.
Don’t worry about memorizing the syntax; you can always rely on tools like crontab guru for reference. One important thing to note is that GitHub doesn’t support cron expressions that are not UTC, meaning that expressions like
@annually will not work.
Consider the following examples of cron expressions:
The cron expression above is a combination of the following elements:
Let’s get back to examining the steps of the workflow. Next, you have the job definition:
Here, a job called
stale is defined, which runs the
actions/stale action and passes the following parameters:
repo-token: the GitHub token that will be used to authenticate against the repository
stale-issue-message: the message that will be used to comment on stale issues
stake-pr-message: the message that will be used to comment on stale PRs
This combination of
actions work together to form the full GitHub workflow.
This example could also be extended to include an additional step that would notify your team on Slack that the workflow has completed, as well as which PRs and issues are stale. You can use the official Slack GitHub Action to easily set this up.
The limitations of scheduled GitHub Actions
While GitHub Actions are powerful there are a few notable limitations:
- Lack of metrics and observability: Basic metrics and observability are not available for scheduled events as a part of the platform.
- Actions can’t call other actions: There isn’t a way to call other actions from a scheduled event. The closest thing is having composite actions as part of a workflow.
- Fixed minimum interval: The minimum interval for scheduled events is 5 minutes.
- Delays based on load: Scheduled events can be delayed during periods of high load. Typically, those periods include the start of every hour.
- Max execution time: There is a maximum execution time of 360 minutes (6 hours) for jobs, which cannot be changed.
Security is another issue when dealing with GitHub Actions, especially when leveraging third-party integrations. Some of these security concerns include:
- Third-party code: While third-party integrations and marketplace actions are powerful, they are not as secure as native GitHub Actions, as outside parties could potentially run malicious code.
- Third-party vulnerabilities: Packages used by third-party actions could be subject to dependency vulnerabilities.
- Malicious Docker images: Actions could be built on malicious Docker images.
It’s highly recommended to follow GitHub’s security best practices for hardening your GitHub Actions workflows.
Finally, one of the biggest limitations is that GitHub Actions can struggle to operate outside of GitHub. For instance, if you wanted to access a database to retrieve information or make an API call to an external service, it might be difficult (if even possible) to perform those actions with GitHub Actions alone. This is where Airplane can help.
Airplane scheduled tasks as a better alternative
While GitHub Actions are a great way to automate workflows, Airplane provides the capabilities provided by GitHub Actions and more, from building simple tasks to database calls to complex, multi-step workflows.
One important difference between Airplane and GitHub Actions is that Airplane separates the concept of a task from a recurring schedule. This distinction allows you to run any single task or runbook as a one-off or set the task to run regularly using Airplane schedules. This is a powerful feature that can be used for several purposes:
- CI/CD: Scheduled tasks can be used as a replacement or addition to your CI/CD workflow—to generate periodic releases on a schedule, run reports, collect data, or perform any other types of activities that need to occur in a recurring manner.
- Simplify larger workflows: Another great use for scheduled tasks is to automate running expensive operations or complex workflows, such as performing static analysis on larger codebases on a weekly basis or performing regular product backups.
Let's walk through how to create a scheduled task in Airplane.
Create a new task
Start by signing up for a free Airplane account. Then create a new SQL task:
For the purpose of this tutorial, we’ll create a task that runs a SQL query and calculates the revenue per company since inception. Define the task by including the task name and description:
We'll then build the task by connecting to our database and adding a SQL query.
A few things to note:
- For this example, you can use the Demo DB provided by Airplane.
- Although this is a simple example using SQL, Airplane allows for complex queries and code-based tasks (Python, Node, etc.) giving you more flexibility when working with data.
- Airplane provides a schema navigator (right-side of the screen) that helps you build your queries with ease.
Next, we can execute our task and see the results in an output table:
Create a new schedule
Now that we've created our first Airplane task, we can set this task to run on a schedule. For example, we can calculate revenue by company every day at midnight.
Click on the New schedule button:
Once you've selected the task and chosen Next, you'll see a screen that allows you to define the schedule:
You can configure the schedule using the same cron expression syntax as GitHub Actions or using Airplane's simple UI for creating schedules.
For this example, say we want to run the company revenue calculation on a monthly basis. With the values defined as pictured above, we can see that Airplane’s next three runs will occur at 3/31/2022 9:00 PM ADT, 4/30/2022 9:00 PM ADT, and 5/31/2022 9:00 PM ADT.
You can then simply click the Create schedule button to create the schedule. You’ll be able to monitor the schedule in the Airplane UI from the next screen:
That's it! We've created a scheduled task. With Airplane, you gain a lot of flexibility and control over your scheduled tasks with no overhead. You can quickly spin up tasks and easily layer on access controls and audit logs. It’s a great alternative for teams looking to take their existing GitHub Actions automation to the next level.
While we discussed Airplane schedules, it's worth mentioning that this only scratches the surface of what you can do with Airplane. You can also do things like create a runbook to automatically drop the report into a specific Slack channel every month.
You can visit our blog to read more on topics like cron troubleshooting and runbook automation, and visit our documentation to learn more about automating operational workflows and other capabilities.
Author: Allan MacGregor
Allan MacGregor is a software engineer and entrepreneur enthusiastic about developing innovative software solutions. Check out his blog here: https://allanmacgregor.com/posts