Techno Blender
Digitally Yours.

How to Write Your Own GitHub Action | by Meysam | Oct, 2022

0 55


Complete your CI/CD toolbox with GitHub Workflows

Several jars of kitchen ingredients
Photo by Pixabay: https://www.pexels.com/photo/aroma-aromatic-assortment-bottles-531446/

GitHub has evolved a lot since Microsoft took over, amid the conglomerate nature of big corporations, or despite it rather. One of the many things that have advanced drastically in GitHub is the CI/CD pipelines. GitHub provides many good workflows and others developed by the open-source community in recent years, with yet more to come as the technology evolves.

This has opened the door for many opportunities since many companies already keep their source codes in GitHub, one of the first players in the market [source]!

While this may sound scary, making one company stronger than others can also open many possibilities and innovations since the traction of the community will drive towards creating more and more value which ultimately will benefit everyone.

Although it is very trivial to many engineers, defining the term is crucial for starters. GitHub Action is the CI/CD pipeline you get once you have an account in GitHub with one or more repositories, each repository having its pipeline workflows.

It enables you to define all the steps you like to happen on a set of specified triggers. The following are a number few examples of such “actions”:

  • Running tests on your repository when a pull request comes in.
  • Running language-specific linters on your project on every push.
  • Deploying to dev/prod when a new release is published.

These are just a few examples of what is possible with GitHub Action, and there are countless more you can think of, depending on the project’s requirements.

A young adult preparing to run in a track
Photo by nappy: https://www.pexels.com/photo/man-wearing-white-sweater-and-black-shorts-about-to-run-936094/

We live in the 21st century, and almost every software problem is already solved; you only need to look hard enough for the problem domain, tie stuff together and ultimately configure the whole platform in a way that can fit your requirements.

It’s all the same for GitHub Actions, as there are already numerous workflow definitions that you can put into your project’s CI/CD definition, pass in the correct value and get what you expect.

This drives us to a point where you will likely not need to rewrite things from scratch.

But even so, there might be occasions where:

  • The available solutions don’t fit your problem
  • The complexity of the problem and the available solution do not align
  • The solution is not flexible configuration-wise

All these and many more are good enough reasons to want to write your own custom GitHub Action, and this is what this article is all about.

We will dive into different ways of writing a custom GitHub Action and provide a practical example of each.

When writing this article, there are three ways you can write GitHub Action. The approaches below can be used to create & publish a GitHub Action, either open-sourced and publicly available for the community or privately for your own.

The types of available GitHub Actions are:

  1. JavaScript: If you’re among the 17.5 million JS developers, or if you’re among the %65 of 70k Stackoverflow survey respondents, you will most likely find this approach to your liking since you can write your logic with your preferred language.
  2. Docker: If you’re not a JavaScript developer, though, just like me, you’ll find this one very interesting since anything that can be containerized can also be shipped as a GitHub Action; these days, that means any application, thanks to the efforts of many great engineers.
  3. Composite: Last but not least, my very favorite one, allowing you to combine multiple GitHub Actions into one, also sold as “Reusable Workflows” to the public.

Since I’m not a JavaScript developer, more than just being able to read and somewhat understand what it does to a certain extent, I will not put more focus there and, instead, magnify where I feel strongest: Docker & Composite.

Two kids holding two balls in front of two cars
Photo by Victoria Akvarel: https://www.pexels.com/photo/two-boys-playing-soccer-ball-beside-cars-1564868/

Choosing any approach for writing a GitHub Action, you’ll need one crucial file that will serve as the definition of your GitHub Action.

The name of the file has to be precisely action.yml , and it should reside at the root of your project. Among many other things, here are the things that you specify in that definition file:

  • What are the inputs
  • How to invoke the Action, i.e., what file or binary to execute
  • What kind of output can one expect to get

Like many other great definition files, this definition is in YAML format, one of the most controversial. Here’s a sample action.yml taken from the GitHub docs.

This file has three main components; all others are optional.

  • name: this a unique name assigned to the Action. This name serves as the ID, and it is required to be unique because the URL github.com/marketplace/actions/MY_GITHUB_ACTION will be given to it, and that cannot be duplicated; this only holds for public Actions that are meant to be published to the GitHub Marketplace and are not needed to be unique otherwise.
  • inputs: a set of names that the Action will receive as its parameters. Think of kubectl get pod --output=yaml which, in this case, the “output” is a parameter to the kubectl binary.
  • runs: the essential part of any Action is where you define the “type” of your Action, one of the three types described above. That “type” is specified under the key using and tells the “runner” how to run your Action. When using docker, you’ll need to specify the path to your Dockerfile with the attribute image. The args is self-explanatory in that it will pass the inputs to the underlying implementation.

