The Sample Programs Website Automatically Generates Featured Images

The Sample Programs Website Automatically Generates Featured Images Featured Image

Today, I want to take a moment to share what’s going on with the Sample Programs website repoOpens in a new tab.. 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

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 repoOpens in a new tab..

If you know me, you know that I like to use tools I’ve already made. For instance, I use an image-titlerOpens in a new tab. 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.

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:

GitHub Actions During Pull Request

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:

GitHub Action During Execution

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:

Binary Search in Every Language Source File

Which showed up like this on the official websiteOpens in a new tab.:

Binary Search Featured Image Automatically Generated

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!

Sample Programs Repo News (19 Articles)—Series Navigation

Everyone once in awhile, I like to update y’all on what’s going on in the Sample Programs repo. At this point, I’ve written quite a few updates, so I figured it might be helpful to group them as a series.

Jeremy Grifski

Jeremy grew up in a small town where he enjoyed playing soccer and video games, practicing taekwondo, and trading Pokémon cards. Once out of the nest, he pursued a Bachelors in Computer Engineering with a minor in Game Design. After college, he spent about two years writing software for a major engineering company. Then, he earned a master's in Computer Science and Engineering. Today, he pursues a PhD in Engineering Education in order to ultimately land a teaching gig. In his spare time, Jeremy enjoys spending time with his wife and kid, playing Overwatch 2, Lethal Company, and Baldur's Gate 3, reading manga, watching Penguins hockey, and traveling the world.

Recent Posts