β¬ οΈ Back to Deployment Index
CI/CD & Documentation Pipeline
Overview
Smart Supply Pro uses GitHub Actions for fully automated continuous integration and continuous deployment. Three coordinated workflows ensure code is tested, documented, and deployed:
- 1οΈβ£ Backend CI β Build & Test
(
1-ci-test.yml) β Compile, test, build Docker image, scan for CVEs - 2οΈβ£ Documentation Pipeline
(
docs-pipeline.yml+2-deploy-ghpages.yml) β Generate API/architecture docs, publish to GitHub Pages - 3οΈβ£ Deployment to Fly.io
(
3-deploy-fly.yml) β Deploy to production (automatic after CI passes)
This document explains the workflow coordination, key steps, and how documentation is generated and published.
Workflow Architecture
(1-ci-test.yml)"] B -->|Stage 1: Compile| C["Maven: compile + test"] C -->|Stage 2: Package| D["Generate JaCoCo coverage
Build Docker image
Push to registry"] D -->|Stage 3: Security| E["Trivy scan
Block on HIGH/CRITICAL"] E -->|β Pass| F["Artifacts ready"] E -->|β Fail| G["π« Deployment blocked"] F -->|Trigger| H["docs-pipeline.yml
Build documentation"] F -->|Trigger| I["3-deploy-fly.yml
Deploy to production"] H -->|Generate| J["OpenAPI docs
Architecture HTML
JaCoCo coverage"] J -->|Output| K["docs-site artifact"] K -->|Trigger| L["2-deploy-ghpages.yml
Publish to gh-pages"] L -->|Git push| M["π GitHub Pages
(Live docs)"] I -->|Validate| N["Health check
Smoke tests"] N -->|β Healthy| O["π Live App
(https://inventoryservice.fly.dev)"] style B fill:#fff3e0 style C fill:#f3e5f5 style D fill:#f3e5f5 style E fill:#fce4ec style H fill:#e3f2fd style J fill:#e1f5fe style M fill:#c8e6c9 style O fill:#a5d6a7
Workflow 1οΈβ£: CI
Build & Test (1-ci-test.yml)
Trigger
- Push to
mainordevelopbranch - Changes in: backend source,
pom.xml, Dockerfile, CI workflow itself - Manual trigger:
workflow_dispatch
Pipeline Steps
| Step | Action | Input | Output | Purpose |
|---|---|---|---|---|
| 1 | Checkout code | Git commit | Source tree | Prepare build environment |
| 2 | Resolve backend path | pom.xml location |
$BACKEND_DIR env var |
Support repo-root or subdir layout |
| 3 | Set up JDK 17 | Temurin distribution | Java compiler | Compile with Java 17 |
| 4 | Cache Maven deps | .m2 directory |
Warm cache | Speed up dependency resolution |
| 5 | Build & Test | mvn clean verify |
Tests, JaCoCo report | Compile, unit tests, integration tests |
| 6 | Display Spring versions | mvn dependency:list |
Version report | Verify Spring Core & Security versions |
| 7 | Generate JaCoCo | target/site/jacoco/ |
HTML report | Code coverage metrics |
| 8 | Upload JaCoCo artifact | HTML files | jacoco-html-{SHA} artifact |
Make available for docs pipeline |
| 9 | Docker login | Docker Hub credentials | Auth token | Prepare for image push |
| 10 | Build Docker image | Dockerfile, JAR, deps | inventory-service:SHA +
:latest |
Package for deployment |
| 11 | Inspect image | Run container, check contents | Verification output | Ensure prod image quality |
| 12 | Push Docker image | Auth + image | Registry entry | Store immutable artifact |
| 13 | Trivy scan | Docker image | CVE report | Block deployment if HIGH/CRITICAL |
| 14 | Job summary | Status, image tags | GitHub summary | Report results to developer |
Example: Build & Test Step
mvn -U clean verify \
-Dspring.profiles.active=test \
-Dtestcontainers.enabled=falseFlags: - -U β Update snapshots (fresh
dependencies) - clean verify β Full lifecycle
(compile β test β package β verify) -
-Dspring.profiles.active=test β Use H2 database,
test config - -Dtestcontainers.enabled=false β Skip
Docker-based integration tests in CI
Security Gate: Trivy Vulnerability Scan
After image is built and pushed:
trivy image ckbuzin/inventory-service:${IMAGE_TAG_SHA} \
--severity CRITICAL,HIGH \
--exit-code 1Behavior: - Scans image for known CVEs in OS
packages and libraries - Reports only CRITICAL and
HIGH severity - Blocks deployment
if vulnerabilities found (exit-code: 1) -
Allows deployment if no HIGH/CRITICAL
(LOW/MEDIUM/unknown are logged)
Example failure:
CRITICAL 3 vulnerabilities found in base image
- openssl 3.0.0 β Use 3.0.5 or later
- glibc 2.31 β Use 2.34 or later
Exit code: 1 β Deployment blocked
Resolution: 1. Update base image in
Dockerfile (e.g., newer eclipse-temurin:17-jre) 2.
Or update vulnerable library in pom.xml 3. Push new
commit β Re-run CI β Retry scan
Artifacts Produced
| Artifact | Location | Size | Purpose | Consumed By |
|---|---|---|---|---|
jacoco-html-{SHA} |
GitHub Actions artifact store | ~5 MB | Code coverage report | docs-pipeline.yml |
| Docker image | Docker Hub (ckbuzin/inventory-service) |
~400 MB | Packaged app | 3-deploy-fly.yml, docker pull |
| Test results | CI logs | (inline) | JUnit report | GitHub, developer review |
Workflow
2οΈβ£: Documentation Pipeline (docs-pipeline.yml +
2-deploy-ghpages.yml)
Trigger
- Automatic: After
1-ci-test.ymlsucceeds (viaworkflow_run) - Manual: Direct push to
mainif docs/ or scripts/ changed
Key Insight: Dual-Trigger Design
Why two triggers?
- After CI (workflow_run): Rebuild docs
whenever code changes
- Ensures OpenAPI, coverage, architecture stay fresh
- Consumes JaCoCo artifact from CI
- Direct push (direct trigger): Rapid
docs-only updates
- Allows emergency doc fixes without rebuilding code
- Skips JaCoCo (optional, not always available)
Step 1:
Build Documentation (docs-pipeline.yml)
Tools Used
| Tool | Purpose | Input | Output |
|---|---|---|---|
| Redocly CLI | OpenAPI β interactive HTML docs | docs/api/openapi/openapi.yaml |
ReDoc HTML site |
| Pandoc | Markdown β HTML conversion | .md architecture files |
Static HTML pages |
| Lua filter | Mermaid diagram rendering in HTML | mermaid code blocks |
Rendered diagrams |
| Bash scripts | Orchestrate build + artifact assembly | Source markdown + images | docs-site/ directory |
Documentation Structure
docs-site/
βββ index.html # Portal entry point
βββ api/
β βββ openapi.html # Swagger/ReDoc interactive
β βββ index.html # API overview
βββ architecture/
β βββ overview.html
β βββ layers/
β βββ resources/
β βββ deployment/
β βββ ... # All architecture guides as HTML
βββ backend/
β βββ coverage/ # JaCoCo HTML report (from CI)
β β βββ index.html
β β βββ inventory-service/
β β βββ ... (line-by-line coverage)
β βββ api/
βββ ...
Build Scripts
scripts/build-openapi-docs.sh
#!/bin/bash
PROJECT_DIR=$1
# Install Redocly CLI (or use pre-installed)
npm install -g @redocly/cli
# Convert OpenAPI YAML β ReDoc HTML
redocly build-docs \
$PROJECT_DIR/docs/api/openapi/openapi.yaml \
-o $PROJECT_DIR/target/docs/api/openapi.htmlscripts/build-architecture-docs.sh
#!/bin/bash
PROJECT_DIR=$1
# Install Pandoc
apt-get install pandoc
# Convert each markdown file to HTML with Lua filter for mermaid
for file in $PROJECT_DIR/docs/architecture/**/*.md; do
output_file="${file%.md}.html"
pandoc "$file" \
--filter /path/to/mermaid-filter.lua \
--template template.html \
-o "$output_file"
doneLua Filter for Mermaid
(mermaid-filter.lua)
function CodeBlock(el)
if el.classes:includes("mermaid") then
-- Wrap in <div class="mermaid"> for mermaid.js to render
return pandoc.RawBlock(
'html',
'<div class="mermaid">' .. el.text .. '</div>'
)
end
endWhen HTML is served, mermaid.js renders the diagrams client-side.
Step 2:
Publish to GitHub Pages (2-deploy-ghpages.yml)
Why Separate Workflow?
- Separation of concerns: Build docs β publish docs
- Artifact staging: docs-site is intermediate artifact
- Coverage preservation: If current build skips coverage, old coverage is retained
- Deployment safety: Can republish without rebuilding
Steps
- name: Checkout gh-pages branch
uses: actions/checkout@v4
with:
ref: gh-pages
fetch-depth: 0
- name: Download docs-site artifact
uses: actions/download-artifact@v4
with:
name: docs-site
- name: Preserve JaCoCo coverage if missing
run: |
if [ ! -d "docs-site/backend/coverage" ] && [ -d "backend/coverage" ]; then
# Current build doesn't have coverage, but old one does
mkdir -p /tmp/coverage-backup
cp -R backend/coverage /tmp/coverage-backup/
# ... (later restore)
fi
- name: Sync docs-site to gh-pages root
run: |
# Remove everything except .git and docs-site
find . -mindepth 1 -maxdepth 1 ! -name '.git' ! -name 'docs-site' -exec rm -rf {} +
# Copy docs-site contents to root
cp -R docs-site/* .
# Restore coverage if preserved
# ...
- name: Commit and push to gh-pages
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
if git status --porcelain | grep .; then
git add .
git commit -m "docs: publish docs-site"
git push origin gh-pages
else
echo "No changes to publish"
fiOutput: Live Documentation
After push to gh-pages, documentation is live
at:
https://keglev.github.io/inventory-service/
Site structure: - / β index.html
(portal) - /api/ β OpenAPI/ReDoc documentation -
/architecture/ β Architecture guides (deployment,
resources, etc.) - /backend/coverage/ β JaCoCo test
coverage report
Workflow
3οΈβ£: Deploy to Fly.io (3-deploy-fly.yml)
See Fly.io Infrastructure for detailed deployment steps.
Quick Summary
- Trigger: Automatic after CI success, OR
manual via
workflow_dispatch - Steps:
- Validate Docker image exists in registry
- Verify Fly.io app exists
- Deploy:
flyctl deploy --image {SHA} --strategy immediate - Health check: Poll
/healthuntil HEALTHY (5-min timeout) - Smoke tests: Validate API endpoints
- Report status
Artifact Flow Diagram
(from CI)"] -->|artifact upload| B["jacoco-html-{SHA}
(GitHub Actions)"] B -->|download| C["docs-pipeline.yml"] C -->|include| D["docs-site artifact"] E["OpenAPI YAML
(code annotations)"] -->|build| C F["Architecture .md
(git repo)"] -->|build| C D -->|download| G["2-deploy-ghpages.yml"] G -->|git push| H["gh-pages branch"] H -->|GitHub Pages| I["π Live Docs
(https://...)"] style B fill:#e1f5fe style D fill:#e1f5fe style I fill:#c8e6c9
Scripts Organization
/scripts/ Directory
scripts/
βββ build-openapi-docs.sh # Redocly: OpenAPI YAML β HTML
βββ build-architecture-docs.sh # Pandoc: Markdown β HTML
βββ mermaid-filter.lua # Pandoc filter for mermaid diagrams
βββ deploy-docs-scripts/ # (Optional) local deployment helpers
βββ ...
These scripts are invoked by docs-pipeline.yml
in CI environment.
Troubleshooting
Docs Build Fails: βRedocly CLI not foundβ
- Ensure
npm install -g @redocly/cliin workflow step - Check npm version compatibility (Node.js 20+)
- Review Redocly syntax:
redocly lint docs/api/openapi.yaml
Pandoc Conversion Fails: βCommand not foundβ
- Install Pandoc:
apt-get install pandoc - Verify Lua filter path is correct
- Check Markdown syntax (review .md file)
Mermaid Diagrams Not Rendering
- Verify Lua filter is wrapping code block in
<div class="mermaid"> - Ensure HTML includes:
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script> - Check diagram syntax:
mmdc -i diagram.md -o diagram.html
JaCoCo Coverage Missing from Docs
- Normal for docs-only pushes (JaCoCo only generated by CI)
- 2-deploy-ghpages.yml preserves old coverage if current build skips it
- To refresh coverage: Re-run
1-ci-test.yml
gh-pages Push Fails: βPermission deniedβ
- Verify GitHub token has
contents: writepermission - Check branch is
gh-pages(case-sensitive) - Ensure git user is configured:
git config user.name/email
Docs Artifacts Too Large
- Review whatβs in
docs-site/artifact - Remove unnecessary images, large generated files
- Compress coverage HTML if needed
- Consider cleanup:
find . -name "*.tmp" -delete
Related Documentation
- Deployment Index β Overview of entire pipeline
- Build & Docker Image β Maven and Docker build details
- Fly.io Infrastructure β Production deployment
- Architecture Overview β System design
Last Updated: November 2025
Audience: DevOps engineers, documentation
maintainers, CI/CD administrators