Skip to content

CI CD Reference

Richard Kent Gates edited this page Jun 9, 2026 · 2 revisions

CI/CD Reference

Complete guide to Rich Statistics continuous integration and deployment.

Workflow Overview

┌─────────────────────────────────────────────────────────────────┐
│                     BRANCH STRUCTURE                             │
├──────────────┬──────────────┬───────────────────────────────────┤
│   develop    │    test      │              main                 │
│   (dev)      │   (staging)  │           (production)            │
├──────────────┼──────────────┼───────────────────────────────────┤
│ Auto-deploy  │ Manual promote│ Manual promotion only             │
│ on push      │ (workflow_dispatch) │ Via promote.yml workflow          │
├──────────────┼──────────────┼───────────────────────────────────┤
│ dev.         │ test.        │ app.                              │
│ richstatistics.com          │ richstatistics.com                │
├──────────────┼──────────────┼───────────────────────────────────┤
│ Freemius: —  │ Freemius:    │ Freemius:                         │
│              │ beta         │ released (public)                 │
└──────────────┴──────────────┴───────────────────────────────────┘

Workflows

1. build-develop.yml

Trigger: Push to develop or workflow_dispatch
Purpose: Continuous integration for development

Jobs:

  • build-zip — PHP checks, create ZIP (version: dev.{run_number})
  • deploy-web — Webhook deploy to dev server
  • build-desktop — Tauri builds for dev

2. build-test.yml

Trigger: workflow_dispatch only
Purpose: Pre-release QA with Freemius beta

Jobs:

  • build-zip — PHP checks, create ZIP
  • deploy-web — Webhook deploy to test server
  • upload-freemiusSDK upload with release_mode=beta
  • build-desktop — Tauri builds for test

3. build-release.yml

Trigger: Tag push (v*.*.*) or workflow_dispatch from promote.yml
Purpose: Production releases

Jobs:

  • build-zip — PHP checks, create ZIP
  • upload-freemiusSDK upload (released or beta)
  • release — GitHub Release, PWA snapshot
  • build-desktop — Tauri builds with version stamp
  • ping-deploy — Webhook deploy to production

4. promote-test.yml

Trigger: workflow_dispatch on develop
Purpose: Merge develop → test

Steps:

  1. Create PR: develop → test
  2. Merge PR (--merge, not squash)
  3. Dispatch "Build Test" workflow

5. promote.yml (Promote to Production)

Trigger: workflow_dispatch on test
Inputs: version (auto-detect), channel (stable/beta)

Steps (stable):

  1. Create PR: test → main
  2. Merge PR
  3. Force-create tag: git tag -f v{version} origin/main
  4. Force-push tag: git push -f origin v{version}
  5. Dispatch "Build Release" workflow

Why force? Handles re-releases at same version (tag already exists from previous release).

Freemius Deploy Script

Location: bin/deploy-freemius.php

Usage:

php bin/deploy-freemius.php <file> <version> <release_mode> [sandbox]

# Examples:
php bin/deploy-freemius.php plugin.zip 2.4.20 beta
php bin/deploy-freemius.php plugin.zip 2.4.20 released

Algorithm:

1. GET plugins/{id}/tags.json — Check if version exists
2. IF exists: Skip upload, use existing tag ID
3. IF not exists: POST with ZIP file, get new tag ID
4. PUT release_mode to tag

Environment Variables:

DEV_ID: 25954
PUBLIC_KEY: ${FREEMIUS_PUBLIC_KEY}
SECRET_KEY: ${FREEMIUS_SECRET_KEY}
PLUGIN_SLUG: rich-statistics
PLUGIN_ID: 25954

Release Modes:

Mode Description Used By
beta Beta opt-in users build-test.yml, beta tags
released All license holders build-release.yml (stable)
pending Unreleased (manual) Not used in CI

Server Deployment

Webhook Mechanism

Flow:

CI workflow
    ↓ POST /_deploy/
Webhook PHP (validates token)
    ↓ Writes timestamp
.deploy-trigger file
    ↓ Cron poller (every minute)
rsa-app-update script
    ↓ Sparse-checkout docs/app/
Deploy to webroot

Manual Trigger:

curl -X POST -H "X-Deploy-Token: $(cat /etc/rsa-webhook-token-{env})" \
  https://{env}.richstatistics.com/_deploy/

PWA Snapshots

Structure:

docs/app/v/
├── 2.4.27/
│   ├── stable/   ← Production PWA
│   │   ├── index.html, app.js, ...
│   │   └── icons/
│   └── beta/     ← Beta PWA (same files)
├── 2.4.26/
│   └── ...
├── versions.json       ← Auto-generated
└── versions-beta.json  ← Auto-generated (same content)

Pruning: Keep last 12 versions, remove older.

Complete Release Flow

Phase 1: Develop

git checkout develop
# ... make changes, commit ...
git push origin develop
# Auto: build-develop.yml runs

Phase 2: Promote to Test

GitHub UI: Actions → Promote to Test → Run on develop

Verify:

  • test.richstatistics.com updated
  • Freemius shows beta version
  • Desktop binaries available
  • Tests pass

Phase 3: Promote to Production

GitHub UI: Actions → Promote to Production → Run on test
Inputs: version=(blank), channel=stable

Verify:

  • GitHub Release created
  • Freemius shows "released"
  • Production PWA updated
  • Desktop binaries available

Troubleshooting

Tag Already Exists

git fetch origin main
git tag -f v2.4.20 origin/main
git push -f origin v2.4.20
gh workflow run "Build Release" --ref "v2.4.20"

Freemius Upload Fails

Check secrets, plugin ID (25954), network connectivity.

Deploy Stuck

# Check cron
grep "rsa-deploy-cron" /var/log/syslog | tail -5

# Manual trigger
curl -X POST -H "X-Deploy-Token: $(cat /etc/rsa-webhook-token)" \
  https://app.richstatistics.com/_deploy/

Branch Deleted

# Restore (if --delete-branch was used)
git push origin origin/main:refs/heads/develop
git push origin origin/main:refs/heads/test

Quick Commands

# Check current version
grep "RSA_VERSION" rich-statistics.php

# Trigger workflows
gh workflow run "Promote to Test" --ref develop
gh workflow run "Promote to Production" --ref test -f channel=stable
gh workflow run "Build Release" --ref "v2.4.20"

# Check Freemius
curl -u "DEV_ID:SECRET" \
  "https://api.freemius.com/v1/developers/25954/plugins/25954/tags.json"

# Manual deploy
curl -X POST -H "X-Deploy-Token: $(cat /etc/rsa-webhook-token)" \
  https://app.richstatistics.com/_deploy/

Documentation


Last Updated: May 18, 2026
Current Status: ✅ All workflows operational, Freemius SDK working

Documentation

Features

User Guide

Compliance


External Links

Clone this wiki locally