Software development is inherently a complex activity. Not too long ago, organizations only released software once or twice per year. Today, tools like GitHub Actions make it possible to release code into production dozens and even hundreds of times in a single day.
In this article, we will introduce you to the basics of GitHub Actions and explore five common GitHub Actions CI/CD best practices to take into account while using GitHub Actions:
- What Is GitHub Actions? Is GitHub Actions CI/CD?
- How do I add a CI/CD to GitHub?
- GitHub Actions CI/CD Best Practices
What Is GitHub Actions? Is GitHub Actions CI/CD?
To meet the demands for automation in continuous integration and deployment (CI/CD) pipelines, GitHub launched “Actions”—integrated CI/CD capabilities on top of their popular code versioning and management platform. The native ecosystem integration enables projects to be automated from the moment code is committed by developers to deployment into production.
The built-in integrations with third-party tools, and ease of use combined with the large pre-existing user base makes GitHub Actions a fast-rising star among CI/CD tools.
How Do I Add a CI/CD to GitHub?
Everyone that has a GitHub account, including non-paid ones, gets automatic access to these CI/CD features as part of their projects without an additional cost.
GitHub Actions CI/CD Best Practices
1. Using Self-Hosted Runners in GitHub Actions Workflows
In GitHub Actions the instructions are executed in “runners”. Runners are execution agents that can either be provided by the GitHub platform or self-hosted. While self-hosting runners increases your operational overhead, there are two big advantages in choosing this option: free runner minutes and increased security.
GitHub Actions customers are billed monthly based on the amount of used minutes per runner. Every plan includes a certain amount of minutes at zero cost and projects are only billed above that quota. The self-hosted runners are always free and don’t count towards the limit. However, it is worth keeping in mind that you might incur computational costs on your environment (data center or cloud provider).
Using self-hosted runners in private repositories is a great practice, giving you full control over the operating system and underlying infrastructure. This opens the possibility to use hardened images according to your organization’s security policies rather than the default GitHub public image. Moreover, this option is particularly important for teams who are doing cloud deployments.
Public-hosted runners require credentials with very broad permissions to your cloud environment to be stored in GitHub. In turn, self-hosted private runners only require GitHub to have credentials that enable the deployment of the runner inside your cloud environment. Any needed permissions can be trusted upon the runner using a specific cloud IAM role. This significantly reduces the exposure of highly privileged credentials outside the cloud environment.
When NOT to use self-hosted runners?
While self-hosted runners are a good practice, using them alongside public repositories is not a desirable scenario. With public repositories that are openly accessible to anyone on the internet, using self-hosted runners might expose you to a situation where malicious code can be merged into the pipeline and be executed in the environment of the private self-hosted runner. Therefore, public runners are more suitable for public repositories. This attack vector is a good reminder that self-hosted runners should always be set in a dedicated environment separated from your production workload.
2. Leveraging GitHub Actions Marketplace
One key differentiating feature of GitHub Actions compared to other CI/CD solutions is the GitHub Actions Marketplace. When developing a new CI/CD pipeline, there are several elements that are common across pipelines and can be reused in the process. GitHub took these code elements (“Actions”) and created a reference library (“Marketplace”) that anyone can leverage.
With the Actions Marketplace, third-party vendors can publish their own code examples, making it more appealing to developers with diverse technology stacks. With popular vendors such as AWS, Microsoft, HashiCorp, Atlassian, and Google already in the marketplace, it is highly probable that you will find Actions that can be leveraged to fulfill the use cases you need.
Marketplace actions can be used to automate tasks, such as performing security scans, creating tickets, sending SMS messages, creating Kubernetes clusters, among much more. Leveraging the action marketplace is a great best practice that enables you to easily follow vendor recommendations, promotes reusability, and significantly reduces the time to develop new CI/CD pipelines.
3. Handling Uncertified Actions
GitHub is actively certifying some of the marketplace actions that are published by third parties. This validation gives an extra assurance to developers that those snippets of code can be trusted.
However, not all actions in the marketplace are certified by GitHub. In fact, the certification badge is only given by GitHub to partner organizations. Therefore, developers and their organizations are often left with a choice on how to handle the uncertified marketplace actions:
- Block all usage
- Fork and allow
- Allow case by case
Let’s take a look at each of these options below.
- Block the Usage of All Uncertified Actions: Blocking the usage of any uncertified by default is a valid option and a route taken especially by large organizations. It is a very conservative approach that gives some peace of mind but prevents engineers from taking advantage of functionalities and forces them to develop additional custom code, increasing the operational overhead.
- Fork and Allow Uncertified Actions: The fork and allow method is a common practice to bypass a blanket restriction on all unverified actions. In this scenario, engineers fork the third-party action repository into their own GitHub organization, thus allowing the action to be used. This approach has some pros and cons worth considering.
Forking enables the action code to be reviewed, changed, and controlled by the engineering team, preventing any unwanted update by the third-party entity that could compromise security. Unfortunately, it is also very common that the action code forked by the engineering teams can be taken into use without any proper review or validation. Plus, without a periodic sync between the forked code and the third-party publisher repository, any improvements, bug fixes, or security patches won’t be available.
- Allow Uncertified Actions Case by Case: Allowing uncertified actions on a case-by-case basis is a good best practice. While the decision to allow these actions shouldn’t be taken lightly, there are cases where denying does not make sense. If you are already using a tool or service from a third-party vendor whose action is not yet certified, allowing it does not significantly increase your risk level. In fact, the same review process and guidelines defined by your organization’s open-source policy should apply to unverified actions codebase.
4. Managing GitHub Actions Secrets
The process of developing a CI/CD pipeline often requires the handling and storage of sensitive information. Secrets such as API keys or service credentials to enable cloud deployments are part of the ingredients needed to automate a process from end to end.
How to Handle Secrets in GitHub Actions?
The worst possible way to handle secrets is to hard code them alongside the CI/CD pipeline code. Regardless of if the GitHub repository where the code is located was marked as private or company-internal, it's a big security risk to have secrets stored as plain text. That’s because it’s near impossible to control the access and usage after someone clones the repository to their local machine.
A good practice is to leverage the GitHub encrypted secrets functionality. This feature enables sensitive data to be encrypted in the GitHub repository (or organization) settings and used as environment variables in the CI/CD pipeline code. This practice limits the access to secrets to only the authorized GitHub runners, preventing sensitive information to be spread among multiple developer machines when cloning repositories. Furthermore, the GitHub secrets feature comes with protection capabilities that prevent attempts to log or print the environment variable value by automatically redacting them to avoid accidental leakage.
5. Self-Hosted Private Runner Reusability and Storage Challenges
Leveraging self-hosted private runners is something engineers typically avoid when they start using GitHub Actions. The initial set up overhead and extra learning curve are not very appealing to GitHub Actions beginners. Also, because self-hosted runners are environment agnostic, there are multiple possible ways to create, customize, and deploy them, making it more challenging to get started.
As mentioned earlier, using self-hosted runners in private repositories is a great best practice. The benefits, while not self-explanatory at first, clearly outweigh the additional effort needed to set them up. One thing that is often overlooked is the need to make that work reusable from the get-go. Leveraging infrastructure as code and cloud automation tools are great ways to manage and deploy self-hosted runners, thus, making them reusable and opening the door to fulfill additional use cases.
How About Storage?
Persistent storage is one of the reasons that engineers opt for self-hosted runners. The underlying storage in the public runners is ephemeral, so any data needed for test automation and validation needs to constantly be downloaded to the public runner. The same applies to any software and configuration required due to the lack of support for custom images.
Automating your self-hosted runner’s deployment and combining it with a good storage management solution, like NetApp Cloud Volumes ONTAP, enables testing environments to be available as templates and rapidly cloned as necessary. This significantly increases the options available to engineers for test automation and quality assurance.
Get More from GitHub Actions CI/CD with NetApp Cloud Volumes ONTAP
It is undeniable that despite its young age, the GitHub Actions CI/CD use case is already a strong and popular player in the CI/CD tooling market. Understanding how to best leverage GitHub Actions to fulfill your use cases and while following industry best practices is a must to unlock its potential.
Cloud Volumes ONTAP, the NetApp data management solution, is a key technology that together with GitHub Actions can speed up your CI/CD pipelines and provide more flexibility and additional features. Cloud Volumes ONTAP can provide persistent storage to self-hosted runners, enabling the rapid creation of testing environments using its FlexClone® technology feature and speeding up the whole CI/CD pipeline workflow.
Moreover, Cloud Volumes ONTAP comes with several out-of-the-box capabilities such as data protection, cost-cutting storage efficiency, and the ability to share data across different environments such as on-premises, AWS, Azure, and Google Cloud.
The Cloud Volumes ONTAP flexibility and array of capabilities can enrich your entire DevOps practices and toolset, try it today. You can learn more about Cloud Volumes ONTAP in these case studies on zero-capacity data cloning and DevOps.
You can learn more about Cloud Volumes ONTAP in these case studies on zero-capacity data cloning and DevOps, and learn How to Set Up GitHub Actions CI/CD Using Self-Hosted AWS Runners and Cloud Volumes ONTAP