# Version Management Guide

## Overview

This WordPress plugin uses a centralized version management system that automatically keeps version numbers synchronized across all plugin files. Version management integrates with your existing GitHub Actions workflows for a complete release process.

## How It Works

### Single Source of Truth

`package.json` is the single source of truth for the version number. All other files are automatically synchronized from this value.

### Files That Contain Version Numbers

The following files are automatically updated when the version changes:

1. **package.json** (line 4)
   - `"version": "0.0.1"`
   - Source of truth, updated by semantic-release

2. **recast-paywall.php** (lines 6, 17, 27)
   - Plugin header: `Version: 0.0.1`
   - Plugin header: `Stable tag: 0.0.1`
   - PHP constant: `define('RECAST_PAYWALL_VERSION', '0.0.1');`

3. **readme.txt** (line 7)
   - `Stable tag: 0.0.1`

### Automated Release Process

This plugin has a sophisticated release workflow with two paths:

#### Path 1: Manual Production Release (Recommended)

1. **Initiate Release** - Manually trigger `Release - Create` workflow
   - Specify version number (e.g., 1.2.3)
   - Specify release type (patch/minor/major)
   - Creates release branch with version updates
   - Opens PR to main branch

2. **Review & Merge** - Review the release PR
   - All version numbers already updated via sync script
   - Merge when ready for production

3. **Automatic Deployment** - `Release - Publish` workflow runs
   - Creates GitHub release
   - Builds and uploads plugin zip
   - Opens PR to sync main → develop

#### Alternative: Manual Version Sync

If you need to manually update versions without going through the full release workflow:

1. **Update package.json** - Set the version directly
2. **Run sync script** - `npm run sync-version`
3. **Commit changes** - Commit the version updates
4. **Push to repository** - Version updated across all files

## Commit Message Format