This definition, when correctly specified, will tell the GitHub Runner how to run your Action. It acts as the entry point; without it, the logic defined in the repository will not be executed since the runner doesn’t know how.

Now that we have defined the outline of GitHub Action, let us complete the argument by bringing some practical examples.

Containerized applications have gained much traction in recent years for good reasons. They allow you to write your application in the programming language of your choice, put it in its own “capsule,” and ship it everywhere, at least nearly.

Even with the limitation of platform-specific image build, you’re still able to create stuff and provide it to a broader audience; compare this to the era where bare metal was the only option, needing to keep in sync the JVM version installed on all the machines, for example!

Now let us jump into the actual code, where we will develop an actual GitHub Action.

Requirement: Send Email Notification on Every GitHub Release

With the introduction, history, and definitions out of the way, it’s time to write some code. In this code, we’ll send an email to a list of people on every GitHub release.

The implementation logic is language-agnostic, but the implementation is not. Here we’ll write a Python app that does the job using SendGrid’s SDK.

As you can see, there is no complexity to the code; it’ll receive the required inputs, prepares the email, and send it accordingly. Several debugging lines help the user understand what stage we’re in, and an exception handling that does nothing but print it out on the standard error.

The Markdown library is used because we will fetch the release note and pass it to the GitHub Action in markdown format.

Containerize the Application

Writing a Dockerfile is the key that allows us to run the app inside an isolated environment, anywhere, anytime, and on any operating system.

If you’re interested in tips and tricks on how to write a proper Dockerfile, check out the link below.

The definition of an app, as noted above, could look like this:

Of course, the send-email-with-sendgrid.py has to be executable with a proper shebang. To make it executable, you will run chmod +x FILENAME.

Define the GitHub Action

We have only written our logic up until now, but it cannot be used in a GitHub Action without a well & proper defined action.yml and that’s where the next step comes in.

We will need a YAML formatted file that will define the Action’s name, the inputs, and how to run it, i.e., how to pass the arguments.

Here’s what such a file will look like.

The args defined in the action.yml are passed as cmd to the docker container. The args are the same ones that are defined with argparse in the Python app above.

Publish to GitHub Marketplace

We have written all the logical implementation code needed to run the app as a GitHub Action. Still, as a final step, if we want to publish our app in the Marketplace and make it searchable, we will need to create a new release, which is probably the easiest step.

As a demonstration, the screenshots are provided below.

The last checkbox is vital since it indicates that you want to publish your GitHub Action on the Marketplace, effectively allowing other people to use it. Ultimately, you will see your GitHub Action in the Marketplace, similar to the picture below.

Upon such GitHub release, you and others will be able to use the GitHub Action using the following YAML-formatted workflow placed under the .github/workflows/ directory of the repository.

This is as easy as it can get. You can, of course, get creative and do more fancy stuff!

Source Code

All the files are available from the link below.

It is crucial to understand that GitHub Runners are contained in a new virtual machine every time they are triggered & they will be disposed of when finished [source]. This means that what you have done in a previous run will not be available unless you’ve saved the result, e.g., GitHub Artifact or GitHub Cache.

That said, you can combine multiple stages of a workflow file and publish it as a single GitHub Action, allowing you to “reuse” it as a unified whole, hence the name “Reusable Workflows.”

This type of GitHub Action is called “composite.” As the name suggests, it comprises a composite of other steps. This is ideal for scenarios where different CI/CD steps are needed for multiple repositories. You don’t want to repeat the same steps everywhere, but rather maintain one repository and update accordingly.

Requirement: Deploy Helm Release to Kubernetes Cluster

We want to deploy Helm Chart with a set of configurable flags to a specific Kubernetes cluster every time a new push to the default branch happens. This requires the following steps:

  1. Install a particular Helm version, ideally configurable.
  2. Fetch the Kubeconfig and the Helm values file, either as YAML encoded string or as a file path in the underlying operating system, e.g., fetched from AWS S3.
  3. Change the file permission of the Kubeconfig & Helm values file on user requests.
  4. Deploy the actual Chart with a configurable release name.
  5. Clean up on user requests, i.e., removing the Kubeconfig and the Helm values file, for security reasons!

