GitHub: Production Ready Pipeline

GitHub: Production Ready Pipeline

This is the second part of a four-part series providing you with, well, production-ready pipelines. Each part focuses on one of the leading software delivery platforms. Last time we covered GitLab, and today we dive into GitHub.

The Series

This series uses a repository specifically designed to highlight each of the software delivery platforms. As usual I include extra goodies not directly related to the topic. Please feel free to use whatever you find useful.

GitHub Workflow

Let's get straight to the goods, 'cuz you don't have a ton of free time to be reading my gibberish. Below is the repository's GitHub workflow.

Since we have already covered a GitLab pipeline in Part 1, we might as well contrast that as we go through this workflow.

Trigger

You configure the workflow trigger via the on node. I advise my clients to strive to use the following trigger configuration. All pushes are in; yes even in your very private/personal branch. Additionally all pull requests targeting master are in. Why? Well, nothing in the repository is "yours" - and at any moment another team member (e.g., developer, tester) should be able to continue work where you left off. All branches should be passing.

Permissions

Workflows need permissions (e.g., read GitHub branch, write to GitHub Pages, write to GitHub Registry). You configure these using the permissions node.

Jobs

Similar to GitLab stages, GitHub jobs is how we configure what a workflow should do. Jobs are run in parallel, but unlike GitLab there is no top-level node where we configure job order. So if you need jobs to run in some logical sequence then you will use the needs setting.

I'm gonna assume that runs-on and container nodes are well understood, but if you want to explore them in detail go ahead and click through on their respective links.

Steps

Finally, the interesting part. The steps node is where the job's actual work is configured. Let's look at the meaningful steps in detail; if I skip over a step it's only because it's properly documented elsewhere on the web.

All software delivery platforms support the run node. This allows us to specify one or more command-lines to be executed in the configured shell. I advise everyone to prefer this method, rather than using an open-source action. Why? Well, for two reasons: 1) your step is more explicit in what and how it is doing; and 2) you retain the most control over what your step does. In reality most steps will utilize a pre-built action, but if you start with this rule then you won't end up with regrets about having your hands tied or the action not working the way you want it to work.

Since the repository is a .NET 7 solution, the above "test" step runs all tests, produces code coverage data, installs a coverage tool, and then uses that tool to generate a code coverage report (along with pretty badges).

These steps are focused on publishing the code coverage report to a GitHub Pages site. This is one (of many) ways of making coverage reports available for deep linking. For example...

While GitLab has more integrated handling of publishing pipeline content, GitHub's features for this are more than adequate.

Before moving on, it's worth mentioning that we have complete control when/whether a step runs using the if setting. As you see above, the GitHub Pages publishing is configured to run only if the workflow is running against the master branch.

The final step to review is building and pushing images. Above we are logging in to GitHub Registry, building a Docker image for Api with three tags, and then pushing the tagged package to GitHub Registry. This is stuff I'm sure you've done a million times, so I will only mention that in a GitHub workflow you want to be sure to set id-token: write and packages: write permissions. That will enable you to log in to the registry and push packages.

Conclusion

In this Part 2, we took a look at a production-ready pipeline for GitHub Actions. We talked about some of the best practices I advise my clients (e.g., trigger on all branches). And we contrasted a GitHub Actions workflow with a GitLab pipeline.

I hope you are finding this series meaningful. If so, stay tuned for Jenkins which is next up. And as always...

Code well, and shape the future.

Resources