🚀 Release & CI/CD Pipeline
This document describes the design, execution flow, files, and automation logic of the LibreFolio Release and CI/CD Pipeline, configured in .github/workflows/release.yml.
The pipeline is built using GitHub Actions and automates code verification, frontend compilation, documentation builds (including dynamic browser screenshot capture), multi-platform Docker container packaging, and public deployment to GitHub Pages.
🛠️ Triggers & Workflow Events
The workflow is configured with three distinct triggers:
release(published): Runs automatically when a new release tag (e.g.v0.10.0) is published on GitHub. This is the official production release path.push(dev branch): Runs automatically on every push to thedevbranch. Used for continuous integration and integration testing.workflow_dispatch(manual): Allows running the pipeline manually from the GitHub Actions tab. It includes aforce_galleryinput to manually trigger Playwright screenshot updates.
🔄 Execution Flow Diagram
The following diagram illustrates the complete execution path, branch conditions, caching mechanisms, and release publishing steps:
graph TD
A([GitHub Actions Trigger]) --> B{Event Type?}
B -->|push to dev| C[Runner Setup & Checkout]
B -->|workflow_dispatch| C
B -->|release published| C
C --> D[Install Python & Node.js Dependencies]
D --> E[Build SvelteKit Frontend]
subgraph Docs Validation
E --> F1[translate-diff]
E --> F2[translate-validate]
E --> F3[check-links]
end
F1 & F2 & F3 --> G[Extract Minor Version for Cache]
G --> H[Cache Restore Step]
H --> I{Cache Hit or force_gallery=true?}
I -->|No / Forced| J[Generate Screenshots via Playwright]
I -->|Yes| K[Skip Screenshot Generation]
J --> L[Save Screenshots to Cache]
K & L --> M[Build MkDocs Documentation]
M --> N[Generate requirements.txt]
N --> O[Extract Docker Metadata]
O --> P{Tagging Logic}
P -->|Branch dev| P1[Tag 'nightly']
P -->|Branch main| P2[Tag 'latest']
P -->|Release Tag| P3[Tag SemVer version]
P1 & P2 & P3 --> Q[Build & Push Docker Image to GHCR]
Q --> R{Deploy Site to gh-pages?}
R -->|main or release event| S[Deploy to gh-pages branch]
R -->|dev branch push| T[Skip Deploy]
S & T --> U{Is Release Event?}
U -->|Yes| V[Update GitHub Release Notes with Docker Pull Info]
U -->|No| W[Skip Notes Update]
V & W --> X[Archive PNG Screenshots as Artifact]
X --> Y([End Workflow])
📂 Core Commands & Implementation Details
1. Verification and Setup
The pipeline prepares the environment by setting up Python 3.13 and Node.js 24, installing dependencies using pipenv install --dev, and compiling the SvelteKit frontend:
The documentation files undergo translation consistency checks and cross-reference link verification to ensure no broken relative URLs are published:
pipenv run ./dev.py mkdocs translate-diff --issues-only
pipenv run ./dev.py mkdocs translate-validate --hide-localized
pipenv run ./dev.py mkdocs check-links
2. Gallery Screenshot Caching & Generation
Playwright screenshot generation can take a significant amount of time (15–20+ minutes). To optimize this, the pipeline caches images using the minor version (e.g. v0.10) or the branch name (dev) as part of the key.
- Extraction: The minor version is computed from the tag or ref:
- Caching: The cached screenshots are restored or saved at:
- Conditional Generation: The screenshot step runs only if there is a cache miss or if
force_gallerywas selected manually:
3. Docker Compilation and Tagging
An image is built from the local Dockerfile containing the FastAPI backend and built SvelteKit client. The image tags are assigned conditionally using docker/metadata-action to protect production builds:
- Tag
latest: Enabled only when running on themainbranch. - Tag
nightly: Enabled only when running on thedevbranch. - Tag SemVer (e.g.
v0.10.2): Generated automatically from release tags.
These images are pushed to the GitHub Container Registry (ghcr.io/librefolio/librefolio).
4. Conditional Documentation Deployment
The built static site is pushed to the gh-pages branch using the mkdocs gh-deploy wrapper in dev.py.
To prevent development changes from polluting the public website, this step runs only on main branch updates or release events:
if: github.ref_name == 'main' || github.event_name == 'release'
run: pipenv run ./dev.py mkdocs deploy
5. Post-Release Automation
If triggered by a release, the pipeline edits the GitHub release notes to append the exact Docker pull instructions:
Finally, generated PNG screenshots (excluding markdown sources) are archived as a workflow run artifact for easy retrieval: