# Pre-Release & Merge-to-Main Checklist This document is the authoritative release checklist for **ZFS Buddy Backup**. Every step in this checklist must be completed and verified before merging changes from the `dev` branch into `main` and publishing a release tag. > [!IMPORTANT] > **Static Procedure Specification**: This file is an authoritative, version-controlled standard operating procedure. **Do NOT edit this file or check off items during release execution.** Keep this document unchanged in git. Track your release progress and verification state in your agent conversation, terminal notes, or pull request description. --- ## Overview of Release Workflow ```text ┌─────────────────────────────────────────────────────────────┐ │ Phase 1: Code Quality, Hygiene & Local Unit Testing │ │ • Dead code & complexity audit • Static PHP/Shell lint │ │ • PII & credential scan • Line endings & permissions│ │ • Fast unit test suite (t/*.t) │ └──────────────────────────────┬──────────────────────────────┘ │ ┌──────────────────────────────▼──────────────────────────────┐ │ Phase 2: Release Candidate Preparation & Version Bump │ │ • Bump version in plg • Author in plg │ │ • Update USER_GUIDE & screenshots • Build txz & sync MD5 │ │ • Commit clean candidate on dev │ └──────────────────────────────┬──────────────────────────────┘ │ ┌──────────────────────────────▼──────────────────────────────┐ │ Phase 3: Automated Testlab Release Gate & Verification │ │ • Run release gate in Execute • Verify matrix scenarios │ │ • Generic & TrueNAS smoke • WebGUI theme & UI check │ │ • Commit generated testlab history on dev │ └──────────────────────────────┬──────────────────────────────┘ │ ┌──────────────────────────────▼──────────────────────────────┐ │ Phase 4: Merge, Tag & GitHub Release Publishing │ │ • Merge dev to main • Push git tag │ │ • Trigger release workflow • Attach txz & publish │ └──────────────────────────────┬──────────────────────────────┘ │ ┌──────────────────────────────▼──────────────────────────────┐ │ Phase 5: Live In-The-Wild Sanity Check │ │ • Clean public URL install • Package MD5 verification │ │ • Emhttp & WebGUI verification • Dashboard load check │ └─────────────────────────────────────────────────────────────┘ ``` --- ## Phase 1: Code Quality, Hygiene & Local Unit Testing Complete these static audits and local unit tests before packaging or provisioning VMs. ### 1.1 Dead Code & Obsolete Logic - **Scan for unused PHP functions & variables**: Ensure all functions declared in `src/usr/local/emhttp/plugins/buddybackup/*.php` are actively used or exported for Unraid emhttp hooks. - **Remove debug statements**: Ensure no stray `var_dump()`, `print_r()`, `console.log()`, `error_log()` debugging spam, or commented-out draft blocks exist in `src/`. - **Clean up dependencies**: Verify that any binary or script in `deps/` is actively required. Remove orphaned helper scripts or temporary files. ### 1.2 Code Complexity & Quality - **Review cyclomatic complexity**: Identify deeply nested conditionals or overly complex loops in `src/` (especially in `common.php`, `Backups.page`, and `BuddysBackupSettings.page`). Refactor into small, single-purpose helper functions where appropriate. - **Consistent error handling**: Ensure all shell command invocations check exit codes and report clean, localized errors to the WebGUI instead of dumping raw stack traces or silent failures. - **Simulated Dynamix template evaluation**: Confirm all `.page` files evaluate cleanly without warnings: ```powershell & "C:\Program Files\Git\usr\bin\perl.exe" t/php_syntax_and_eval.t ``` - **No raw unescaped ampersands**: Ensure XML headers in `.page` files do not contain unescaped `&` characters (must use `&` where required by Unraid parser). ### 1.3 Personal Information (PII) & Secret Leak Prevention - **No hardcoded credentials**: Verify zero hardcoded private keys, passwords, authentication tokens, or test SSH keys in the repository. - **No personal or host paths**: Ensure files do not contain local developer paths (e.g., `C:\Users\...`, `/mnt/user//...`, `/home//...`). - **No private IP addresses or hostnames**: Verify examples and test fixtures use dummy IPs (e.g., `192.0.2.x`, `127.0.0.1`) or standard RFC documentation addresses instead of real private LAN addresses. - **Clean `.gitignore` enforcement**: Confirm that `.testlab/`, `testlab/config/lab.local.json`, and local transient logs are ignored and not staged: ```powershell git status --ignored ``` ### 1.4 Line Endings (CRLF vs LF) & File Permissions - **Unix line endings (`LF`)**: Shell scripts on Unraid fail immediately with `\r: command not found` if committed with Windows `CRLF`. Ensure all files in `src/` have Unix `LF` line endings: ```powershell Get-ChildItem -Path src -Recurse -File | ForEach-Object { $content = [System.IO.File]::ReadAllText($_.FullName) if ($content.Contains("`r`n")) { Write-Warning "CRLF found in $($_.FullName)" } } ``` - **Executable permissions (`0755`)**: Verify executable bits on shell/perl scripts in `src/usr/local/emhttp/plugins/buddybackup/`: - `deps/restrict_zfs` - `deps/generic_host_setup.sh` - `deps/sanoid` - `deps/syncoid` - `scripts/rc.buddybackup` ### 1.5 Automated Unit & TAP Suite (`t/*.t`) - **Run all TAP tests**: Run the complete unit and integration test suite: ```powershell # Run natively with Windows / Git Perl: powershell -ExecutionPolicy Bypass -File ./testlab/scripts/run-unit-tests.ps1 # Or run inside WSL (exercises full PHP evaluation): powershell -ExecutionPolicy Bypass -File ./testlab/scripts/run-unit-tests.ps1 -UseWsl ``` Verify all of the following test files pass without failures: - `t/restrict_zfs.t`: Strict allowlist parsing, command injection defense, and privilege escalation guards. - `t/restrict_zfs_scope.t`: Dataset scope boundaries and path traversal rejection. - `t/generic_host_setup.t`: Remote host setup script behavior, argument parsing, and state files. - `t/generic_host_setup_truenas.t`: TrueNAS SCALE specific sudo and allowlist path behaviors. - `t/php_syntax_and_eval.t`: PHP syntax check (`php -l`), `.page` template evaluation, and telemetry keys. - `t/multi_buddy.t`: Multi-buddy key handling and configuration parsing. - `t/backwards_compat.t`: Protocol and CLI backwards compatibility across versions. - **New code test coverage**: Ensure any newly introduced feature or bug fix includes an accompanying test in `t/`. --- ## Phase 2: Release Candidate Preparation & Version Bump Prepare the release metadata, package archive, and clean git state *before* running the automated testlab release gate. The release gate requires a clean worktree and a pre-bumped version to validate upgrade matrices and record persistent release history. ### 2.1 Version Bump in `buddybackup.plg` - **Set release version**: Update the `version` entity in [`buddybackup.plg`](file:///y:/buddybackup.plg): ```xml ``` *(If releasing multiple builds in a single day, append a letter suffix, e.g. `2026.09.23a`).* ### 2.2 Changelog & Release Notes Authoring - **Update `` in [`buddybackup.plg`](file:///y:/buddybackup.plg)**: Unraid's Plugin Manager displays this XML block directly to users when checking for updates. Add a new section at the top with the release version: ```xml ###YYYY.MM.DD - Concise bullet points of user-facing features, enhancements, and bug fixes - Mention any breaking changes or required manual actions ``` - **Draft GitHub Release notes**: Prepare release highlights, detailed changelog, and thank-yous for community issue reporters. ### 2.3 User Guide & Documentation - **Update [`docs/USER_GUIDE.md`](file:///y:/docs/USER_GUIDE.md)**: Document any new features, configuration options, changed UI labels, or revised operational recommendations. - **Refresh screenshots**: If UI layouts or tabs were modified, capture new screenshots from live testlab nodes and update images in `docs/images/`. #### Screenshot Inventory & Reference Status All user guide screenshots should be captured in Unraid Dark Mode (`theme="black"`), using clean sample datasets (e.g. `bbpool/buddybackup/secure`), and without private IP addresses or sensitive credentials. | Screenshot ID | Location / Page | State / Description Captured | Theme / Mode | |:---|:---|:---|:---| | `screenshot_01_backups_overview.png` | **Backup and restore** | Top SSH key banner with Copy button, action toolbar, and 3 collapsed cards with status dots and telemetry badges. | Dark Mode | | `screenshot_02_backup_card_expanded.png` | **Backup and restore** | Expanded backup card showing 2-column layout, skip parent option, telemetry banner, and bottom actions. | Dark Mode | | `screenshot_03_generic_host_helper.png` | **Backup and restore** | Close-up of Destination column with `Remote (generic ZFS host)` selected, showing inline setup helper with curl command & Copy button. | Dark Mode | | `screenshot_04_restore_wizard.png` | **Backup and restore** | Modal popup of the Restore Snapshot Wizard showing the dataset/snapshot list and destination selection. | Dark Mode | | `screenshot_05_snapshots_page.png` | **Snapshot creation and pruning** | Sanoid configuration card showing hourly/daily/weekly retention inputs and the trigger backup dropdown. | Dark Mode | | `screenshot_06_buddys_backups.png` | **Buddy's Backups** | Incoming buddy card expanded showing telemetry banner, SSH key, destination parent dataset example, and retention fields. | Dark Mode | | `screenshot_07_advanced_settings.png` | **Advanced Settings** | Settings section showing timezone, alert thresholds, and security overrides. | Dark Mode | | `screenshot_08_log_viewer.png` | **Log** | Live log viewer streaming recent replication and connection test entries. | Dark Mode | | `screenshot_09_dashboard_tile.png` | **Unraid Dashboard** | BuddyBackup tile on the main Unraid dashboard showing task statuses and storage metrics. | Dark Mode | | `screenshot_10_truenas_replication_task.png` | **TrueNAS SCALE WebGUI** | Data Protection → Replication Task showing `Snapshot Retention Policy: None` and destination dataset path. | External (Optional) | - **Update [`README.md`](file:///y:/README.md)**: Keep feature summaries, requirements, and compatibility tables up to date. ### 2.4 Build Package & Synchronize MD5 Checksum - **Package `buddybackup.txz`**: Build the release archive from `src/`. Ensure owner is `root:root` and file permissions are preserved (using WSL tar): ```bash tar -C src -cJf buddybackup.txz . ``` - **Calculate & update MD5 in `buddybackup.plg`**: Calculate the MD5 hash of `buddybackup.txz` and update `pkgMD5` in [`buddybackup.plg`](file:///y:/buddybackup.plg): ```xml "> ``` - **Verify checksum match**: ```powershell $actualMd5 = (Get-FileHash -Path "buddybackup.txz" -Algorithm MD5).Hash.ToLower() Write-Host "Package MD5: $actualMd5" ``` Confirm that `buddybackup.plg` contains this exact hash string. ### 2.5 Commit Release Candidate to `dev` - **Review git diff**: Ensure only intended files (`buddybackup.plg`, `docs/`, `README.md`) are modified: ```powershell git status git diff ``` - **Commit release candidate**: ```bash git commit -am "Prepare YYYY.MM.DD release candidate" ``` *Note: A clean worktree is mandatory for Phase 3 so the release gate can build workspace artifacts and publish durable release history.* --- ## Phase 3: Automated Testlab Release Gate & Verification With the release candidate committed and version bumped, execute the comprehensive testlab matrix. ### 3.1 Automated Testlab Release Gate - **Run release gate in Execute mode**: ```powershell powershell -ExecutionPolicy Bypass -File ./testlab/scripts/run-release-gate.ps1 -LabConfig testlab/config/lab.local.json -MatrixProfile release-default -Execute ``` - **Verify preflight checks pass**: - Clean git worktree confirmed (no uncommitted or untracked changes). - Version bump confirmed (`buddybackup.plg` version > `previousReleaseVersion`). - **Verify all matrix scenarios pass**: - `base-setup-verify`: Plugin installed, zpool present, encrypted & unencrypted datasets active. - `fresh-install`: Clean install succeeds without emhttp warnings. - `upgrade-preserves-config`: Upgrading in-place from previous release retains backup jobs, SSH state, receiver mode, and advanced settings. - `backup-smoke` & `restore-smoke`: Bidirectional remote and local backups pass; snapshot listing and dataset restoration verified. - `post-reboot`: Nodes reboot cleanly; settings, datasets, and WebGUI authentication persist across reboot. - **Verify Result File & Release History**: - Verify run manifest stored in durable host storage: `%LOCALAPPDATA%\BuddyBackup\TestlabHistory//` - Verify public history summary generated/updated in [`testlab/release-history/README.md`](file:///y:/testlab/release-history/README.md), [`testlab/release-history/index.json`](file:///y:/testlab/release-history/index.json), and [`testlab/release-history/runs/.json`](file:///y:/testlab/release-history/runs/). ### 3.2 Backwards Compatibility - **Older Sender → Newer Receiver**: Verify an older BuddyBackup version can push backups to the candidate release without protocol or allowlist rejection. - **Newer Sender → Older Receiver**: Verify the candidate release can push backups to an older BuddyBackup receiver. - **Configuration Migration**: Verify configuration written by older releases loads seamlessly without loss of settings. ### 3.3 Generic Host & TrueNAS SCALE Verification - **Generic OpenZFS host smoke**: Run the generic smoke test against `nodeC`: ```powershell powershell -ExecutionPolicy Bypass -File ./testlab/scripts/run-generic-smoke.ps1 -LabConfig testlab/config/lab.local.json -Execute ``` - **TrueNAS SCALE validation**: If changes touch `generic_host_setup.sh`, allowlist scoping, sudo mode, or generic host UI, complete all checks in [`testlab/MANUAL-SCALE-CHECKLIST.md`](file:///y:/testlab/MANUAL-SCALE-CHECKLIST.md): - Setup command generation & execution on TrueNAS SCALE. - Persistent allowlist location verified (`/mnt//.buddybackup/`). - TrueNAS UI configuration (SSH service Auxiliary Parameters, user sudo commands). - Push smoke: Unraid → TrueNAS. - Replication smoke: TrueNAS SCALE native replication task → Unraid (Retention = None, Sudo = Disabled). - Teardown & grant change checks (`--revoke`, `--clean`). - Negative security checks (blocked commands, non-allowlisted datasets rejected). ### 3.4 WebGUI Theme & Visual Inspection - **Theme compatibility**: Inspect the BuddyBackup WebGUI under both Unraid themes: - **White (light) theme**: Verify contrast, table borders, status badges, and input text visibility. - **Black (dark) theme**: Verify no blinding white boxes, text readability, and icon rendering. - **Unraid OS version UI styling**: Verify rendering across Unraid 6.12.x and Unraid 7.x Dynamix layouts. - **Browser console**: Open browser developer tools; confirm zero JavaScript errors or 404 missing asset warnings. - **Interactive form actions**: - Test connection button on newly entered (unsaved) entries vs existing saved entries. - Snapshot creation and manual "Send backup now" button flows. - Restore wizard modal navigation and dataset selector dropdowns. ### 3.5 Commit Testlab Release History - **Commit testlab history updates**: Stage and commit the generated history files on `dev`: ```bash git add testlab/release-history/ git commit -m "Record testlab release gate history for YYYY.MM.DD" ``` --- ## Phase 4: Merge, Tag & GitHub Release Publishing ### 4.1 Merge `dev` to `main` - **Rebase or merge `dev` into `main`**: ```bash git checkout main git pull origin main git merge dev --ff-only # or clean merge commit git push origin main ``` ### 4.2 Git Tag Creation & Push - **Tag the release**: ```bash git tag -a YYYY.MM.DD -m "Release YYYY.MM.DD" git push origin YYYY.MM.DD ``` ### 4.3 GitHub Release Publishing - **Trigger workflow**: The tag push triggers [`.github/workflows/create_release.yml`](file:///y:/.github/workflows/create_release.yml), which drafts a release with `buddybackup.plg`. - **Upload `buddybackup.txz`**: Attach the built `buddybackup.txz` archive to the GitHub release draft. - **Publish release**: Paste the changelog into the release description and publish the release. --- ## Phase 5: Live In-The-Wild Sanity Check ### 5.1 Test Install from Public URL - **Install on a clean test Unraid server or testlab node**: ```bash plugin install https://raw.githubusercontent.com/Piratkopia13/unraid-buddybackup/refs/heads/main/buddybackup.plg ``` ### 5.2 Verify Live Installation - Confirm `buddybackup.plg` downloads without SSL or HTTP errors. - Confirm `buddybackup.txz` downloads and matches the `pkgMD5` hash. - Confirm package extracts cleanly with zero emhttp warnings or errors. - Confirm BuddyBackup appears immediately in Unraid's **Settings** menu and the dashboard panel loads. --- ## Release Process Reference & Acceptance Criteria | Step | Area | Tool / Command | Acceptance Criteria | | :--- | :--- | :--- | :--- | | 1 | Dead code, complexity & secrets | Static review & perl syntax | Zero unused code, no debug dumps, clean syntax, no PII | | 2 | Line endings (LF) & permissions (0755) | PowerShell inspection | Unix LF in `src/`, executable bits on shell/perl scripts | | 3 | TAP Unit Test Suite (`t/*.t`) | `run-unit-tests.ps1` | All unit & integration tests pass (7/7) | | 4 | Version bump, changelog & docs | `buddybackup.plg`, `USER_GUIDE.md` | Version updated, `` authored, docs synced | | 5 | Packaging & checksum sync | `tar`, `Get-FileHash` | `buddybackup.txz` built, `pkgMD5` matches in `.plg` | | 6 | Clean release candidate commit | `git commit` on `dev` | Worktree clean for release gate execution | | 7 | Testlab automated release gate | `run-release-gate.ps1 -Execute` | All matrix scenarios pass, history files written | | 8 | TrueNAS SCALE & generic smoke | `run-generic-smoke.ps1` | Raw receive & replication verify cleanly | | 9 | WebGUI Light & Dark theme review | Browser inspection | UI renders cleanly under both Unraid themes | | 10 | Commit testlab release history | `git commit` on `dev` | Test history recorded in repository | | 11 | Merge to `main` and push tag | `git merge dev` & `git tag` | `main` updated, tag pushed to GitHub | | 12 | GitHub release published | GitHub Releases | Release published with `.plg` & `.txz` assets | | 13 | Live test install from GitHub URL | `plugin install ` on Unraid | Clean install & emhttp registration on Unraid |