Files
igny8/docs/60-PLUGINS/PLUGIN-UPDATE-WORKFLOW.md
2026-01-09 22:45:30 +00:00

14 KiB

Plugin Update Workflow

Last Updated: January 9, 2026
Status: Production
Scope: How to release plugin updates and what happens automatically vs manually


Table of Contents

  1. Update Workflow Overview
  2. What Happens Automatically
  3. What Requires Manual Action
  4. Step-by-Step: Releasing a New Version
  5. Post-Update Verification Checklist
  6. Version Numbering
  7. Rollback Procedure
  8. Emergency Updates

1. Update Workflow Overview

The Big Picture

┌─────────────────────────────────────────────────────────────────────────┐
│                     Plugin Update Lifecycle                              │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  ┌──────────────┐                                                       │
│  │ 1. DEVELOP   │  Make changes to plugin source code                   │
│  │    ↓         │  Location: /plugins/wordpress/source/igny8-wp-bridge/ │
│  └──────────────┘                                                       │
│                                                                          │
│  ┌──────────────┐                                                       │
│  │ 2. VERSION   │  Update version in PHP header + constant              │
│  │    ↓         │  File: igny8-bridge.php                               │
│  └──────────────┘                                                       │
│                                                                          │
│  ┌──────────────┐                                                       │
│  │ 3. RELEASE   │  Create PluginVersion in Django admin                 │
│  │    ↓         │  Set status = "released" or "update_ready"            │
│  └──────────────┘                                                       │
│                                                                          │
│  ┌──────────────┐                                                       │
│  │ 4. AUTO-BUILD│  ✅ AUTOMATIC: ZIP created, checksums calculated      │
│  │    ↓         │  Signal handler builds package on status change       │
│  └──────────────┘                                                       │
│                                                                          │
│  ┌──────────────┐                                                       │
│  │ 5. VERIFY    │  Test download, check contents, verify endpoints      │
│  │    ↓         │  See verification checklist below                     │
│  └──────────────┘                                                       │
│                                                                          │
│  ┌──────────────┐                                                       │
│  │ 6. AVAILABLE │  WordPress sites can now see and install update       │
│  │              │  Users update via WP admin or auto-update             │
│  └──────────────┘                                                       │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

2. What Happens Automatically

When you change a PluginVersion status to released or update_ready, the following happens automatically via Django signals:

Automatic Actions

Action Details
ZIP Creation Source files packaged into distribution ZIP
Version Update Version number updated in PHP files inside ZIP
File Cleanup Tests, .git, pycache, .bak files removed from ZIP
Checksum Calculation SHA256 hash generated
File Size Recording Byte count stored in database
File Path Update file_path field populated
Released Date released_at timestamp set
Symlink Update *-latest.zip symlink updated

How It Works (Signal Handler)

# backend/igny8_core/plugins/signals.py

@receiver(pre_save, sender=PluginVersion)
def auto_build_plugin_on_release(sender, instance, **kwargs):
    """
    Triggered when PluginVersion.status changes to:
    - 'released'
    - 'update_ready'
    
    Actions:
    1. Calls create_plugin_zip() utility
    2. Updates instance.file_path
    3. Updates instance.file_size
    4. Updates instance.checksum
    5. Sets instance.released_at
    """

What WordPress Sites See

Once released, the check-update API returns:

{
    "update_available": true,
    "latest_version": "1.2.0",
    "download_url": "https://api.igny8.com/api/plugins/igny8-wp-bridge/download/",
    "changelog": "Your changelog here"
}

WordPress will show "Update Available" in:

  • Plugins page
  • Dashboard → Updates
  • Admin bar (if enabled)

3. What Requires Manual Action

Manual Steps Required

Action When How
Update Source Version Before release Edit igny8-bridge.php header
Create PluginVersion Record Each release Django admin or management command
Write Changelog Each release Enter in PluginVersion.changelog
Verify After Release After status change Run verification checklist
Mark Old Version Deprecated After successful release Change old version status