Here’s what such a requirement would look like in a GitHub Action definition file:

Notice the value under .runs.using which is composite, meaning that we will define the runnable steps in the same action.yml file.

These “steps” are the same steps as you would otherwise put in any of the files placed under .github/workflows/ The only difference is the shell attribute, which is a required key for every step. It tells the runner how the commands should run. The list of available shells is documented here.

The syntax of the file is self-explanatory, as well as human-readable. Everything you see under the run attribute of every step is a set of bash-executable commands.

You can also place any Python or JavaScript file in the same repository and call that file from the same action.yml file, making your GitHub Action more powerful and versatile.

How to Use this?

You will, effectively, have a workflow definition similar to the below for using the above GitHub Action.

Source Code

All the files are available from the link below.

Sunset picture taken from the middle of the street
Photo by Nout Gons: https://www.pexels.com/photo/road-in-city-during-sunset-248159/

CI/CD has made our operations’ lives a lot easier, giving us the agility to develop and removing the burden of manual and repeatable deployments. In the 21st century and with the rise of many tools and technologies that aim to automate repeatable jobs, CI/CD has been among the most successful ones that are an integral part of every company these days, making them not a luxury, but a requirement to keep the level of maintainability to a maximum amount.

GitHub Actions, one of the most famous CI/CD toolboxes, gives a lot of functionality. To compete with the current CI/CD solutions, GitHub Actions has come a long way to provide extendability so that people can create and publish their solutions for a specific requirement. You will be able to find many off-the-shelf workflows that are ready for your production battle.

In this article, we have given practical examples of how to write an actual custom GitHub Action when you can’t find a ready-made one. With this knowledge in your toolbox, you’ll be unstoppable in the amount of value you can create for yourself, your company, and the community.

Have an excellent rest of the day. Stay tuned, and take care!


Complete your CI/CD toolbox with GitHub Workflows

Several jars of kitchen ingredients
Photo by Pixabay: https://www.pexels.com/photo/aroma-aromatic-assortment-bottles-531446/

GitHub has evolved a lot since Microsoft took over, amid the conglomerate nature of big corporations, or despite it rather. One of the many things that have advanced drastically in GitHub is the CI/CD pipelines. GitHub provides many good workflows and others developed by the open-source community in recent years, with yet more to come as the technology evolves.

This has opened the door for many opportunities since many companies already keep their source codes in GitHub, one of the first players in the market [source]!

While this may sound scary, making one company stronger than others can also open many possibilities and innovations since the traction of the community will drive towards creating more and more value which ultimately will benefit everyone.

Although it is very trivial to many engineers, defining the term is crucial for starters. GitHub Action is the CI/CD pipeline you get once you have an account in GitHub with one or more repositories, each repository having its pipeline workflows.

It enables you to define all the steps you like to happen on a set of specified triggers. The following are a number few examples of such “actions”:

  • Running tests on your repository when a pull request comes in.
  • Running language-specific linters on your project on every push.
  • Deploying to dev/prod when a new release is published.

These are just a few examples of what is possible with GitHub Action, and there are countless more you can think of, depending on the project’s requirements.

A young adult preparing to run in a track
Photo by nappy: https://www.pexels.com/photo/man-wearing-white-sweater-and-black-shorts-about-to-run-936094/

We live in the 21st century, and almost every software problem is already solved; you only need to look hard enough for the problem domain, tie stuff together and ultimately configure the whole platform in a way that can fit your requirements.

It’s all the same for GitHub Actions, as there are already numerous workflow definitions that you can put into your project’s CI/CD definition, pass in the correct value and get what you expect.

This drives us to a point where you will likely not need to rewrite things from scratch.

But even so, there might be occasions where:

  • The available solutions don’t fit your problem
  • The complexity of the problem and the available solution do not align
  • The solution is not flexible configuration-wise

All these and many more are good enough reasons to want to write your own custom GitHub Action, and this is what this article is all about.

We will dive into different ways of writing a custom GitHub Action and provide a practical example of each.

When writing this article, there are three ways you can write GitHub Action. The approaches below can be used to create & publish a GitHub Action, either open-sourced and publicly available for the community or privately for your own.

