Post

Icon Release Web Workflow

Automated Jekyll documentation generation from feature JSON files with video integration and GitHub Pages deployment

Release Web Workflow

Release Web Workflow

The Release Web workflow automates the generation of Jekyll documentation posts from feature JSON files and deploys the documentation site to GitHub Pages.

Overview

This workflow replaces the KSP-based post generation with a streamlined bash script that:

  • Reads feature definitions from JSON files
  • Generates Jekyll markdown posts with proper front matter
  • Includes video player integration for feature demos
  • Deploys the complete site to GitHub Pages

Workflow Triggers

The workflow runs on:

1
2
3
4
5
6
7
8
on:
  workflow_dispatch:  # Manual trigger
  push:
    branches:
      - main
    paths:
      - 'docs/**'     # Any changes to docs
      - 'content/**'  # Any changes to content

Architecture

graph TD
    A[Trigger: Manual or Push] --> B[Generate Feature Posts Job]
    B --> C[Scan content/feature/*.json]
    C --> D[Extract JSON data]
    D --> E[Generate Jekyll posts]
    E --> F[Deploy Jekyll Pages Job]
    F --> G[Regenerate posts]
    G --> H[Setup Ruby & Node]
    H --> I[Build frontend assets]
    I --> J[Build Jekyll site]
    J --> K[Deploy to GitHub Pages]

Job 1: Generate Feature Posts

Input Sources

The workflow processes JSON files from content/feature/ directory:

1
2
3
4
5
6
7
8
{
  "name": "KrillApp.RuleEngine.RuleEngineDo.OutgoingWebHook",
  "title": "Outgoing WebHook Action",
  "description": "Detailed description...",
  "shortDescription": "Send HTTP requests to external URLs...",
  "category": "Krill Server",
  "subcategory": "Rule Engine"
}

File Naming Convention

Generated files follow this pattern:

1
{DATE}-generated-{kebab-case-name}.md

Example transformations:

JSON FilenameGenerated Markdown
KrillApp.RuleEngine.json2025-11-17-generated-krillapp-ruleengine.md
KrillApp.RuleEngine.RuleEngineDo.OutgoingWebHook.json2025-11-17-generated-krillapp-ruleengine-ruleenginedo-outgoingwebhook.md
KrillApp.DataPoint.Trigger.Deadband.json2025-11-17-generated-krillapp-datapoint-trigger-deadband.md

Front Matter Generation

Each post includes Jekyll front matter:

1
2
3
4
5
6
7
8
9
10
---
title: Outgoing WebHook Action
author: bsautner
date: 2025-11-17 15:00:00 -0500
description: Send HTTP requests to external URLs for notifications and integrations.
product: Krill App
categories: [Krill Server, Rule Engine]
render_with_liquid: false
icon: krillapp_ruleengine_ruleenginedo_outgoingwebhook
---

Field Mapping

JSON FieldFront Matter FieldTransformation
title or nametitleDirect copy, fallback to name
shortDescription or descriptiondescriptionPrefers shortDescription
categorycategories[0]Default: “Krill App”
subcategorycategories[1]Optional
nameiconLowercase, dots → underscores
Current timestampdateYYYY-MM-DD HH:MM:SS TZ

Video URL Inference

Video URLs are constructed based on the Feature Generate Video workflow pattern:

1
2
3
FEATURE_NAME_LOWER=$(basename "$json_file" .json | tr '[:upper:]' '[:lower:]')
VIDEO_SHORT_URL="https://cms.krill.systems/features/latest/001-${FEATURE_NAME_LOWER}-short.mp4"
VIDEO_LONG_URL="https://cms.krill.systems/features/latest/002-${FEATURE_NAME_LOWER}-long.mp4"

Example:

  • JSON: KrillApp.RuleEngine.json
  • Short video: https://cms.krill.systems/features/latest/001-krillapp.ruleengine-short.mp4
  • Long video: https://cms.krill.systems/features/latest/002-krillapp.ruleengine-long.mp4

Post Content Template

Each generated post includes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# {Title}

{Description}

## Demo Video

### Short Demo

<video width="100%" controls>
  <source src="{SHORT_VIDEO_URL}" type="video/mp4">
  Your browser does not support the video tag.
</video>

### Full Demo

<video width="100%" controls>
  <source src="{LONG_VIDEO_URL}" type="video/mp4">
  Your browser does not support the video tag.
</video>

---

*This post was automatically generated from the feature definition at `{filename}.json`*

Job 2: Deploy Jekyll Pages

This job handles the complete Jekyll site build and deployment.

Steps Overview

  1. Checkout & Regenerate Posts
    • Fresh checkout of main branch
    • Regenerate all posts (not persisted in git)
  2. Setup Ruby Environment
    • Ruby 3.2
    • Bundle cache enabled
  3. Setup Node.js Environment
    • Node 20
    • Install patch-package and dependencies
  4. Build Frontend Assets
    • Run npm build for CSS/JS assets
  5. Setup GitHub Pages
    • Configure Pages deployment
  6. Build Jekyll Site
    • Production environment
    • Output to _site directory
  7. Deploy to GitHub Pages
    • Upload artifacts
    • Deploy to Pages

Why Regenerate Posts?

Generated posts are not committed to source control because:

Single Source of Truth: JSON files are the source
Always Current: Posts always reflect latest JSON
No Git Bloat: Reduces repository size
Clean History: Only tracks source changes
Automated: No manual sync needed

Integration with Feature Generate Video

The Release Web workflow works in tandem with Feature Generate Video:

sequenceDiagram
    participant Dev as Developer
    participant JSON as content/feature/*.json
    participant FGV as Feature Generate Video
    participant S3 as S3 (cms.krill.systems)
    participant RW as Release Web
    participant GH as GitHub Pages
    
    Dev->>JSON: Update feature JSON
    Dev->>FGV: Trigger video generation
    FGV->>FGV: Generate short/long videos
    FGV->>S3: Upload videos
    Dev->>JSON: Commit JSON changes
    JSON->>RW: Auto-trigger (push to main)
    RW->>RW: Generate posts with video URLs
    RW->>GH: Deploy documentation

Video URL Pattern

Videos must be uploaded to S3 with this naming convention:

1
2
3
s3://cms.krill.systems/features/latest/
  ├── 001-{featurename}-short.mp4
  └── 002-{featurename}-long.mp4

Where {featurename} is the JSON filename (without .json) in lowercase.

Environment Variables

1
2
3
env:
  S3_BUCKET: cms.krill.systems
  S3_PREFIX: features/latest

These control where videos are expected to be hosted.

JSON Processing

The workflow uses jq for JSON parsing with fallback to grep/sed:

1
2
3
4
5
6
if command -v jq &> /dev/null; then
  TITLE=$(jq -r '.title // .name' "$json_file")
else
  # Fallback to grep/sed
  TITLE=$(grep -o '"title"[[:space:]]*:[[:space:]]*"[^"]*"' "$json_file" | sed 's/.*: *"\(.*\)"/\1/')
fi

Usage

Automatic Deployment

Push changes to docs/ or content/ directories:

1
2
3
git add content/feature/NewFeature.json
git commit -m "Add new feature definition"
git push origin main

The workflow will automatically:

  1. Detect the change
  2. Generate Jekyll posts
  3. Build the site
  4. Deploy to GitHub Pages

Manual Deployment

  1. Go to Actions tab
  2. Select Release Web workflow
  3. Click Run workflow
  4. Select branch (main)
  5. Click Run workflow button

Output

Console Output Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
🔍 Scanning content/feature directory for JSON files...
Found 36 JSON files to process

📝 Generating: docs/_posts/2025-11-17-generated-krillapp-ruleengine.md
   Title: Rule Engine
   Categories: [Krill Server, Rule Engine]
✅ Generated: docs/_posts/2025-11-17-generated-krillapp-ruleengine.md

📝 Generating: docs/_posts/2025-11-17-generated-krillapp-datapoint.md
   Title: Data Points
   Categories: [Krill Server, Data Points]
✅ Generated: docs/_posts/2025-11-17-generated-krillapp-datapoint.md

🎉 Generated 36 Jekyll posts from 36 JSON files

📋 Generated files:
docs/_posts/2025-11-17-generated-krillapp-client-about.md
docs/_posts/2025-11-17-generated-krillapp-datapoint.md
...

Generated Post Management

Not in Git

Generated posts are excluded from source control:

# .gitignore (recommended)
docs/_posts/*generated-*.md

Regenerated on Deploy

Every deployment:

  1. Starts fresh (no generated posts)
  2. Scans all JSON files
  3. Generates all posts
  4. Builds and deploys

This ensures posts are always in sync with JSON sources.

Troubleshooting

Posts Not Showing Up

Check:

  1. JSON file exists in content/feature/
  2. JSON has required fields: name, title or both
  3. JSON is valid (use jq . file.json)
  4. Workflow completed successfully

Videos Not Loading

Check:

  1. Videos uploaded to correct S3 path
  2. Filename matches pattern: 00N-{lowercase-name}.mp4
  3. S3 bucket is publicly accessible
  4. CORS configured on S3 bucket

Build Failures

Common issues:

  1. Invalid JSON syntax
  2. Missing Ruby/Node dependencies
  3. Jekyll build errors
  4. Pages deployment permissions

Check the Actions logs for specific error messages.

Comparison to Old KSP Workflow

Before (KSP-based)

  • ❌ Required Kotlin compilation
  • ❌ Complex KSP processor
  • ❌ Slower build times
  • ❌ Posts committed to git

After (Bash-based)

  • ✅ Pure bash script
  • ✅ Simple JSON parsing
  • ✅ Fast execution
  • ✅ Posts generated on-demand
  • ✅ Cleaner git history

Future Enhancements

Potential improvements:

  • Add validation for required JSON fields
  • Generate table of contents automatically
  • Include feature status badges
  • Add search optimization metadata
  • Generate sitemaps automatically
  • Support for custom video players
  • Add analytics tracking
  • Feature Generate Video: Creates the videos referenced in posts
  • Release The Kraken: Full platform release (includes docs)
  • Release Version: Version management (referenced in docs)

Permissions Required

1
2
3
4
permissions:
  contents: read    # Read repository
  pages: write      # Deploy to Pages
  id-token: write   # OIDC for Pages

Summary

The Release Web workflow provides:

Automated Documentation: Posts generated from JSON
Video Integration: Links to S3-hosted demos
Auto Deployment: Triggered on content changes
No Git Bloat: Generated content not committed
Fast Builds: Simple bash processing
Always Current: Posts match JSON sources

This creates a seamless documentation pipeline from feature definitions to published site.

This post is licensed under CC BY 4.0 by the author.