Source Version Update Locations

When releasing a new version, update these in the source:

File: /plugins/wordpress/source/igny8-wp-bridge/igny8-bridge.php

/**
 * Plugin Name: IGNY8 WordPress Bridge
 * Version: 1.2.0                          ← UPDATE THIS
 */

define('IGNY8_BRIDGE_VERSION', '1.2.0');    AND THIS

Note: The ZIP build process also updates these, but it's good practice to keep source in sync.


4. Step-by-Step: Releasing a New Version

Step 1: Make Code Changes

cd /data/app/igny8/plugins/wordpress/source/igny8-wp-bridge/

# Make your changes to PHP files
# Test locally if possible

Step 2: Update Version Number

Edit igny8-bridge.php:

/**
 * Plugin Name: IGNY8 WordPress Bridge
 * Version: 1.2.0                          ← New version
 */

define('IGNY8_BRIDGE_VERSION', '1.2.0');    Match here

Step 3: Create PluginVersion in Django Admin

  1. Go to: https://api.igny8.com/backend/
  2. Navigate to: Plugin DistributionPlugin Versions
  3. Click Add Plugin Version
  4. Fill in:
    • Plugin: IGNY8 WordPress Bridge
    • Version: 1.2.0
    • Status: draft (initially)
    • Changelog: Describe changes
    • Min PHP Version: 7.4 (or higher if needed)
  5. Click Save

Step 4: Release the Version

  1. Edit the PluginVersion you just created
  2. Change Status to released
  3. Click Save

What happens: Signal triggers auto-build → ZIP created → database updated

Step 5: Verify Release

Run the verification checklist below.

Step 6: Deprecate Old Version (Optional)

  1. Find the previous version in Django admin
  2. Change Status to deprecated
  3. Save

5. Post-Update Verification Checklist

Immediate Checks (Do Every Release)

# 1. Verify ZIP exists
ls -lh /data/app/igny8/plugins/wordpress/dist/igny8-wp-bridge-v1.2.0.zip

# 2. Verify symlink updated
ls -la /data/app/igny8/plugins/wordpress/dist/igny8-wp-bridge-latest.zip

# 3. Test download endpoint
curl -s -o /dev/null -w "%{http_code} - %{size_download} bytes\n" \
    https://api.igny8.com/api/plugins/igny8-wp-bridge/download/

# 4. Test check-update endpoint
curl -s "https://api.igny8.com/api/plugins/igny8-wp-bridge/check-update/?current_version=1.0.0" | python3 -m json.tool

# 5. Test info endpoint
curl -s https://api.igny8.com/api/plugins/igny8-wp-bridge/info/ | python3 -m json.tool

# 6. Verify version in ZIP
unzip -p /data/app/igny8/plugins/wordpress/dist/igny8-wp-bridge-v1.2.0.zip \
    igny8-wp-bridge/igny8-bridge.php | grep -E "Version:|IGNY8_BRIDGE_VERSION"

# 7. Verify API URL in ZIP (must be api.igny8.com)
unzip -p /data/app/igny8/plugins/wordpress/dist/igny8-wp-bridge-v1.2.0.zip \
    igny8-wp-bridge/igny8-bridge.php | grep "api.igny8.com"

Database Verification

# Check database has correct values
docker exec igny8_backend python manage.py shell -c "
from igny8_core.plugins.models import Plugin, PluginVersion
p = Plugin.objects.get(slug='igny8-wp-bridge')
v = p.get_latest_version()
print(f'Version: {v.version}')
print(f'Status: {v.status}')
print(f'File path: {v.file_path}')
print(f'File size: {v.file_size}')
print(f'Checksum: {v.checksum[:32]}...')
print(f'Released at: {v.released_at}')
"

Expected Results

