Skip to content

Commit e0094a5

Browse files
committed
TIL about keeping logic out of workflows
1 parent 4063453 commit e0094a5

1 file changed

Lines changed: 105 additions & 0 deletions

File tree

  • content/til/2025/12/05/keep-github-actions-simple
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
---
2+
title: Keep Github Actions Simple
3+
date: 2025-12-05T07:43:04-07:00
4+
tags: [github, actions, ci]
5+
toc: true
6+
series: []
7+
summary: |-
8+
A reminder to keep Github Actions simple and as free of logic as possible.
9+
draft: false
10+
images: []
11+
---
12+
13+
## Shifting Build Platforms is an Opportunity
14+
I was chatting with someone about shifting GitLab pipelines to GitHub Actions.
15+
One of the options is lift-and-shift.
16+
Clearly the system has to still be deployable: without that nothing else really matters.
17+
Over time, there's a tendency to put a ton of logic into the YAML files that represent build, test, and deployment pipelines.
18+
When shifting between workflow platforms, it's a chance to clean up.
19+
20+
If you've ever tried to debug a GitHub Actions workflow YAML, you know exactly what I mean.
21+
Push a change, see it break, debug the logic, tweak the YAML file, push again, rinse and repeat.
22+
You can literally see this in the git log :-)
23+
24+
My practice is to **keep logic out of the YAML files** and instead use external scripts or tools to handle complex tasks.
25+
This makes the YAML files easier to read and maintain, and also makes it easier to reuse the same logic across multiple workflows.
26+
27+
## A Shell Script Example
28+
29+
For my experimentation Calcmark language, I have [this](https://github.com/CalcMark/go-calcmark/blob/v0.1.23/.github/workflows/release.yml#L36) GitHub Action workflow:
30+
31+
{{< highlight yaml "hl_lines=36">}}
32+
name: Release
33+
34+
on:
35+
push:
36+
tags:
37+
- 'v*.*.*'
38+
39+
permissions:
40+
contents: write
41+
42+
jobs:
43+
release:
44+
name: Build and Release
45+
runs-on: ubuntu-latest
46+
47+
steps:
48+
- name: Checkout code
49+
uses: actions/checkout@v4
50+
with:
51+
fetch-depth: 0
52+
53+
- name: Set up Go
54+
uses: actions/setup-go@v5
55+
with:
56+
go-version: '1.21'
57+
58+
- name: Install GitHub CLI
59+
run: |
60+
type -p gh >/dev/null || sudo apt-get install -y gh
61+
62+
- name: Run release script
63+
env:
64+
CI: true
65+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
66+
run: |
67+
chmod +x release.sh
68+
./release.sh
69+
{{</ highlight >}}
70+
71+
This is almost 100% boilerplate to set up a build and deploy process using Go and a couple of tools.
72+
The *real* work is done by that last inocuous looking line at the bottom: [`release.sh`](https://github.com/CalcMark/go-calcmark/blob/v0.1.23/release.sh).
73+
That's where the logic lives.
74+
75+
Now, you may not *like* shell scripts but you have to admin that they're easier to run and debug locally and test with something like a `--local` vs. `--server` flag rather than the old try-push-debug-push-try loop.
76+
77+
## A Go Example
78+
79+
If shell scripts make you wince, this website uses a Go script.
80+
Here's the relevant part of the workflow YAML:
81+
82+
```yaml
83+
- name: Render D2 diagrams
84+
run: go run blog.go
85+
- name: Build with Hugo
86+
env:
87+
HUGO_CACHEDIR: ${{ runner.temp }}/hugo_cache
88+
HUGO_ENVIRONMENT: production
89+
TZ: America/Los_Angeles
90+
run: |
91+
hugo \
92+
--gc \
93+
--minify \
94+
--baseURL "${{ steps.pages.outputs.base_url }}/"
95+
- name: Generate resume PDF
96+
run: go run blog.go
97+
- name: Upload artifact
98+
uses: actions/upload-pages-artifact@v3
99+
with:
100+
path: ./public
101+
```
102+
103+
And [read the `blog.go` script]() to understand how I use the exact same script for local development and build as I do in the GitHub Action.
104+
You'll see that it generates by resume PDF based on content in my [resume page]({{< ref "resume/index.md">}}), and generates SVG diagrams for articles using the [D2](https://d2lang.com/) language.
105+
Putting all that stuff in an Action YAML would be a total pain.

0 commit comments

Comments
 (0)