<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>pipeline on Digi Hunch</title><link>https://static.digihunch.com/tag/pipeline/</link><description>Recent content in pipeline on Digi Hunch</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Sat, 20 Jul 2024 21:53:05 -0400</lastBuildDate><atom:link href="https://static.digihunch.com/tag/pipeline/index.xml" rel="self" type="application/rss+xml"/><item><title>Getting started with GitHub Actions</title><link>https://static.digihunch.com/2021/05/getting-started-with-github-actions/</link><pubDate>Thu, 27 May 2021 13:52:31 -0400</pubDate><guid>https://static.digihunch.com/2021/05/getting-started-with-github-actions/</guid><description>&lt;p class="wp-block-paragraph"&gt;In my &lt;a class="rank-math-link" href="https://github.com/digihunch/orthweb"&gt;orthweb&lt;/a&gt; &lt;a href="https://static.digihunch.com/projects/"&gt;project&lt;/a&gt;, I had to compile a library on my own. In search for free computing resources I realized that GitHub action can meet all my needs.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-ci-cd-pipeline"&gt;CI/CD pipeline&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;As a development project grows, there are many operational tasks demanding automation. Prior to pipeline technology, developers used to use &lt;a href="https://en.wikipedia.org/wiki/Make_(software)"&gt;Makefile&lt;/a&gt; to organize command execution locally. Today, its role has declined, but &lt;a href="https://tech.trivago.com/post/2019-12-20-makefiles-in-2019/"&gt;Makefile&lt;/a&gt; is a good choice in certain situations. In most cases though, to offload the build command execution to a shared system, automation engines like Jenkins came around. Then Jenkins evolved into pipelines.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In strict terms, CI pipeline is the build pipeline; and CD pipeline is release pipeline. The two types of pipelines use pretty much the same pool of building blocks, with different purposes. The build pipeline focuses on producing quality artifact in a consistent manner. The release pipelines focus on system stability while deploying an artifact across different environments. Because release pipelines may connect to different environment, it has to deal with various situations. It is very common to have multiple stages in release pipeline, each stage pointing to a different environment (e.g. DEV, TEST and PROD). At workplace both could be loosely referred to as CI/CD pipeline, or even simply pipeline.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A lot of projects provide pipeline capability: BitBucket, Bamboo, TeamCity, Jenkins, Azure DevOps, AWS CodePipeline, TravisCI etc. Since late 2018, GitHub also joined the game with GitHub actions. It is openly &lt;a class="rank-math-link" href="https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions#:~:text=GitHub%20Actions%20usage%20is%20free,is%20controlled%20by%20spending%20limits."&gt;free&lt;/a&gt; for public repositories, and has a free tier for private repositories. It executes task as defined in .github/workflow/action.yaml in the code project. I will take my own project as an example.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-runners"&gt;Runners&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;You can run jobs in self-hosted runners or GitHub managed runners, similar to other pipeline solutions (e.g. self-hosted agent vs managed agent from Azure DevOps). The &lt;a href="https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#github-hosted-runners" class="rank-math-link"&gt;GitHub hosted runners&lt;/a&gt; only have three operating systems to support: Windows, Ubuntu and MacOS. The Ubuntu and Windows runners are built from Standard_DS2_v2 VMs in Microsoft Azure. They are pre-installed with a &lt;a href="https://github.com/actions/virtual-environments" class="rank-math-link"&gt;virtual environment &lt;/a&gt;with packages required for common build tasks. The same virtual environment is also used in hosted agents by Azure DevOps. While they are free and you can elevate privilege on the runner, you cannot SSH or RDP to it for further troubleshooting. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The &lt;a href="https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners" class="rank-math-link"&gt;self-hosted runners&lt;/a&gt; require users to manage the instance on their own, including configuring virtual environment, installing &lt;a href="https://github.com/actions/runner" class="rank-math-link"&gt;GitHub Action Runner&lt;/a&gt;, etc.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-workflow-file"&gt;Workflow file&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Most pipeline declaration uses YAML or JSON, such as &lt;a href="https://www.jenkins.io/doc/book/pipeline/jenkinsfile/" class="rank-math-link"&gt;Jenkinsfile&lt;/a&gt;, AWS &lt;a href="https://docs.aws.amazon.com/code-samples/latest/catalog/code-catalog-cloudformation-codepipeline.html" class="rank-math-link"&gt;CodePipeline&lt;/a&gt;. GitHub refers to an automation process as a &amp;#8220;workflow&amp;#8221; and you can program the workflow in YAML (.github/workflow/action.yaml). Here is the &lt;a href="https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions" class="rank-math-link"&gt;reference&lt;/a&gt; and an example with environmental variable and versioning: &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;script src="https://gist.github.com/digihunch/e6ed668872c5b0506d25f638ff70727e.js"&gt;&lt;/script&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The handling of environment is documented &lt;a href="https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable" class="rank-math-link"&gt;here&lt;/a&gt;. There are a lot of custom actions available in GitHub &lt;a href="https://github.com/marketplace" class="rank-math-link"&gt;Marketplace&lt;/a&gt;. For example, the versioning in the above example, uses an &lt;a href="https://github.com/marketplace/actions/nuget-build-number-generator" class="rank-math-link"&gt;action&lt;/a&gt; by &lt;a href="https://einaregilsson.com/a-github-action-for-generating-sequential-build-numbers/" class="rank-math-link"&gt;Einar Egilsson&lt;/a&gt;, which is open source itself.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-example-pipeline"&gt;Example pipeline&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;My example &lt;a href="https://github.com/digihunch/orthweb/blob/67542d9329be36e3b8ca895c8b71805c9711aaa3/.github/workflows/action.yml" class="rank-math-link"&gt;pipeline&lt;/a&gt; consists of two phases: &lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Build Library: spin up a docker container to build source code, and publish the artifact&lt;/li&gt;&#10;&lt;li&gt;Publish Image: add the artifact to an existing Docker image, and publish the result as my own image.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The status of the pipeline is also open, and can be found &lt;a href="https://github.com/digihunch/orthweb/actions" class="rank-math-link"&gt;here&lt;/a&gt;. The retention period of artifact is 90 days by default but can be &lt;a href="https://docs.github.com/en/actions/reference/usage-limits-billing-and-administration#artifact-and-log-retention-policy" class="rank-math-link"&gt;customized&lt;/a&gt;. To persist the artifact, I add it to my own Docker image and publish it to &lt;a href="https://hub.docker.com/r/digihunch/orthanc-plugin" class="rank-math-link"&gt;DockerHub&lt;/a&gt;, hence the second phase.&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img loading="lazy" decoding="async" width="1152" height="724" src="https://static.digihunch.com/wp-content/uploads/2021/05/image-1.png" alt="" class="wp-image-2299"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt; When building the second phase, I need to generate secret from my DockerHub account and store that &lt;a href="https://docs.github.com/en/actions/reference/encrypted-secrets" class="rank-math-link"&gt;encrypted secrets&lt;/a&gt; in GitHub settings, so that the secret value can be referenced in workflow file.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Failures in Actions are displayed in error steps and by default the rest of the steps are skipped. &lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img loading="lazy" decoding="async" width="968" height="624" src="https://static.digihunch.com/wp-content/uploads/2021/05/image-2.png" alt="" class="wp-image-2301"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I use the &lt;strong&gt;&lt;a class="rank-math-link" href="https://github.com/marketplace/actions/docker-build-push-action"&gt;Docker build &amp;amp; push plugin&lt;/a&gt;&lt;/strong&gt; to build and push my own docker image to DockerHub. Apart from DockerHub as my choice, GitHub also has its own artifactory GitHub &lt;a class="rank-math-link" href="https://github.com/features/packages"&gt;Packages&lt;/a&gt; with a small free tier. It supports NPM, Docker, Maven, Gradle, etc. &lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Triggers of Action&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Most of the times, GitHub action are triggered upon commit to main branch of the repo. In GitHub, this is known as a &lt;a href="https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch"&gt;workflow_dispatch&lt;/a&gt; event. This is not the only event that can trigger GitHub action. All the available events are listed &lt;a href="https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#available-events"&gt;here&lt;/a&gt; on its documentation. This makes it very flexible to trigger action at many points in the workflow. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;One example is to trigger GitHub action during PR review. When a developer opens a PR with a few commits in the proposed branch, the PR can preemptively check linting, style, etc and even build the application. These activities can also be defined in a GitHub action manifest with &lt;strong&gt;pull_request&lt;/strong&gt; as triggering event.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Troubleshooting&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In general, it is painful to troubleshoot activities happening inside of runners. I often had to write a few steps for the sake of printing variables, and trigger a run to see what their value is. This requires a lot of time especially when I have to wait for available runners. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To help troubleshooting pipeline runs there is an open-source utility called &lt;a href="https://github.com/nektos/act"&gt;act&lt;/a&gt;. You can run GitHub actions locally from a Docker container on your MacBook. You can deliver environment variables and secrets via files. If you ever need to troubleshoot the runner environment, you have the option to connect to the Shell environment inside of the runner container. This tool is extremely helpful.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-closing-remarks"&gt;Closing remarks&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;GitHub action really makes the CI/CD pipeline capability available to any developers who stores their code on GitHub. GitHub expands from a code repository solution to a full CI/CD solution with a free tier sufficient for personal projects.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2021/05/secure-web-application-deployment/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Secure web application deployment&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2021/06/kubernetes-storage-explained/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Kubernetes Storage Explained – from in-tree plugin to CSI&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Git Explained 2 of 2</title><link>https://static.digihunch.com/2019/06/git-explained-2-of-2/</link><pubDate>Tue, 18 Jun 2019 17:06:00 -0400</pubDate><guid>https://static.digihunch.com/2019/06/git-explained-2-of-2/</guid><description>&lt;p class="wp-block-paragraph"&gt;This is a continuation from &lt;a href="https://static.digihunch.com/2019/06/git-explained-1-of-2/"&gt;Git Explained 1 of 2 &lt;/a&gt;where the fundamental concepts are covered. In this article we introduce some tools for customization and maintenance.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;As for Git configuration, there are two files to dictate your Git configuration. ~/.gitconfig and .git/config in project directory. Running `git config &amp;#8211;list &amp;#8211;show-origin` shows all config entries and where they are from. For example you can custom your Git hooks location. Neither of the two files are being version controlled, so the configuration is only effective in the client environment,&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;&lt;strong&gt;Server side Git hooks&lt;/strong&gt;&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Git implementation supports server side hooks (pre-receive, update, post-receive). They are bash scripts placed in .git/hooks with specific names, fired upon event occurrence. Exit code of 1 from the scripts fails the event. Since server side Git hook consumes server resources, many repository hosting vendors (e.g. &lt;a href="https://community.atlassian.com/t5/Bitbucket-questions/Does-Bitbucket-Cloud-support-git-pre-receive-hooks/qaq-p/950235"&gt;BitBucket Cloud&lt;/a&gt;) do not support it. You will need to enable it in self-hosted servers (e.g. BitBucketServer).&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;&lt;strong&gt;Client side Git hooks&lt;/strong&gt;&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Since server side hooks are not widely supported in every vendor, client-side Git hooks is good alternative places to implement functions such as code style check, commit size check, etc&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The default directory for hooks is .git/hooks/ under the project directory is not version controlled and not easy to share with the team. If the hook needs to be shared among project contributors, we can place hooks files in .githooks/ under project directory. This will make the hook files version controlled. In addition, we need to point the hooks to this directory in configuration, by running `git config core.hooksPath .githooks` from project directory.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img loading="lazy" decoding="async" width="1020" height="767" src="https://static.digihunch.com/wp-content/uploads/2019/10/git-hooks.png" alt="" class="wp-image-211"/&gt;&lt;/figure&gt;&#10;&lt;h3 class="wp-block-heading"&gt;&lt;strong&gt;Web hooks &lt;/strong&gt;&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Web hooks can be thought of as an event notification mechanism. It is a common feature provided by VCS repository hosting providers. If a certain type of event occurs to the repo, web hook will fire an RESTful API call. The HTTP Endpoint, authentication secret and event payload are pre-configured in the repo settings. Web hooks are commonly supported by Git-based repo implementation, such as &lt;a href="https://confluence.atlassian.com/bitbucket/manage-webhooks-735643732.html"&gt;BitBucket cloud&lt;/a&gt;, &lt;a href="https://developer.github.com/webhooks/"&gt;GitHub&lt;/a&gt;, &lt;a href="https://docs.gitlab.com/ee/user/project/integrations/webhooks.html"&gt;GitLab&lt;/a&gt; or &lt;a href="https://docs.aws.amazon.com/codecommit/latest/userguide/how-to-notify.html"&gt;AWS CodeCommit&lt;/a&gt;. It can also be enabled in self hosted Git repo. Web hook is a powerful tool to drive downstream event, such as Jenkins to start building the code. The major difference between server side hook and web hook is web hook is RESTful API driven, whereas server side hook is executing a script.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-pipelines"&gt;&lt;strong&gt;Pipelines&lt;/strong&gt;&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Some repo hosting vendor also provide a feature named pipeline. BitBucket has &lt;a href="https://confluence.atlassian.com/bitbucket/get-started-with-bitbucket-pipelines-792298921.html"&gt;Pipeline&lt;/a&gt; as a CI/CD tool, AWS has &lt;a href="https://aws.amazon.com/codepipeline/"&gt;AWS Code Pipeline&lt;/a&gt;, and GitLab offers &lt;a href="https://docs.gitlab.com/ee/ci/pipelines/"&gt;CI/CD pipeline&lt;/a&gt; as well. These pipelines are usually in the form of a YAML file in the repo with a special name. The YAML spell out the steps to perform along the pipeline.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;&lt;strong&gt;Squash&lt;/strong&gt; Commits&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For small projects I was in the habit of committing to main branch. I often need to squash a number of commits into one to &amp;#8220;clean up&amp;#8221;. Usually a Pull Request (e.g. in GitHub) or Merge Request (e.g. in GitLab) have such option during approval. We can squash a few commits with git command as well (suppose we want to squash the most recent 16 commits):&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git rebase -i HEAD~16&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git push origin +main&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The command will open text editor to allow you to mark what to do with each commit. You can mark all except one commit as squash. For the commit to keep, mark it as pick. Then save the text editor. Git rebase will perform the squash for you. However, since this is a rebase, do not do this if there are other collaborators working on the same branch.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;&lt;strong&gt;Cleanse a repository&lt;/strong&gt;&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Take BitBucket cloud for example, the size of a remote repo has a &lt;a href="https://confluence.atlassian.com/bitbucket/what-kind-of-limits-do-you-have-on-repository-file-size-273877699.html"&gt;non-expandable hard limit&lt;/a&gt; of 2GB, and a soft limit of 1GB. Once the soft limit is reached, a warning will be displayed on Bitbucket&amp;#8217;s landing page as well as when contributors pushes changes. Once the hard limit is reached, the entire repo will turn read-only mode.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Space consumption can be caused by accidental committing of large file. As covered in the &lt;a href="https://static.digihunch.com/2019/06/git-explained-1-of-2/"&gt;previous post&lt;/a&gt;, files are stored as blob objects in .git directory. If a file was deleted by `git rm` command, it simply means it is de-referenced from the next commit and on. After all, Git as a distributed version control system, has the ability to magically restore the deleted file when we want. The cost of that magic, is that deleted file is permanently stored in the repo, in the form of blob object, although not present in the working directory. It consumes space not only in remote repo, but also in the local repo of each contributor.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The purpose of Git repository is to store source code which are fairly small texts. However if a contributor pushed in large files, it can be tricky to cleanse a Git repo on the remote side. Here is some guidelines:&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt; Before cleansing, identify large unwanted files in current working directory, delete them with `git rm` and then commit this change in master branch. &lt;/li&gt;&#10;&lt;li&gt;Consolidate branches (e.g. delete useless remote branches with `git push origin &amp;#8211;delete branch_name`). This step itself does not free up space in remote repo but it simplifies the branches;&lt;/li&gt;&#10;&lt;li&gt;Remove large blob objects and commit objects that reference them. This step essentially is re-writing the commit history of repo. Given the risk, it is recommended to perform this step from a separate local project directory with bare repo only without working directory. &lt;a href="https://www.nicoespeon.com/en/2014/04/clean-git-repo-like-a-boss/"&gt;This article&lt;/a&gt; presents some good advices and illustrations. The command recommended is `git filter-branch -f &amp;#8211;tree-filter &amp;#8220;rm -rf \large_file.zip&amp;#8221; &amp;#8211;prune-empty &amp;#8212; &amp;#8211;all` ; and if that is too slow &lt;a href="https://rtyley.github.io/bfg-repo-cleaner/"&gt;here&lt;/a&gt; is an alternative named BFG Repo-Cleaner.&lt;/li&gt;&#10;&lt;li&gt;After this step, each commit will have a new hash id. For the repo size to reduce, either wait until the next garbage collection on the server side, or request cloud vendor to run a manual garbage collection.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2019/06/git-explained-1-of-2/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Git Explained 1 of 2&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2019/07/practical-cryptography-for-it-professional/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Cryptography Basics 1 of 2&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item></channel></rss>