Check Expected
Download returns 200 status, ~150-200KB
check-update shows "latest_version": "1.2.0"
info shows "version": "1.2.0"
ZIP version header Version: 1.2.0
API URL api.igny8.com (NOT app.igny8.com)

WordPress Verification (If Possible)

  1. Go to a test WordPress site with plugin installed
  2. Navigate to DashboardUpdatesCheck Again
  3. Verify "IGNY8 WordPress Bridge" shows update available
  4. Click "View version details" → verify changelog appears
  5. Click "Update Now" → verify update completes successfully

6. Version Numbering

Semantic Versioning

Format: MAJOR.MINOR.PATCH (e.g., 1.2.3)

Part When to Increment
MAJOR Breaking changes, incompatible API changes
MINOR New features, backwards compatible
PATCH Bug fixes, minor improvements

Version Code Calculation

Used for numeric comparison in database:

1.0.0  → 10000
1.0.1  → 10001
1.2.0  → 10200
1.2.3  → 10203
2.0.0  → 20000

Formula: (MAJOR * 10000) + (MINOR * 100) + PATCH


7. Rollback Procedure

If Update Causes Issues

Option 1: Quick Rollback via Database

# Make old version the "latest" by changing status
docker exec igny8_backend python manage.py shell -c "
from igny8_core.plugins.models import PluginVersion

# Demote new version
new = PluginVersion.objects.get(plugin__slug='igny8-wp-bridge', version='1.2.0')
new.status = 'deprecated'
new.save()

# Promote old version back
old = PluginVersion.objects.get(plugin__slug='igny8-wp-bridge', version='1.1.1')
old.status = 'released'
old.save()

print('Rollback complete')
"

Option 2: Keep Old ZIP Files

Old ZIP files are preserved in dist/. To serve an old version:

# Update symlink to point to old version
cd /data/app/igny8/plugins/wordpress/dist/
ln -sf igny8-wp-bridge-v1.1.1.zip igny8-wp-bridge-latest.zip

Retention Policy

Keep at least 3 previous version ZIPs for emergency rollback:

  • Current release
  • Previous release
  • One before that

8. Emergency Updates

For Critical Security Fixes

  1. Set force_update = True on the new PluginVersion
  2. This flag signals WordPress sites that update is mandatory
  3. Sites with auto-updates enabled will update immediately

Emergency Release Checklist

# 1. Make the fix in source
cd /data/app/igny8/plugins/wordpress/source/igny8-wp-bridge/
# ... make changes ...

# 2. Update version (use PATCH increment)
# Edit igny8-bridge.php

# 3. Create version in Django admin with:
#    - Status: update_ready
#    - Force Update: ✓ (checked)
#    - Changelog: "SECURITY: [description]"

# 4. Verify immediately
curl https://api.igny8.com/api/plugins/igny8-wp-bridge/check-update/?current_version=1.0.0

# Response should include:
# "force_update": true

Quick Reference Card

Release New Version

1. Edit source code
2. Update version in igny8-bridge.php (header + constant)
3. Create PluginVersion in Django admin (status: draft)
4. Change status to "released" → Auto-build triggers
5. Run verification checklist
6. Deprecate old version

Verification Commands

# Test all endpoints
curl -I https://api.igny8.com/api/plugins/igny8-wp-bridge/download/
curl https://api.igny8.com/api/plugins/igny8-wp-bridge/check-update/?current_version=1.0.0
curl https://api.igny8.com/api/plugins/igny8-wp-bridge/info/

# Check ZIP contents
unzip -l /data/app/igny8/plugins/wordpress/dist/igny8-wp-bridge-v*.zip | head -20

Emergency Rollback

# Swap versions in database
docker exec igny8_backend python manage.py shell -c "
from igny8_core.plugins.models import PluginVersion
PluginVersion.objects.filter(version='NEW').update(status='deprecated')
PluginVersion.objects.filter(version='OLD').update(status='released')
"