Use [Conventional Commits](https://www.conventionalcommits.org/) format to trigger automatic version bumps:

### Version Bump Types

| Commit Prefix | Version Bump | Example |
|---------------|--------------|---------|
| `feat:` | Minor (0.x.0) | `feat: add new payment gateway` |
| `fix:` | Patch (0.0.x) | `fix: resolve mobile display issue` |
| `BREAKING CHANGE:` | Major (x.0.0) | `feat!: redesign paywall API` |
| `docs:`, `style:`, `refactor:`, `perf:`, `test:`, `chore:`, `ci:`, `build:` | Patch (0.0.x) | `docs: update installation guide` |

### Examples

```bash
# Patch release (0.0.1 -> 0.0.2)
git commit -m "fix: resolve caching issue with entitlements"
git commit -m "docs: update README with new features"

# Minor release (0.0.1 -> 0.1.0)
git commit -m "feat: add support for custom paywall templates"
git commit -m "feat: implement webhook retry mechanism"

# Major release (0.0.1 -> 1.0.0)
git commit -m "feat!: redesign API with breaking changes

BREAKING CHANGE: The paywall API has been completely redesigned.
Migration guide available in docs/MIGRATION.md"
```

## Manual Version Management

### Updating Versions Manually

If you need to manually update the version:

1. Edit the version in `package.json`
2. Run the sync script:
   ```bash
   npm run sync-version
   ```
3. Commit the changes:
   ```bash
   git add .
   git commit -m "chore: bump version to x.y.z"
   ```

### Sync Script

The sync script is located at `scripts/sync-version.js` and can be run manually:

```bash
# Via npm script
npm run sync-version

# Or directly
node scripts/sync-version.js
```

## GitHub Actions Workflows

This plugin has multiple workflows for different purposes:

### 1. release-create.yml - "Release - Create" (Manual Trigger)

**Purpose**: Create a release branch and PR for production deployment

**Trigger**: Manual workflow dispatch from GitHub Actions UI

**What it does**:
1. Checks out develop branch
2. Validates version format and ensures it's greater than current
3. **Uses sync-version script** to update all version numbers
4. Creates release branch (e.g., `release/v1.2.3`)
5. Commits version changes
6. Creates PR to main branch

### 2. release-publish.yml - "Release - Publish" (Automatic)

**Purpose**: Deploy release when PR is merged to main

**Trigger**: When a PR with branch name starting with `release/` is merged to main

**What it does**:
1. Extracts version from release branch name
2. Validates version consistency across files
3. Creates git tag (e.g., `v1.2.3`)
4. Creates GitHub release
5. Builds and uploads plugin zip
6. Optionally deploys to WordPress.org
7. Creates PR to sync main → develop

### 3. ci.yml - "CI - Validation" (Automatic)

**Purpose**: Run tests and validation on all branches

**Trigger**: Push or PR to develop/main branches

**What it does**:
1. Runs PHPUnit tests
2. Checks coding standards (PHPCS)
3. Validates plugin structure
4. Runs security scans
5. Builds plugin package on PR merge

### 4. wordpress-deploy.yml - "Deploy - WordPress.org" (Manual, Optional)

**Purpose**: Deploy to WordPress.org plugin repository

**Trigger**: Manual workflow dispatch (you choose when to deploy)

**What it does**:
1. Validates release tag format
2. Checks out the specified tag
3. Builds plugin package
4. Deploys to WordPress.org SVN (or dry run for testing)

**Features**:
- ✅ **Manual trigger only** - Never runs automatically
- ✅ **Dry run mode** - Test without deploying
- ✅ **Credential validation** - Checks for required secrets
- ✅ **Version validation** - Ensures proper tag format

**Note**: This workflow is completely separate from versioning/releases. You can create releases and test versioning without ever deploying to WordPress.org.

## Release Process

### Production Release (Recommended)

This is the recommended approach for creating production releases:

1. **Initiate Release**
   - Go to GitHub Actions
   - Select "Release - Create" workflow
   - Click "Run workflow"
   - Enter version number (e.g., `1.2.3`)
   - Select release type (patch/minor/major)
   - Optionally add release notes
   - Click "Run workflow"

2. **Review Release PR**
   - Workflow creates a release branch (e.g., `release/v1.2.3`)
   - All version numbers are updated via sync script
   - PR is automatically created to main branch
   - Review changes in the PR
   - Run any final manual tests

3. **Merge and Deploy**
   - Merge the release PR to main
   - `Release - Publish` workflow automatically:
     - Creates git tag (e.g., `v1.2.3`)
     - Creates GitHub release with notes
     - Builds and uploads plugin zip
     - Creates PR to sync main → develop
     - **Does NOT deploy to WordPress.org** (that's separate)

4. **Sync Back to Develop**
   - Review and merge the main → develop PR
   - Development continues on develop branch

5. **Deploy to WordPress.org** (Optional, when ready)
   - Go to Actions → "Deploy - WordPress.org"
   - Click "Run workflow"
   - Enter the release tag (e.g., `v1.2.3`)
   - Check "Dry run" to test first (recommended)
   - Click "Run workflow"
   - Review output, then run again without dry run to deploy


### Manual Version Sync (For Fixes)

If version numbers get out of sync:

```bash
# Update package.json to desired version
npm version 1.2.3 --no-git-tag-version

# Sync to all other files
npm run sync-version

# Or set version directly
node scripts/sync-version.js --from 1.2.3

# Commit changes
git add .
git commit -m "chore: sync version to 1.2.3"
```

## Semantic Versioning

This plugin follows [Semantic Versioning 2.0.0](https://semver.org/):

Given a version number **MAJOR.MINOR.PATCH**:

- **MAJOR**: Incompatible API changes (breaking changes)
- **MINOR**: New functionality, backward compatible
- **PATCH**: Bug fixes, backward compatible

### Pre-release Versions

For pre-release versions, semantic-release supports:

- **Beta**: `1.0.0-beta.1`
- **RC**: `1.0.0-rc.1`

Configure these in `.releaserc.json` if needed.

## Configuration Files

### scripts/sync-version.js

The centralized version sync script. Supports two modes:

**Mode 1: Sync from package.json** (default)
```bash
node scripts/sync-version.js
```
Reads version from `package.json` and updates all other files.

**Mode 2: Set version and sync**
```bash
node scripts/sync-version.js --from 1.2.3
```
Updates `package.json` to specified version, then updates all other files.

The script updates:
- `package.json` - version field (when using `--from`)
- `recast-paywall.php` - Plugin header Version field
- `recast-paywall.php` - Plugin header Stable tag field
- `recast-paywall.php` - RECAST_PAYWALL_VERSION PHP constant
- `readme.txt` - Stable tag field
- `composer.json` - version field (if it exists)

### package.json

Contains the sync-version script:

```json
{
  "version": "0.0.1",
  "scripts": {
    "sync-version": "node scripts/sync-version.js",
    "build": "wp-scripts build",
    "start": "wp-scripts start"
  }
}
```

### .releaserc.json (Optional)

If you want to use pure semantic-release instead of the manual release workflow:

```json
{
  "branches": ["main"],
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    "@semantic-release/changelog",
    ["@semantic-release/npm", { "npmPublish": false }],
    ["@semantic-release/exec", { "prepareCmd": "npm run sync-version" }],
    ["@semantic-release/git", {
      "assets": [
        "package.json",
        "package-lock.json",
        "CHANGELOG.md",
        "recast-paywall.php",
        "readme.txt"
      ],
      "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
    }],
    "@semantic-release/github"
  ]
}
```

## Troubleshooting

### Versions Out of Sync

If you find version numbers are different across files:

```bash
# Fix it by syncing from package.json
npm run sync-version
git add .
git commit -m "chore: sync version numbers"
```

### Release Workflow Not Running

Check that:

1. Release PRs have branch names starting with `release/`
2. GitHub Actions has write permissions
3. `GITHUB_TOKEN` secret is available
4. Workflows are enabled in repository settings

### Failed Release

If a release fails:

1. Check GitHub Actions logs for errors
2. Fix any issues (version conflicts, test failures, etc.)
3. For `Release - Create` failures: Re-run the workflow
4. For `Release - Publish` failures: May need to manually create tag/release

### Manual Version Override

If you need to force a specific version:

1. Update `package.json` version manually
2. Run `npm run sync-version`
3. Commit with `[skip ci]` to avoid triggering release:
   ```bash
   git commit -m "chore: force version to x.y.z [skip ci]"
   ```

## Best Practices

1. **Always use conventional commits** for clear changelog and automatic versioning
2. **Never manually edit version numbers** in plugin files (except package.json)
3. **Run sync-version after package.json changes** if not using semantic-release
4. **Test on develop branch** before merging to main
5. **Use meaningful commit messages** - they become your changelog!

## Benefits

✅ **No manual version management** - fully automated
✅ **Consistent versions** across all files
✅ **Automatic changelog generation** from commits
✅ **Clear version history** with semantic versioning
✅ **Automated GitHub releases** with plugin zip files
✅ **Error-free releases** - no forgetting to update a file
✅ **Better commit messages** - encourages conventional commits

## Workflow Diagram

```
┌─────────────────────────────────────────────────────────────────┐
│                     DEVELOPMENT WORKFLOW                         │
└─────────────────────────────────────────────────────────────────┘

  [develop branch]
       │
       │ Feature work
       │
       ├─── ci.yml (tests, linting, validation)
       │
       ▼
  [Ready for release]
       │
       │ Manual trigger
       ▼
  [Release - Create]
       │
       ├─── Validates version
       ├─── Runs sync-version.js --from VERSION
       └─── Creates release/vX.Y.Z branch
              │
              └─── Creates PR → main
                      │
                      │ Review & approve
                      ▼
                  [Merge PR]
                      │
                      └─── Release - Publish
                            ├─── Creates git tag
                            ├─── Creates GitHub release
                            ├─── Builds plugin zip
                            └─── Creates PR: main → develop

  [main branch]
       │
       └─── Stable production code

┌─────────────────────────────────────────────────────────────────┐
│                   CENTRALIZED VERSION SYNC                       │
└─────────────────────────────────────────────────────────────────┘

  package.json ─────► sync-version.js ─────┬──► recast-paywall.php
       ▲                                    ├──► readme.txt
       │                                    └──► composer.json
       │
  [--from VERSION flag sets package.json first]
```

## Quick Reference

### Create a Production Release

```bash
# Via GitHub Actions UI
1. Go to Actions → Release - Create
2. Enter version (e.g., 1.2.3)
3. Select release type (patch/minor/major)
4. Click "Run workflow"
5. Review and merge the created PR
```

### Manual Version Sync

```bash
# Set specific version
node scripts/sync-version.js --from 1.2.3

# Sync from package.json
npm run sync-version
```

### Check Current Versions

```bash
# Check all version locations
grep "Version:" recast-paywall.php
grep "Stable tag:" readme.txt
grep "version" package.json | head -1
```

## Questions?

- Check `scripts/README.md` for detailed script documentation
- Review `.github/workflows/` for workflow details
- Follow [Semantic Versioning](https://semver.org/) guidelines
- Use [Conventional Commits](https://www.conventionalcommits.org/) format

