Generating this site with Netlify and GitHub Actions
With the whole move to Mastodon, I’ve been thinking a lot about owning my content again and what will happen with all the interesting things I’ve written on Twitter. That’s a topic that is worth its own post, but it got me thinking about focusing more on this blog again.
That coincided with a technical curiosity. As I talk in my meta post about the site redesign this site is built using Swift’s Publish package and served by Netlify. This gives me a blazing fast static website for free. But until now I’ve been generating the website locally from my computer. Back in the day Netlify didn’t really support running Swift in their servers easily, so I didn’t spend time trying to solve that. When I added automatic image generation to the posts for social sharing I used SwiftUI, which means I need to run on macOS anyway.
But now time has passed, and I want to have the flexibility to publish in my blog from somewhere that is not my computer. But let’s be honest, it’s mostly a technical curiosity. I’m sure I will still write most of my content from my computer, but that won’t change unless I remove the friction and make it a possibility.
The first order of business was to update the code to Swift 5.7. One of the main reasons I moved out from other site generators in other languages is because every time I had to update anything, it was a mess of dependencies and language issues in languages I didn’t care about.
Because this is Swift, I’m able to do any update without even thinking about it. But the reality is that this time it took me by surprise.
The aforementioned image generation that runs in SwiftUI has a requirement, it must run in the main thread. Obviously because is doing UI stuff. But Publish updated some internals to make use of Swift Concurrency and that caused problems.
The short story is that Publish has only adopted concurrency half way. It uses it internally to speed up some things, but it still left the entry point as a normal synchronous function. I imagine that was the best solution when that Publish version was released, but nowadays it is a terrible idea. In order to make the runtime wait Publish uses an internal semaphore that blocks the main thread, which as you can imagine it doesn’t play nicely with SwiftUI.
Since the library doesn’t get much attention, I just forked it and fix it myself. I’m still indecisive on what I will do with this. I don’t want to maintain forks, but if the original library doesn’t get more maintainers, I’m afraid of its future.
But with that out of the way, the generator run perfectly in Swift 5.7. I also updated some of my Publish plugins (Item Poster and Reading time) to be up to date with the rest of dependencies.
Running Swift on Linux in Netlify
The next step was to make sure my code could run on Linux, since is what all servers are based on. Thankfully Netlify makes that very easy.
First, Swift is now fully supported as a build environment. By default it uses an older version of Swift but, as the docs explains, you just need to set an environment variable with he version you want and it will be automatically installed on the server image. Easy peasy.
But then we had to update the code to work somewhere else that was not my machine. And one thing I detest of some development workflows is when you can’t try your changes locally. Years ago, I worked a bit on AWS Lambda and the setup that they gave me was so awful that I refused to work more on that project. So of course for this I quickly investigated how to test things locally without waiting for Netlify servers.
And of course the answer was Docker. It still baffles me that the solution to self-created problems by the industry is packaging entire computers. Is a good idea, don’t get me wrong, but it doesn’t solve the root of our problems. Anyway, Netlify has all the instructions you need to run their image locally. And it was very easy to do, even for myself.
With that in place, I just had to run the generator and start ifdefing out everything that required macOS and making some hard-coded paths (yes, I’m lazy sometimes when it’s not a critical project).
Everything seemed to work except, of course, the SASS dependency was not installed in the same way. On macOS I use brew but on Linux I opted to use npm since it was already pre-installed. Took a few tries to get everything setup correctly, but it wasn’t too bad. That said, I despise that my site generation requires non-Swift dependencies. Is such a shame that to do anything on the web you need so many dependencies. In my other site, Pulubi Worlds, I opted to use tailwind instead, but I’m pretty sure it will be the same mess. Well, a fight for another day.
And with that I had my site building on Netlify on every push. Nice!
Using GitHub actions for macOS execution
But of course, those pesky posters wouldn’t generate on Linux. I need to run that on macOS remember?
Until then, the poster generation was part of the site generation, it was just another Publish step. But now I had to look for another solution.
Thankfully GitHub gives some macOS time for free, not much mind you, with their GitHub Actions. So I opted to make a separate command on my CLI to run only the poster creation. I configured the action to only run if there were changes on the Content folder to avoid wasting those precious macOS minutes.
Conclusion
So now I have my site, including social poster generation, running on the cloud, still for free. This means I can write in my blog from anywhere which hopefully inspires me to write more.
I plan to do a couple more things using GitHub actions to reduce the friction. The dream would be to have a CMS that runs on top of GitHub, a CMS for static sites. But for now I can live with some more niceties.
Another thing I’m interesting in exploring is the whole micro.blog, indieweb and federation idea. I know static sites don’t play super nice with some of those things, but is interesting to think about nonetheless.