Skip to content

Release Tracks

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

Release Tracks

Rich Statistics uses a three-branch CI/CD pipeline with automated Freemius integration. Each environment has its own WordPress site, PWA web app, desktop binaries, and APT repository.

Overview

Branch Environment Subdomain Freemius Use Case
develop Development dev.richstatistics.com Bleeding-edge development, auto-deploy on push
test Staging / QA test.richstatistics.com beta Pre-release QA, beta testing
main Production app.richstatistics.com released End-user releases (tagged v*.*.*)

Release Pipeline

feature branch → develop → test → main (tagged v*)
     ↓              ↓        ↓         ↓
  PR merge     auto-deploy  manual   Freemius
                to dev       promote  released
                           to test   + GitHub Release
                                     + PWA snapshot
                                     + Desktop builds

Promotion Workflows

Promote to Test

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

What happens:

  1. Creates PR: develop → test
  2. Merges PR (--merge preserves history)
  3. Dispatches Build Test workflow

Build Test runs:

  • PHP lint, PHPCS, PHPUnit tests
  • Creates plugin ZIP (version: test.{run_number})
  • Deploys PWA to test.richstatistics.com
  • Uploads to Freemius as beta (opt-in beta testers)
  • Builds desktop binaries (Linux + Windows)

Promote to Production

Trigger: GitHub Actions → Promote to Production → Run on test → Channel: stable

What happens:

  1. Creates PR: test → main
  2. Merges PR (--merge)
  3. Force-creates tag: git tag -f v{version} origin/main
  4. Force-pushes tag: git push -f origin v{version}
  5. Dispatches Build Release workflow

Build Release runs:

  • PHP lint, PHPCS, PHPUnit tests
  • Creates plugin ZIP
  • Uploads to Freemius as released (public to all license holders)
  • Creates GitHub Release with ZIP + SHA256 checksum
  • Creates PWA snapshot: docs/app/v/{version}/{stable,beta}/
  • Updates versions.json (auto-generated)
  • Prunes old snapshots (keep last 12)
  • Builds desktop binaries (version-stamped)
  • Deploys PWA to app.richstatistics.com

Freemius Integration

Release Modes

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

How It Works

The bin/deploy-freemius.php script uses the official Freemius PHP SDK:

  1. Check if version existsGET plugins/{id}/tags.json
  2. If exists: Skip upload, use existing tag ID
  3. If not exists: Upload ZIP via POST plugins/{id}/tags.json
  4. Set release_modePUT plugins/{id}/tags/{tag_id}.json

Benefits:

  • Handles re-uploads gracefully (skips if version exists)
  • Updates release_mode without re-uploading
  • No third-party action dependencies
  • Full error reporting

Manual Workflow Triggers

Promote to Test

gh workflow run "Promote to Test" --ref develop

Promote to Production

# Stable release
gh workflow run "Promote to Production" --ref test -f channel=stable

# Beta release (tag test branch only)
gh workflow run "Promote to Production" --ref test -f channel=beta

Build Release (manual)

gh workflow run "Build Release" --ref "v2.4.20"

Troubleshooting

Tag Already Exists

If promote fails with fatal: tag 'vX.Y.Z' already exists:

# Force update tag to current main
git fetch origin main
git tag -f vX.Y.Z origin/main
git push -f origin vX.Y.Z

# Re-dispatch Build Release
gh workflow run "Build Release" --ref "vX.Y.Z"

Note: promote.yml now uses git tag -f and git push -f automatically.

Freemius Upload Fails

Check:

  1. GitHub Secrets configured: FREEMIUS_PUBLIC_KEY, FREEMIUS_DEV_ID, FREEMIUS_SECRET_KEY
  2. Plugin ID: 25954, Developer ID: 25954
  3. ZIP file path correct
  4. Network connectivity (SDK uses curl)

View logs:

gh run view {run-id} --log | grep -E "Checking|Found|Uploading|Setting|Done"

Deploy Stuck

Manual trigger:

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

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

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

Check cron:

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

Server Endpoints

Resource Production Dev Test
PWA origin app.richstatistics.com dev.richstatistics.com test.richstatistics.com
Webhook app.richstatistics.com/_deploy/ dev.richstatistics.com/_deploy/ test.richstatistics.com/_deploy/
APT repo app.richstatistics.com/apt/ dev.richstatistics.com/apt/ test.richstatistics.com/apt/
Desktop binaries app.richstatistics.com/dist/ dev.richstatistics.com/dist/ test.richstatistics.com/dist/
Webhook token /etc/rsa-webhook-token /etc/rsa-webhook-token-dev /etc/rsa-webhook-token-test

Downloads

Desktop App

Environment Platform URL
Production Linux (amd64) https://app.richstatistics.com/dist/rich-statistics_amd64.deb
Production Linux (arm64) https://app.richstatistics.com/dist/rich-statistics_arm64.deb
Production Windows https://app.richstatistics.com/dist/rich-statistics.exe
Dev Windows https://dev.richstatistics.com/dist/rich-statistics.exe
Test Windows https://test.richstatistics.com/dist/rich-statistics.exe

PWA Web App

Environment URL
Production https://app.richstatistics.com/
Dev https://dev.richstatistics.com/
Test https://test.richstatistics.com/

Version Management

Version Strings (Must All Match)

File: rich-statistics.php

  • Line 6 (plugin header): Version: 2.4.27
  • Line 65 (constant): define( 'RSA_VERSION', '2.4.27' );

File: readme.txt

  • Line 7: Stable tag: 2.4.27

Version Bump Checklist

Before promoting to production:

  • Update all three version strings
  • Commit and push to test branch
  • Verify tests pass
  • Run Promote to Production workflow

Documentation


Last Updated: June 7, 2026
Current Version: 2.4.27 (beta on test, 2.4.27 released on production)

Documentation

Features

User Guide

Compliance


External Links

Clone this wiki locally