The types of available GitHub Actions are:

  1. JavaScript: If you’re among the 17.5 million JS developers, or if you’re among the %65 of 70k Stackoverflow survey respondents, you will most likely find this approach to your liking since you can write your logic with your preferred language.
  2. Docker: If you’re not a JavaScript developer, though, just like me, you’ll find this one very interesting since anything that can be containerized can also be shipped as a GitHub Action; these days, that means any application, thanks to the efforts of many great engineers.
  3. Composite: Last but not least, my very favorite one, allowing you to combine multiple GitHub Actions into one, also sold as “Reusable Workflows” to the public.

Since I’m not a JavaScript developer, more than just being able to read and somewhat understand what it does to a certain extent, I will not put more focus there and, instead, magnify where I feel strongest: Docker & Composite.

Two kids holding two balls in front of two cars
Photo by Victoria Akvarel: https://www.pexels.com/photo/two-boys-playing-soccer-ball-beside-cars-1564868/

Choosing any approach for writing a GitHub Action, you’ll need one crucial file that will serve as the definition of your GitHub Action.

The name of the file has to be precisely action.yml , and it should reside at the root of your project. Among many other things, here are the things that you specify in that definition file:

  • What are the inputs
  • How to invoke the Action, i.e., what file or binary to execute
  • What kind of output can one expect to get

Like many other great definition files, this definition is in YAML format, one of the most controversial. Here’s a sample action.yml taken from the GitHub docs.

This file has three main components; all others are optional.

  • name: this a unique name assigned to the Action. This name serves as the ID, and it is required to be unique because the URL github.com/marketplace/actions/MY_GITHUB_ACTION will be given to it, and that cannot be duplicated; this only holds for public Actions that are meant to be published to the GitHub Marketplace and are not needed to be unique otherwise.
  • inputs: a set of names that the Action will receive as its parameters. Think of kubectl get pod --output=yaml which, in this case, the “output” is a parameter to the kubectl binary.
  • runs: the essential part of any Action is where you define the “type” of your Action, one of the three types described above. That “type” is specified under the key using and tells the “runner” how to run your Action. When using docker, you’ll need to specify the path to your Dockerfile with the attribute image. The args is self-explanatory in that it will pass the inputs to the underlying implementation.

This definition, when correctly specified, will tell the GitHub Runner how to run your Action. It acts as the entry point; without it, the logic defined in the repository will not be executed since the runner doesn’t know how.

Now that we have defined the outline of GitHub Action, let us complete the argument by bringing some practical examples.

Containerized applications have gained much traction in recent years for good reasons. They allow you to write your application in the programming language of your choice, put it in its own “capsule,” and ship it everywhere, at least nearly.

Even with the limitation of platform-specific image build, you’re still able to create stuff and provide it to a broader audience; compare this to the era where bare metal was the only option, needing to keep in sync the JVM version installed on all the machines, for example!

Now let us jump into the actual code, where we will develop an actual GitHub Action.

Requirement: Send Email Notification on Every GitHub Release

With the introduction, history, and definitions out of the way, it’s time to write some code. In this code, we’ll send an email to a list of people on every GitHub release.

The implementation logic is language-agnostic, but the implementation is not. Here we’ll write a Python app that does the job using SendGrid’s SDK.

As you can see, there is no complexity to the code; it’ll receive the required inputs, prepares the email, and send it accordingly. Several debugging lines help the user understand what stage we’re in, and an exception handling that does nothing but print it out on the standard error.

The Markdown library is used because we will fetch the release note and pass it to the GitHub Action in markdown format.

Containerize the Application

Writing a Dockerfile is the key that allows us to run the app inside an isolated environment, anywhere, anytime, and on any operating system.

If you’re interested in tips and tricks on how to write a proper Dockerfile, check out the link below.

The definition of an app, as noted above, could look like this:

Of course, the send-email-with-sendgrid.py has to be executable with a proper shebang. To make it executable, you will run chmod +x FILENAME.

Define the GitHub Action

We have only written our logic up until now, but it cannot be used in a GitHub Action without a well & proper defined action.yml and that’s where the next step comes in.

We will need a YAML formatted file that will define the Action’s name, the inputs, and how to run it, i.e., how to pass the arguments.

Here’s what such a file will look like.

