Introduction
Hey there everyone 👋! I’m excited to continue our journey, this time diving into the world of modern software development. In the previous articles, we explored the fundamentals of Git (Part 1: Understanding Git) and learned how to set up our first GitHub repository (Part 2: Setting Up Your First GitHub Repository). Now, we’re ready to take our development workflow to the next level with GitHub Actions!
So, what exactly is GitHub Actions? Simply put, it’s a powerful tool built right into GitHub that helps you automate all sorts of tasks within your software development lifecycle. Think of it as your personal robotic assistant that can automatically test your code, build your application, and even deploy it to your servers.
But why should we care about GitHub Actions in the first place? What’s wrong with building, testing, and deploying our applications the good old-fashioned way? Well, while there’s nothing inherently wrong with manual processes, they do come with some significant drawbacks. They’re often time-consuming, require a lot of mental context switching, and are prone to human error. This is where GitHub Actions shines! It provides a way to automate these repetitive tasks, freeing you up to focus on what you really love – writing code and building awesome features.
In this article, we are going to explore just that! We will cover the fundamentals of GitHub Actions, how it integrates with your existing development workflow, and the basic building blocks that make up a GitHub action, such as workflows, jobs, and steps.
Don’t worry if some of these concepts seem complex at first. We’ll break them down step by step, using clear examples and explanations. By the end of this article, you’ll have a solid understanding of what GitHub Actions is and how it can help transform your development process.
Alright, let’s jump right into the exciting world of GitHub Actions!
How GitHub Actions Works
Figure 1: A visual representation of a typical GitHub Actions workflow, from code commit to deployment.
In the introduction, we talked about the downsides of manual, repetitive tasks in software development. Now, let’s see how GitHub Actions provides a powerful solution by automating these processes. It’s all about letting the tools do the heavy lifting so you can stay focused on creating.
One of the great advantages of GitHub Actions is that it’s built right into GitHub. This means it’s readily available where your code is hosted, making it incredibly convenient to set up and manage your automated workflows. But what exactly is a workflow? Simply put, it’s an automated process that you define, made up of a series of steps that are executed in a specific order. You can think of it as a recipe for your automation tasks.
Since it’s so tightly integrated, GitHub Actions can automatically detect events that happen in your repository. For instance, it knows when you push your code. Think of pushing as simply uploading your latest code changes to your GitHub repository. Another event it can detect is when you create a pull request. You can think of a pull request as a way of saying, “Hey, I’ve made some changes, and I’d like them to be reviewed and merged into the main project.” These events, among many others, can be used to set the automation gears in motion.
But what exactly are these “gears,” and how do they work? Let’s walk through a typical workflow, as illustrated in Figure 1. We’ll keep it high-level for now, focusing on the main stages:
- Code Commit: It all starts when you write code and commit it (save your changes) to your local repository.
- Push to GitHub: You then push your committed code to your GitHub repository, essentially syncing your local changes with the version stored on GitHub.
- Workflow Trigger: This
push
event can automatically trigger the corresponding workflow you’ve defined. This is where the magic of GitHub Actions begins! - Action Time: GitHub Actions springs into action. It uses a runner (we’ll explore this in more detail in a later section) to carry out the series of steps defined in your workflow. These steps often include:
- Checking out your code: Getting a fresh copy of your code from the repository.
- Setting up the environment: Installing any necessary software or tools, like Node.js for a JavaScript project or cloud platform CLI tools like the Azure CLI or AWS CLI.
- Installing dependencies: Downloading and installing any required packages or libraries.
- Running tests: Automatically executing your test suite to ensure your code works as expected.
- Deployment (Optional): If all tests pass, and you’ve configured it to do so, GitHub Actions can automatically deploy your code to a server or hosting platform, like Microsoft Azure or AWS. This makes your changes live.
- Monitoring (Optional): You can even set up steps to monitor your application after deployment, ensuring everything is running smoothly.
The beauty of this is the automation. Once you’ve set up a workflow, this entire process can happen automatically every time you push code to GitHub. No more manual testing, building, or deploying – GitHub Actions handles it all for you.
In the next section, we’ll break down the key components of GitHub Actions – workflows, events, jobs, steps, and actions – to give you a deeper understanding of how it all works under the hood. Then, we’ll move on to creating your very first workflow!
Inside GitHub Actions: Understanding the Key Components
Now that we’ve seen GitHub Actions in action, let’s go inside and break down the key components that power these automated workflows.
-
Workflows: Think of a workflow as the overall recipe for your automation. It’s a set of instructions, defined in a YAML file, that tells GitHub Actions what to do. This recipe can be as simple as just running tests or as complex as building, testing, and deploying your entire application.
-
Events: Events are the triggers that kick off your workflows. They’re like the “start” button for your automation. You have a lot of flexibility here - common events include pushing code, creating a pull request, or even running your workflow on a schedule. You get to decide which events should set your automation in motion.
-
Jobs: Jobs are independent units of work within a workflow. Each job runs on a fresh instance of a runner (we’ll talk more about runners in a later section, so don’t worry if this sounds unfamiliar now!). Meaning each job starts with a clean slate. You can have multiple jobs in a workflow, and they can run in parallel or sequentially, depending on how you define them. For example, you might have one job for building your code and another for running tests.
-
Steps: Steps are the individual instructions within a job. They run one after the other, in the order you define. Each step can either be a simple shell command (like
npm install
to install dependencies) or a more involved action. -
Actions: Actions are where GitHub Actions becomes really powerful. They are reusable, self-contained units of code that perform specific tasks. Think of them as pre-built building blocks that you can snap together to create complex workflows without writing a lot of code yourself! You can find a wide variety of actions in the GitHub Marketplace, covering common tasks like checking out code, setting up different programming environments, or deploying to various cloud platforms. You can even create your own custom actions to automate tasks specific to your project!
Don’t worry if these components still feel a bit abstract. It’ll all become much clearer as you start building your own workflows. In the next section, we’ll create a simple “Hello World” workflow together, and you’ll see firsthand how all these pieces fit together to create automation magic!
Your First GitHub Actions Workflow
Now that we have a good grasp of the key components inside GitHub Actions, let’s create our first workflow together! We’ll keep it simple for now - a basic “Hello World” workflow that runs whenever you push code to your repository. This is where the magic truly begins!
To follow along, you’ll need a GitHub repository. This article builds on the concepts and setup from the previous articles in the series, particularly Part 2: Setting Up Your First GitHub Repository. If you’ve been following along, you should already have the my-first-project
repository (from Part 2) cloned to your local machine and open in VS Code. If you’re joining us now, no problem! You can still follow along by cloning this repository: https://github.com/ahmedmuhi/my-first-project.git
.
Here are the steps to clone and open the repository in VS Code:
- Open your computer’s terminal or command prompt.
- Navigate to where you would like to clone the repository using the
cd
command. - Clone the repository using the command:
git clone https://github.com/ahmedmuhi/my-first-project.git
- Open VS Code and then click on
File
in the top menu bar. - Click on
Open Folder...
and select themy-first-project
folder.
Alright, with that in place, you are now ready to create your first workflow!
Creating Your Workflow File
-
In VS Code, you should have the
my-first-project
folder open. -
Right-click on the Explorer panel (the left sidebar showing your project files).
-
Select “New Folder”.
-
Name the folder
.github
and press Enter. (Make sure you include the leading dot!) -
Right-click on the
.github
folder and select “New Folder” again. -
Name this folder
workflows
and press Enter. -
Right-click on the
.github/workflows
folder and select “New File”. -
Name the file
main.yml
and press Enter.You’ve just created the file that will hold your workflow definition! Notice that we’re using the
.yml
extension. This indicates that we’re writing in YAML (YAML Ain’t Markup Language), which is a human-readable data format often used for configuration files like GitHub Actions workflows. Don’t worry if you are not familiar with YAML, as we will explain everything in detail as we go.
Adding the Workflow Code
Now, paste the following code into your main.yml
file:
|
|
Figure 2: Creating the workflow file in VS Code
Let’s break down what’s happening in this workflow, step by step.
First, we give our workflow a name: “Hello World”. You’ll see this name in the Actions tab of your repository on GitHub, making it easy to identify your different workflows. Try to give your workflows descriptive names that clearly indicate their purpose - in this case, “Hello World” is simple enough.
Next, we have on: [push]
. This is where we specify how this workflow starts - in this case, it will run each time code is pushed to this repository. As we mentioned earlier, this is our event trigger - the action that sets our automation in motion.
Next, we define a single job called “say-hello”. Remember, a job is a set of steps that run together. This job will run on an Ubuntu server, which is managed by GitHub. That’s what runs-on: ubuntu-latest
means. We’ll dive deeper into runners in the next section, but for now, just know that it’s the environment where your job will be executed.
Our job has two steps:
- A step that prints “Hello, GitHub Actions!” to the log. We’ve named this step “Say hello”. Notice how this step uses a simple
echo
command. This is a basic shell command. - A step that shows us the current date and time. We’ve named this step “Tell us the time”, and it uses the
date
shell command.
Each step here is a simple command, showing you that steps don’t always need to use complex actions - they can be straightforward shell commands too.
When this workflow runs, you’ll see these messages appear in your workflow’s logs on GitHub. Pretty simple, right? But it demonstrates the core concepts in action. You’ve defined a workflow, set a trigger, specified a job, and outlined the steps to be executed.
Now, you might be wondering, where does this ‘ubuntu-latest’ environment actually exist? How does GitHub run this code? This is where the concept of runners comes into play! Let’s explore that in the next section.
Understanding GitHub Runners
In the previous section, we created our first workflow and saw that it runs on an environment called ubuntu-latest
. But what exactly is that environment, and where does it come from? This brings us to the concept of runners.
Think of a runner as a dedicated server that executes the instructions defined in your workflow. It’s the environment where your jobs and steps actually run. When you define a job and specify runs-on
, you’re essentially telling GitHub what kind of server you need for that job.
Now, when it comes to runners, GitHub offers a convenient, managed option called GitHub-hosted runners. These are pre-configured servers maintained by GitHub, ready for you to use in your workflows. It’s like having a temporary computer in the cloud that automatically starts up, runs your workflow, and then shuts down. And the best part? You don’t have to configure or manage these servers yourself! GitHub takes care of all the underlying infrastructure.
When you use runs-on: ubuntu-latest
in your workflow, you’re telling GitHub: “Hey, I want you to use one of your servers running the latest version of Ubuntu Linux for this job.”
GitHub-hosted runners come with a wide range of software and tools already installed, making them suitable for many common development tasks. They’re an excellent choice when you’re starting out with GitHub Actions, as you can just specify the operating system you need, and GitHub takes care of the rest.
It’s worth mentioning that there are other types of runners, like self-hosted runners. These are servers that you set up and maintain, giving you more control over the environment. While they offer more customization, they also require more setup and maintenance. We won’t delve into self-hosted runners in this article, but it’s good for you to know that they exist for more advanced use cases.
So, going back to our “Hello World” workflow, when you see runs-on: ubuntu-latest
, remember that it’s simply instructing GitHub to use one of its managed Ubuntu servers to execute your job. You specify the environment, and GitHub handles the rest. This simplicity and ease of use are part of what makes GitHub Actions so powerful!
Now that we have a solid understanding of runners, let’s put this knowledge into action and actually run our “Hello World” workflow on GitHub!
Putting It All into Action: Running Your Workflow
Now comes the exciting part - actually running your workflow on GitHub! We’ve written our workflow code, and we understand that GitHub-hosted runners will execute it. So, let’s get that code into our repository and see the magic happen.
Step 1: Staging Your Changes
Remember how we created the main.yml
file inside the .github/workflows
directory? That file is currently only on your local computer. To get it onto GitHub, we first need to “stage” it, which essentially means preparing it to be saved as a version in Git.
Here’s how to do it in VS Code:
-
Click the Source Control icon in the left sidebar (it looks like a branch or a “Y” shape).
-
You should see
main.yml
listed under “Changes.” -
Click the
+
(plus) icon next tomain.yml
. This stages the file, marking it for inclusion in your next commit.Figure 3: Staging the workflow file in VS Code
(Note: The command-line equivalent for staging is git add .github/workflows/main.yml
)
Step 2: Committing Your Changes
Now that we’ve staged our file, it’s time to commit it. Think of a commit as taking a snapshot of your changes at a specific point in time. It’s like saving a version of your work.
Here’s how to commit in VS Code:
-
In the Source Control panel, you’ll see a message box at the top.
-
Type a descriptive commit message, such as “Add Hello World workflow”.
-
Click the “Commit” button (the prominent button with the checkmark icon located above the message box) to commit the changes.
Figure 4: Committing the workflow file in VS Code
(Note: The command-line equivalent for committing is git commit -m "Add Hello World workflow"
)
Step 3: Syncing Your Changes to GitHub
We’ve saved our changes locally, but they’re still not on GitHub. To get them there, we need to “sync” our commit. You will notice that the commit button now displays “Sync Changes” with a number “1” next to the upward-pointing arrow.
Here’s how to do it in VS Code:
-
Click the “Sync Changes” button in the Source Control panel.
Figure 5: Syncing the changes to GitHub using VS Code
-
You might see a message saying, “This action will pull and push commits from and to ‘origin/main’”. This is just VS Code letting you know that it’s going to update your local repository with any changes from GitHub (if there are any) and then upload your new commit to GitHub. Click “OK”.
Figure 6: Confirming the pull and push actions of “Sync Changes” in VS Code
(Note: In VS Code, the “Sync Changes” button performs both a git pull
and a git push
operation. It first pulls any changes from the remote repository to your local machine and then pushes your local commits to the remote repository on GitHub. The command-line equivalent for pushing is git push origin main
)
Step 4: Watching Your Workflow Run
Now, head over to your repository on GitHub.
-
Click on the “Actions” tab. You should see your “Hello World” workflow listed, along with a summary of the most recent run.
Figure 7: Initial view of the Actions tab on GitHub after pushing the workflow
In this view, you can see all your workflows, their runs, and their status. Notice the green checkmark next to your “Add Hello World workflow” run? That means it completed successfully!
-
Click on the “Add Hello World workflow” run (the one with the green checkmark). This will take you to a more detailed view of that specific run.
Figure 8: Viewing the details of the workflow run on GitHub
Here, you can see an overview of the run, including the trigger, status, how long it took, and more. You’ll also see the “say-hello” job listed under the “Jobs” section.
Note: You might notice a warning message under the “Annotations” section, saying that “ubuntu-latest” will soon use a new version of Ubuntu. This is just an informational message from GitHub and doesn’t affect our simple workflow. In future articles, we will explore how to specify different runner versions if needed.
-
Click on the “say-hello” job. This will show you the individual steps that were executed within that job. They’ll be collapsed by default.
Figure 9: Viewing the collapsed logs of the say-hello job on GitHub
-
Click on each step under the “say-hello” job (e.g., “Set up job,” “Say hello,” “Tell us the time,” “Complete job”) to expand it and view its details. You should see the output of your “echo” and “date” commands in the “Say hello” and “Tell us the time” steps, respectively.
Figure 10: Viewing the expanded logs of the say-hello job on GitHub
Note: You’ll notice two extra steps that we didn’t define in our workflow: “Set up job” and “Complete job.” These are standard steps that GitHub Actions automatically adds to set up the runner environment before your job starts and to clean up afterward.
Practice Makes Perfect
Why not try triggering the workflow again? You can make a small change to your README.md
file in VS Code, then stage, commit, and sync the changes just like we did with the workflow file. Head back to the “Actions” tab on GitHub, and you’ll see your workflow running again!
Congratulations! You’ve just run your first GitHub Actions workflow! How amazing is that? You created a workflow file, committed it to your repository, pushed it to GitHub, and watched as GitHub Actions automatically executed it on a hosted runner.
In the next section, we’ll add a brief troubleshooting section, but for now, take a moment to appreciate what you’ve accomplished. You’re well on your way to mastering automation with GitHub Actions!
Troubleshooting
Even with the best instructions, things might not always go as planned. Here are a few common issues you might encounter and how to solve them:
1. Indentation Errors:
YAML files, like the one we used for our workflow, are very sensitive to indentation. Using the wrong number of spaces or mixing spaces and tabs can lead to errors.
- Symptom: Your workflow fails to run, and you see an error message in the Actions tab that mentions “YAML” or “indentation.”
- Solution:
- Make sure you are using two spaces for each indentation level.
- Do not use tabs. Most code editors, including VS Code, can be configured to use spaces instead of tabs automatically.
- Carefully review the indentation of your
main.yml
file, comparing it to the example in this article. Each nested level (e.g., steps within a job) should be indented by two additional spaces.
2. Workflow Not Triggering:
- Symptom: You push changes to your repository, but the workflow doesn’t run.
- Solutions:
- Check the “Actions” tab: Make sure you are looking at the “Actions” tab on your GitHub repository to see if any workflows are running or have run.
- Verify the trigger event: Double-check that your workflow is set to trigger on the correct event (e.g.,
on: [push]
for pushes to the repository). - Ensure the workflow file is in the correct location: The workflow file (
main.yml
) must be located in the.github/workflows
directory of your repository. - Check for typos: Make sure there are no typos in the file path, filename, or the
on:
trigger definition.
3. Workflow Fails with an Error:
- Symptom: The workflow runs but fails, indicated by a red “X” icon in the Actions tab.
- Solution:
- Read the logs: Click on the failed workflow run, then click on the job (e.g., “say-hello”). Expand each step to view its logs. The error message in the logs will usually provide clues about what went wrong.
- Check for typos: Carefully review your workflow YAML file for any typos, especially in commands or file paths.
- Check the syntax of your code: A common pitfall in writing code is typos, and a small typo can cause the code to malfunction. Carefully check the correctness of your code.
4. “Sync Changes” Button Not Appearing:
- Symptom: After committing in VS Code, the “Sync Changes” button doesn’t appear.
- Solutions:
- Check for Unstaged Changes: Ensure all changes have been staged before committing.
- Check for Uncommitted Changes: Make sure you’ve committed all your changes. The ‘Sync Changes’ button will only appear if you have local commits that haven’t been pushed.
- Verify Remote Connection: Make sure your local repository is properly connected to your remote GitHub repository. You can verify this by checking the status of your repository using
git status
in the VS Code integrated terminal. It will show you the status of your files and if you are connected to a remote repository. You can also try to push from the command line usinggit push origin main
. If this fails, you may need to re-add the remote origin or check your Git configuration. - Restart VS Code: Sometimes, restarting VS Code can resolve minor glitches.
If you encounter other issues, don’t hesitate to consult the official GitHub Actions documentation or search for solutions online. The GitHub community is vast and helpful! You can also leave a comment below, and we will do our best to assist you.
Wrapping Up
Congratulations! You’ve not only created and run your first GitHub Actions workflow but also learned how to troubleshoot common issues. That’s a fantastic accomplishment!
In this article, we started by exploring the fundamentals of GitHub Actions and understanding how it can transform your development workflow by automating tedious tasks. We then walked through the key components: workflows, events, jobs, steps, and actions. We put our knowledge into practice by creating a simple “Hello World” workflow, seeing how to structure it in a YAML file, and running it on a GitHub-hosted runner. Finally, we learned how to use VS Code to manage our changes and push them to GitHub, triggering the workflow automatically.
You now have a solid foundation for automating your development process with GitHub Actions. You know how to create workflows, define triggers, set up jobs, and write steps. You’ve also seen how GitHub-hosted runners provide a convenient way to execute your workflows without managing your own infrastructure.
In the upcoming articles, we’ll dive deeper into more advanced GitHub Actions features. We’ll explore different types of triggers, learn how to use actions from the GitHub Marketplace, work with different types of runners, and build more complex workflows that automate real-world development tasks.
Stay tuned, keep practicing, and get ready to take your automation skills to the next level! We’d love to hear about your experience with this tutorial! Feel free to leave a comment below, ask questions, or share your own “Hello World” workflow. Happy automating!