I’ve been using DigitalOcean for quite some time now and had recently setup their App Platform to run my website. Their platform is great in that I’m able to build a docker container running Openresty and it handles all of my needs. The platform does a great job of catching docker build failures and stops attempting a deployment when this happens. A few weeks ago, I had a concerning thought in that they don’t catch problems with my Openresty configuration until it’s too late. The moment their platform executes openresty inside the container, everything pukes and my site goes offline.
This isn’t terrible because I don’t make many changes to the server configuration. If I do, I could just run the docker locally and make sure nothing is wrong. As I have continued into the DevOps world more, I realized how outdated and manual this process was. I also realized that not every change I make to the server configuration is checked manually.
The fear is real
Fast forward to today and you’ll see that I broke my site a few times tinkering. I am wanting to do some additional tricks and configuration changes in Openresty so I started making them. Just as luck would have it, the site went down and I didn’t notice right away.
Github Actions to Save The Day
I figured the easiest thing would be to replicate what I was doing manually. The easiest thing would be to create a Github action that would check my configuration files using openresty -t
just like I did that one time I actually checked my configuration before push a commit. I figured I’d take some simple steps:
- Run the action on any commit
- Load the files into a container
- Run
openresty -t
- Wait for Digitalocean to build and load the changes
Problem #1 – Where do I even go next?
What I wanted to do was easy as I was doing it in Dockerfile
in the repo already. My initial research and knowledge had me going down the route of building the container, deploying the container somewhere, and then attempting to run the container. This seemed like way too much overhead so I found the combination of run-on
and container
jobs:
build:
runs-on: ubuntu-latest
container:
image: openresty/openresty:1.19.9.1-4-alpine-fat
The runs-on
just tells Github what underlying platform you’d like to run on for the host OS. The container
allows you to also run on any docker container available. This does even support private repos and a host of other configuration parameters if needed.
Problem #2 – How do I mount the repos files into the container?
My first thought was to simply use the volumes
parameter and tell it to mount GITHUB_WORKSPACE
to the container and off we go! This was a terrible thought as you can tell by the error that I got running the action.
jobs:
build:
runs-on: ubuntu-latest
container:
image: openresty/openresty:1.19.9.1-4-alpine-fat
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it.
- name: Checkout Branch
uses: actions/checkout@v3
- name: Copy Server Config
id: copy-server-config
run: cp conf/nginx.conf /usr/local/openresty/nginx/conf/nginx.conf
- name: Copy Default Config
id: copy-default-config
run: cp conf/default.conf /etc/nginx/conf.d/
- name: Copy Site Configs
id: copy-site-configs
run: cp conf/site-*.conf /etc/nginx/conf.d/
- name: Create Lua Directory
id: create-lua-dir
run: mkdir /etc/nginx/lua
- name: Copy Access Lua File
id: copy-lua-access
run: cp lua/access.lua /etc/nginx/lua/access.lua
- name: Test OpenResty Configuration
id: test-openresty
run: openresty -t
Problem #3 – The Action Didn’t Stop The Digitalocean Build
Digitalocean only watches a branch for pushes and then starts a build on any push. I was hoping that my Action would fail the push and therefore stop the Digitalocean build. This was not the case. This was an easy fix, I just decided to make sure all of my commits were done to a dev
branch and configured the Action to trigger on that. I updated my Action a little more
name: Openresty Configuration Check
on:
push:
branches: [ "dev" ]
pull_request:
branches: [ "dev" ]
jobs:
build:
runs-on: ubuntu-latest
container:
image: openresty/openresty:1.19.9.1-4-alpine-fat
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it.
- name: Checkout Branch
uses: actions/checkout@v3
- name: Copy Server Config
id: copy-server-config
run: cp conf/nginx.conf /usr/local/openresty/nginx/conf/nginx.conf
- name: Copy Default Config
id: copy-default-config
run: cp conf/default.conf /etc/nginx/conf.d/
- name: Copy Site Configs
id: copy-site-configs
run: cp conf/site-*.conf /etc/nginx/conf.d/
- name: Create Lua Directory
id: create-lua-dir
run: mkdir /etc/nginx/lua
- name: Copy Access Lua File
id: copy-lua-access
run: cp lua/access.lua /etc/nginx/lua/access.lua
- name: Test OpenResty Configuration
id: test-openresty
run: openresty -t
Problem #4 – I’m Lazy and Don’t Want to Constantly Merge My Changes
I found an Action in the Github Marketplace that would automatically merge my changes from one branch to another. Now I have my final Action.
name: Openresty Configuration Check
on:
push:
branches: [ "dev" ]
pull_request:
branches: [ "dev" ]
jobs:
build:
runs-on: ubuntu-latest
container:
image: openresty/openresty:1.19.9.1-4-alpine-fat
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it.
- name: Checkout Branch
uses: actions/checkout@v3
- name: Copy Server Config
id: copy-server-config
run: cp conf/nginx.conf /usr/local/openresty/nginx/conf/nginx.conf
- name: Copy Default Config
id: copy-default-config
run: cp conf/default.conf /etc/nginx/conf.d/
- name: Copy Site Configs
id: copy-site-configs
run: cp conf/site-*.conf /etc/nginx/conf.d/
- name: Create Lua Directory
id: create-lua-dir
run: mkdir /etc/nginx/lua
- name: Copy Access Lua File
id: copy-lua-access
run: cp lua/access.lua /etc/nginx/lua/access.lua
- name: Test OpenResty Configuration
id: test-openresty
run: openresty -t
- name: Merge dev -> main
uses: devmasx/merge-branch@master
with:
type: now
target_branch: main
github_token: ${{ github.token }}
Conclusion
Now, I can save me from myself! Anytime that I need to make changes to my configuration, I commit the changes to dev. From there, my Action runs and makes sure that the Openresty configuration is ok. If that runs fine, then I automatically merge my changes into main
and that triggers the Digitalocean App build.