The args defined in the action.yml are passed as cmd to the docker container. The args are the same ones that are defined with argparse in the Python app above.

Publish to GitHub Marketplace

We have written all the logical implementation code needed to run the app as a GitHub Action. Still, as a final step, if we want to publish our app in the Marketplace and make it searchable, we will need to create a new release, which is probably the easiest step.

As a demonstration, the screenshots are provided below.

The last checkbox is vital since it indicates that you want to publish your GitHub Action on the Marketplace, effectively allowing other people to use it. Ultimately, you will see your GitHub Action in the Marketplace, similar to the picture below.

Upon such GitHub release, you and others will be able to use the GitHub Action using the following YAML-formatted workflow placed under the .github/workflows/ directory of the repository.

This is as easy as it can get. You can, of course, get creative and do more fancy stuff!

Source Code

All the files are available from the link below.

It is crucial to understand that GitHub Runners are contained in a new virtual machine every time they are triggered & they will be disposed of when finished [source]. This means that what you have done in a previous run will not be available unless you’ve saved the result, e.g., GitHub Artifact or GitHub Cache.

That said, you can combine multiple stages of a workflow file and publish it as a single GitHub Action, allowing you to “reuse” it as a unified whole, hence the name “Reusable Workflows.”

This type of GitHub Action is called “composite.” As the name suggests, it comprises a composite of other steps. This is ideal for scenarios where different CI/CD steps are needed for multiple repositories. You don’t want to repeat the same steps everywhere, but rather maintain one repository and update accordingly.

Requirement: Deploy Helm Release to Kubernetes Cluster

We want to deploy Helm Chart with a set of configurable flags to a specific Kubernetes cluster every time a new push to the default branch happens. This requires the following steps:

  1. Install a particular Helm version, ideally configurable.
  2. Fetch the Kubeconfig and the Helm values file, either as YAML encoded string or as a file path in the underlying operating system, e.g., fetched from AWS S3.
  3. Change the file permission of the Kubeconfig & Helm values file on user requests.
  4. Deploy the actual Chart with a configurable release name.
  5. Clean up on user requests, i.e., removing the Kubeconfig and the Helm values file, for security reasons!

Here’s what such a requirement would look like in a GitHub Action definition file:

Notice the value under .runs.using which is composite, meaning that we will define the runnable steps in the same action.yml file.

These “steps” are the same steps as you would otherwise put in any of the files placed under .github/workflows/ The only difference is the shell attribute, which is a required key for every step. It tells the runner how the commands should run. The list of available shells is documented here.

The syntax of the file is self-explanatory, as well as human-readable. Everything you see under the run attribute of every step is a set of bash-executable commands.

You can also place any Python or JavaScript file in the same repository and call that file from the same action.yml file, making your GitHub Action more powerful and versatile.

How to Use this?

You will, effectively, have a workflow definition similar to the below for using the above GitHub Action.

Source Code

All the files are available from the link below.

Sunset picture taken from the middle of the street
Photo by Nout Gons: https://www.pexels.com/photo/road-in-city-during-sunset-248159/

CI/CD has made our operations’ lives a lot easier, giving us the agility to develop and removing the burden of manual and repeatable deployments. In the 21st century and with the rise of many tools and technologies that aim to automate repeatable jobs, CI/CD has been among the most successful ones that are an integral part of every company these days, making them not a luxury, but a requirement to keep the level of maintainability to a maximum amount.

GitHub Actions, one of the most famous CI/CD toolboxes, gives a lot of functionality. To compete with the current CI/CD solutions, GitHub Actions has come a long way to provide extendability so that people can create and publish their solutions for a specific requirement. You will be able to find many off-the-shelf workflows that are ready for your production battle.

In this article, we have given practical examples of how to write an actual custom GitHub Action when you can’t find a ready-made one. With this knowledge in your toolbox, you’ll be unstoppable in the amount of value you can create for yourself, your company, and the community.

Have an excellent rest of the day. Stay tuned, and take care!

FOLLOW US ON GOOGLE NEWS

Read original article here

Denial of responsibility! Techno Blender is an automatic aggregator of the all world’s media. In each content, the hyperlink to the primary source is specified. All trademarks belong to their rightful owners, all materials to their authors. If you are the owner of the content and do not want us to publish your materials, please contact us by email – [email protected]. The content will be deleted within 24 hours.

Leave a comment