Today, I want to take a moment to share what’s going on with the Sample Programs website repo. Recently, I pulled it out into its own repo, and now it features automatic featured image generation. Now that’s cool!
Table of Contents
- Feature Overview
- Using GitHub Actions to Generate Featured Images
- Breaking Down a GitHub Action
- Seeing a GitHub Action in Action
- Call to Action
Feature Overview
I’m writing this article today because I wanted to brag a little about a feature I recently added to the Sample Programs website repository. If you’re not familiar with the repository, it’s a place where we document all of the languages, projects, and code snippets in the Sample Programs repo.
If you know me, you know that I like to use tools I’ve already made. For instance, I use an image-titler script to generate my featured images on this site. Well, I also use it to generate the images on the Sample Programs site.
Of course, the problem is that new folks have to download and use my image-titler to be able to generate images. While this would be great marketing for me, I find that people don’t really want barriers in their way to contribution.
That’s when I had an idea. What if I put together some continuous integration system that could generate featured images for me every time a pull request is made? That way, no one would ever have to manually generate an image. They could just drop one in a folder and the edited version would appear on the official site. Well, I did it! And, we’re going to talk about how.
Using GitHub Actions to Generate Featured Images
Now, I’ve been familiar with continuous integration since I worked at GE. Back then, teams were using Jenkins, so that’s what I learned initially. Later on, I became familiar with Travis CI, and that’s what I’ve been using ever since.
That said, I’m the type of person that prefers tools that are consolidated. For instance, I used to use everything Google because all the apps interfaced properly. In general, I find it frustrating to try to get several third-party apps to mingle, so I often prefer the former. Yes, I’m aware this somewhat implies that massive corporations are good.
At any rate, I’ve been wanting to try GitHub actions for awhile because I assumed it integrated better with GitHub than a tool like Travis CI. I still love Travis CI, but I’m not exactly beholden to any set of software tools. In other words, I’m happy to switch when it makes sense, and it’s convenient.
In this case, I finally had the chance to give GitHub actions a try! And, I used it to generate featured images for me automatically.
So, here’s how things work at a high level. Every time a pull request is made, a GitHub action fires up that executes the image-titler on every image in a special folder. The results are dumped in the usual location, and git attempts to commit the changes on the current branch.
Here’s what that looks like as a GitHub action script:
# This is a basic workflow to help you get started with Actions name: CI # Controls when the action will run. Triggers the workflow on push or pull request # events but only for the master branch on: pull_request: branches: - master # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: # This workflow contains a single job called "build" build: # The type of runner that the job will run on runs-on: ubuntu-latest # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 - uses: actions/setup-python@v1 # Runs a single command using the runners shell - name: Install Image Titler run: pip install image-titler # Runs a set of commands using the runners shell - name: Generate Images run: | sources=assets/sources/ images=assets/images/ logo=icon-small.png for file in "$sources"* do image-titler --path "$file" --output "$images" --logo "$images$logo" filename=$(basename "$file") edit=$(cd "$images" && ls -t | head -n1) mv "$images$edit" "$images$filename" done - name: Commit Changes uses: EndBug/add-and-commit@v5 # You can change this to use a specific version with: # The message for the commit # Default: 'Commit from GitHub Actions' message: 'Generated featured images from sources' env: # This is necessary in order to push a commit to the repo GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Leave this line unchanged
In the next section, we’ll break down this script.
Breaking Down a GitHub Action
If you’ve never used GitHub Actions, it works a lot like Travis CI. Basically, you specify what you want to do through a configuration file, and GitHub Actions attempts to comply.
In this case, we only perform our action on pull requests to master:
on: pull_request: branches: - master
The magic happens in the following section which specifies how the job is going to get done:
jobs: build: runs-on: ubuntu-latest
In this case, we have a single action called “build” which runs on Linux. Then, all the steps defined below that dictate what will happen and in what order. In this case, we start our set of steps by specifying a couple libraries:
steps: - uses: actions/checkout@v2 - uses: actions/setup-python@v1
Basically, the first tool allows us to checkout the repo, so we can access it. Then, the second tool allows us to run Python scripts in subsequent steps.
From there, it’s a matter of laying out exactly what we want to do. For example, our first step installs the image-titler script:
- name: Install Image Titler run: pip install image-titler
Then, we use it to generate all of our images:
- name: Generate Images run: | sources=assets/sources/ images=assets/images/ logo=icon-small.png for file in "$sources"* do image-titler --path "$file" --output "$images" --logo "$images$logo" filename=$(basename "$file") edit=$(cd "$images" && ls -t | head -n1) mv "$images$edit" "$images$filename" done
This step is a bit more messy because we include raw shell scripting. For example, we set up some variables and write a loop to execute the image-titler script. Looking back on this now, I’m just happy the image-titler script works—no questions asked.
Finally, we make use of another existing GitHub Action which allows us to commit the changes back onto our current branch:
- name: Commit Changes uses: EndBug/add-and-commit@v5 with: message: 'Generated featured images from sources'
This action is a bit more complicated than it appears, but basically it just commits any new images using the commit message above—nothing otherwise.
Seeing a GitHub Action in Action
When this action is actually executed, the user will see something like this:
Do you see that commit message? That was automatically generated by this GitHub action. If you’re curious, you can even see how it went:
So, it looks like it takes about 11 seconds to install image-titler, 1 second to generate our images, and 6 seconds to commit them. That’s time well saved; let me tell you!
In this case, I was able to add this image to a folder:
Which showed up like this on the official website:
Now, that’s just cool if you ask me! If I had more time, I’d start populating the whole site with these new images, but I’ll leave that up to y’all. Feel free to help me out.
Call to Action
Speaking of getting help with images, that’s not all we need! In fact, we need loads of help with generating project, language, and code snippet documentation. I know it’s a job no one wants to do, but it’s essential for helping new folks. If you want to pay it forward to future developers, I think they’d really appreciate your effort.
If not, no worries. You can always help out The Renegade Coder more broadly by checking out this list of ways to grow the site. Not to spoil anything, but that’ll get you links to my YouTube channel, Newsletter, and Discord server.
Alternatively, here are some related articles:
Let me know if you’d like to see more articles like this! Otherwise, thanks for stopping by, and take care!
Recent Posts
One of the core features of modern programming languages is functions, but did you know Python has them too? Let's take a look!
Python has a cool feature that allows you to overload the operators. Let's talk about what that means and how you might use it!