Auto Create Jigsaw Tags via GitHub Actions

June 9, 2023

Jigsaw is an awesome static site generator that is built on PHP and Laravel components. In fact as of last week, it now powers this blog.

One thing that I have noticed while creating posts is that if you add a new tag (morphed from the default categories jigsaw's template provies) and don't add the corresponding tag file in the source/_tags directory, you will get a 404 error when trying to view the tag page.

I wanted to automate this process so that when I create a new post, if I add a new tag, it will automatically create the tag file for me. Given that I am using GitHub Actions to build and deploy the site, I figured that would be the best place to do this.

Github Action

The first thing I did was create a new file in my .github/workflows directory called add-missing-tags.yml. This file will be used to create any missing tag files if they don't already exist.

name: Add Missing Tags

      - 'source/_posts/**.md'

    runs-on: ubuntu-latest

      - name: Checkout Repository
        uses: actions/checkout@v2

      - name: Extract Tags
        run: |
          #!/usr/bin/env bash

          # Find all markdown files in ./source/_posts directory
          markdown_files=$(find ./source/_posts -name "*.md")

          # Loop through each markdown file
          for file in $markdown_files; do
            # Extract tags from the header using awk and remove square brackets
            tags=$(awk -F 'tags: *\\[|\\]' '/tags:/ {gsub(/ /, "", $2); print $2}' "$file")

            # Convert comma-separated tags to an array and trim whitespace from each tag
            IFS=',' read -ra tags_array <<< "$tags"
            for tag in "${tags_array[@]}"; do
              trimmed_tags+=("$(echo -e "${tag}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')")

            # Sort and remove duplicates from the tags
            sorted_tags=$(printf '%s\n' "${trimmed_tags[@]}" | sort -u)

            # Print the sorted tags
            echo "Tags in $file: $sorted_tags"

            # Loop through each tag
            for tag in $sorted_tags; do
              # Check if a Markdown file exists in ./source/_tags with the tag name
              if [[ ! -f "./source/_tags/$" ]]; then
                echo "Creating file ./source/_tags/$"
                echo "---" > "./source/_tags/$"
                echo "extends: _layouts.tag" >> "./source/_tags/$"
                echo "title: $tag" >> "./source/_tags/$"
                echo "---" >> "./source/_tags/$"

      - name: Commit changes
        uses: stefanzweifel/git-auto-commit-action@v4
          commit_message: "[bot] adding missing tags"

The first part of the workflow sets up the triggers for the action and limits it to only run when a file in the source/_posts directory is pushed.

name: Add Missing Tags

      - 'source/_posts/**.md'

The next part focuses on finding all the existing tags on posts and creating the corresponding tag files if they don't already exist.

Finally, if any tag files were created, it will commit the changes to the repository automatically.

Preview of Github Commit

Note: I have changed the default categories to tags in my config.php file, so if you are using the default categories you will need to change the script to reflect that.