GitHub Actions Workflow
Telar uses GitHub Actions to automatically build and deploy your site. Understanding this workflow helps you troubleshoot issues and optimize your development process.
What GitHub Actions Does
When you deploy via GitHub Pages, the build process is fully automated. No manual steps required!
User Actions (You)
Edit content directly on GitHub or push from local:
- Edit the
objectstab in your Google Sheet orobjects.csvintelar-content/spreadsheets/ - Edit markdown in
telar-content/texts/ - Add images to
telar-content/objects/ - Commit and push to main branch
Automated Actions (GitHub)
The workflow (.github/workflows/build.yml) automatically:
- Fetches Google Sheets (if enabled)
- Downloads content from your published Google Sheet
- Converts to CSV format
- Saves to
telar-content/spreadsheets/
- Converts CSVs to JSON
- Runs
scripts/csv_to_json.py - Reads CSVs from
telar-content/spreadsheets/ - Embeds markdown content from
telar-content/texts/ - Generates JSON files in
_data/for Jekyll
- Runs
- Generates IIIF Tiles
- Runs
scripts/generate_iiif.py - Processes only objects listed in
objects.csvwithout external IIIF manifests - Finds images in
telar-content/objects/by object_id - Creates tiled image pyramids in
iiif/objects/ - Generates manifest files
- Runs
- Processes Audio (conditional)
- Runs only when audio files are detected in
telar-content/objects/ - Installs
ffmpegandaudiowaveformon the runner - Extracts audio clips and generates waveform peak data
- Uses a content-hash cache key so unchanged audio is not reprocessed
- Runs only when audio files are detected in
- Builds JavaScript Bundle
- Sets up Node.js and runs
npm install - Bundles JavaScript modules with esbuild in IIFE format
- Outputs
assets/js/telar-story.jswith source map
- Sets up Node.js and runs
- Builds Jekyll Site
- Runs
bundle exec jekyll build - Compiles templates with data
- Outputs to
_site/directory
- Runs
- Encrypts Private Stories
- Runs
scripts/encrypt_protected_stories.py, unconditionally, immediately before deploy - Encrypts any story marked
private: yes(orprotected: yes) in place in_site/ - Fails the build if anything would otherwise ship as plaintext
- Runs
- Deploys to GitHub Pages
- Publishes
_site/directory - Site goes live at your GitHub Pages URL
- Publishes
Build Triggers
The workflow runs automatically when:
- Push to main branch: Any commit triggers a build
- CSV or markdown changes: Content updates deploy immediately
- Config changes:
_config.ymlmodifications rebuild site
Manual Build Trigger
Sometimes you need to rebuild without making code changes (e.g., after editing Google Sheets).
How to Manually Trigger
- Go to your repository on GitHub
- Click Actions tab
- Select Build and Deploy workflow
- Click Run workflow button (top right)
- Select branch (usually
main) - Click green Run workflow button
- Wait 2-5 minutes for completion
When to Trigger Manually
- After editing Google Sheets content
- After adding objects or story steps in Google Sheets
- To rebuild without code changes
- To force a clean build
Workflow File
The workflow is defined in .github/workflows/build.yml. The following is a simplified outline — the actual file contains caching logic and conditional steps:
name: Build and Deploy Telar Site
on:
push:
branches: [main]
workflow_dispatch:
inputs:
force_iiif:
description: 'Force IIIF tile regeneration'
type: boolean
default: true
force_audio:
description: 'Force audio regeneration'
type: boolean
default: true
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: '3.11'
- name: Set up Node.js
uses: actions/setup-node@v7
with:
node-version: '22'
- name: Build JavaScript bundle
- name: Fetch data from Google Sheets (if enabled)
- name: Convert CSV to JSON
- name: Generate Jekyll collections
- name: Generate search data
- name: Process audio objects (peaks + clips)
# Only when audio files changed, or on a manual run with force_audio;
# otherwise the audio data is restored from the cache
- name: Build Jekyll site
- name: Check for destination conflicts
- name: Generate IIIF tiles into _site
# Only when images, objects.csv or _config.yml changed, or on a manual
# run with force_iiif; otherwise the tiles are restored from the cache
- name: Encrypt protected stories
- name: Upload artifact
uses: actions/upload-pages-artifact@v5
- name: Deploy to GitHub Pages
uses: actions/deploy-pages@v5
On a manual run, the force_iiif and force_audio checkboxes decide whether IIIF tiles and audio are regenerated. Both are ticked by default. Untick one to take that part from the cache instead, and the build finishes sooner.
Build Status
Checking Build Status
- Go to Actions tab in your repository
- See list of recent workflow runs
- Green checkmark = successful build
- Red X = failed build
Viewing Build Logs
- Click on a workflow run
- Click on the job name (e.g., “build-and-deploy”)
- Expand steps to see detailed logs
- Use logs to troubleshoot errors
Common Build Errors
CSV Parsing Error
Error: Failed to parse story-1.csv
Solution:
- Check CSV file for syntax errors
- Ensure all required columns are present
- Verify no special characters breaking CSV format
Spreadsheet Refused
Error: Two columns in this spreadsheet mean the same thing: ... (fails at the “Convert CSV to JSON” step; the message names the file)
Solution:
- Two of the sheet’s headers name the same field, for example
mediumandmedium_genre, orprivadoandprotected. Keep one of each pair, delete the other, and rebuild. - If you edit your site in the Compositor, publish it again from there instead of editing the file.
Error: This spreadsheet has a column Telar uses for itself: '_metadata' (fails at the same step)
Solution:
- Rename the
_metadatacolumn and rebuild. Telar keeps that name for its own use: if a row has anything in that column, Telar reads it as its own data and leaves the row off the published site.
IIIF Generation Error
Error: Failed to process image textile-001.jpg
Solution:
- Verify image file exists in
telar-content/objects/ - Ensure object is listed in the
objectstab of your Google Sheet orobjects.csvwith blanksource_url - Check image isn’t corrupted
- Ensure image format is supported (JPG, PNG, TIFF)
Jekyll Build Error
Error: Liquid syntax error
Solution:
- Check markdown files for invalid syntax
- Verify frontmatter is properly formatted
- Look for unclosed tags or brackets
Google Sheets Fetch Error
Error: Failed to fetch Google Sheets
Solution:
- Verify
published_urlis correct in_config.yml - Ensure sheet is published to web (not just shared)
- Check sheet has proper permissions
Private Story Build Failure
Error: story/stories are marked protected but no story_key is set (fails at the “Convert CSV
to JSON” step)
Solution:
- Add
story_key: yourkeyto_config.yml, or removeprivate: yesfrom the story
Error: story/stories are marked protected, but .github/workflows/build.yml does not run
scripts/encrypt_protected_stories.py (fails at the “Convert CSV to JSON” step)
Solution:
- Your build workflow predates v1.6.0’s private-story encryption step. See Upgrading Telar: v1.6.0
Upgrade Notes to update
build.yml.
Error: the “Encrypt protected stories” step itself fails (near the end of the build, just before “Upload artifact”)
Solution:
- This means the rendered site still contains a trace of a private story’s content that should have been encrypted away. This is a bug, not a configuration issue — report it with the workflow run link.
Build Performance
Typical build times:
- Small sites (< 10 objects, 1-2 stories): 2-3 minutes
- Medium sites (10-50 objects, multiple stories): 3-5 minutes
- Large sites (50+ objects, many stories): 5-10 minutes
Optimizing Build Time
- Use external IIIF for large images (skips tile generation)
- Commit fewer images at once (split large uploads)
- Clean repository periodically (remove unused files)
Troubleshooting
Build Fails Every Time
- Check recent commits for errors
- Review build logs for specific error messages
- Test locally first (
bundle exec jekyll serve) — note that this never runs the private-story encryption step, so it won’t reproduce a private-story build failure. For that, usepython3 scripts/build_local_site.py --build-onlyinstead (see Local Development Reference) - Revert to last working commit if needed
Build Succeeds But Site Not Updating
- Clear browser cache (hard refresh: Cmd+Shift+R or Ctrl+Shift+R)
- Wait 5 minutes for CDN propagation
- Check GitHub Pages settings (Settings → Pages)
- Verify correct branch is set for Pages deployment
Google Sheets Not Updating
- Manually trigger workflow (see above)
- Verify the published URL in
_config.yml - Check the sheet is published to web
- Review fetch logs in Actions tab