Compare commits

...

346 Commits

Author SHA1 Message Date
mokogitea-actions[bot] f56c1bfbd1 chore(version): pre-release bump to 02.58.05-dev [skip ci] 2026-07-06 01:17:22 +00:00
jmiller aeb9d18ccb Merge pull request 'fix: restore missing str_replace subject arg in MokoRestore standalone gen (#226)' (#228) from fix/mokorestore-str-replace-args into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 29s
2026-07-06 01:17:01 +00:00
mokogitea-actions[bot] 0a51ed75da chore(version): pre-release bump to 02.58.04-dev [skip ci]
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
2026-07-06 01:16:02 +00:00
jmiller 0ae9bfd93a fix: restore missing subject arg in MokoRestore str_replace (standalone gen)
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 30s
MokoRestore::generateStandaloneScript() rewrites the 'Backup Archive'
pre-check via str_replace(ORIG, REPL) but was missing the third
$php subject argument, so every standalone-mode backup fatally errored
with 'str_replace() expects at least 3 arguments, 2 given' at the
'Generating standalone restore.php...' step. The archive still finalized
and uploaded, but no restore.php was produced -- the underlying cause of
#226 (restore script missing on the remote).

Refs #226

Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
2026-07-05 20:15:30 -05:00
mokogitea-actions[bot] 1c0a87ca4a chore(version): pre-release bump to 02.58.03-dev [skip ci] 2026-07-06 00:40:33 +00:00
jmiller 2cb8527c25 Merge pull request 'fix(engine): check + log restore-script remote upload (fixes #226)' (#227) from fix/restore-script-upload-result into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 24s
2026-07-06 00:40:18 +00:00
mokogitea-actions[bot] 35febb8854 chore(version): pre-release bump to 02.58.02-dev [skip ci]
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
2026-07-06 00:39:57 +00:00
jmiller bf91611b97 fix(engine): check + log restore-script remote upload (no longer silent)
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 21s
The standalone restore script was uploaded to each remote with the result
discarded and nothing logged, so a failed second upload left the restore script
missing from the remote with no warning while the archive still recorded
'complete'. Capture the result: log success, and on failure set uploadFailed
(-> warning status) and log the reason.

Fixes #226

Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
2026-07-05 19:39:37 -05:00
mokogitea-actions[bot] 9bc0fc8ad8 chore(version): pre-release bump to 02.58.01-dev [skip ci] 2026-07-06 00:33:03 +00:00
jmiller e75a58709b Merge pull request 'chore(sync): cascade main -> dev' (#225) from main into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 43s
2026-07-06 00:32:12 +00:00
gitea-actions[bot] 8be1e332c6 chore(release): build 02.58.00 [skip ci]
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
2026-07-06 00:32:07 +00:00
jmiller ba91f74edc Merge pull request 'release: promote dev → main (installer + admin-menu + UI fixes)' (#224) from dev into main
Sync Workflows to Repos / sync (push) Has been skipped
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Cascade Main -> Dev / Cascade main -> dev (push) Successful in 9s
Universal: PR Check / Branch Policy (pull_request) Successful in 9s
Universal: PR Check / Secret Scan (pull_request) Successful in 29s
Universal: PR Check / Validate PR (pull_request) Failing after 54s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 1m31s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-07-06 00:30:29 +00:00
mokogitea-actions[bot] 387bfbdeda chore(version): pre-release bump to 02.57.13-dev [skip ci]
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Has been skipped
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 1m53s
2026-07-06 00:17:00 +00:00
jmiller f7d8d82a4e Merge pull request 'refactor(ui): modal padding via Bootstrap container, drop msbackup class' (#223) from fix/modal-container-padding into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 27s
2026-07-06 00:16:33 +00:00
mokogitea-actions[bot] 9e5a942800 chore(version): pre-release bump to 02.57.12-dev [skip ci]
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
2026-07-06 00:16:10 +00:00
jmiller dad3ce2db3 refactor(ui): modal padding via Bootstrap container, drop msbackup class
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 20s
Per feedback, wrap the destination modal content in a Bootstrap .container-fluid
and give that a 1rem frame in the WAM stylesheet, instead of a custom
.msbackup class on .modal-content. Inner header/body/footer drop their own
horizontal padding so the frame isn't doubled.

Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
2026-07-05 19:15:49 -05:00
mokogitea-actions[bot] 8325afb03a chore(version): pre-release bump to 02.57.11-dev [skip ci] 2026-07-06 00:06:23 +00:00
jmiller 662918db38 Merge pull request 'feat(ui): SFTP key file upload + msbackup modal padding frame' (#222) from fix/modal-msbackup-class into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 27s
2026-07-06 00:04:47 +00:00
jmiller 1ab99daaba feat(ui): SFTP key file upload; msbackup modal padding frame
Generic: Project CI / Lint & Validate (pull_request) Successful in 18s
Universal: PR Check / Branch Policy (pull_request) Successful in 3s
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 8s
Universal: PR Check / Validate PR (pull_request) Failing after 14s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 12s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Failing after 5s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
- Add/Edit Destination modal: SFTP key can now be UPLOADED as a file (read into
  the key textarea client-side via FileReader) instead of copy/paste; pasting
  still works.
- Give .modal-content a "msbackup" class with a 1rem padding frame — Bootstrap's
  .modal-content has no padding of its own, which made the modal feel cramped.
  Styling lives in the WAM stylesheet (media/.../admin.css), scoped to .msbackup.

Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
2026-07-05 19:04:05 -05:00
mokogitea-actions[bot] c84dcf2864 chore(version): pre-release bump to 02.57.10-dev [skip ci] 2026-07-05 23:59:02 +00:00
jmiller e1f5afb301 Merge pull request 'fix(plugin): pre-update backup notifies on success, not only failure' (#221) from fix/preupdate-notification into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 42s
2026-07-05 23:58:21 +00:00
mokogitea-actions[bot] dfd4e77ade chore(version): pre-release bump to 02.57.09-dev [skip ci]
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 3s
2026-07-05 23:58:13 +00:00
jmiller 1a1c81550c fix(plugin): pre-update backup notifies on success too, not only failure
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Universal: PR Check / Branch Policy (pull_request) Successful in 3s
Generic: Project CI / Lint & Validate (pull_request) Successful in 17s
Universal: PR Check / Secret Scan (pull_request) Successful in 12s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 44s
Universal: PR Check / Validate PR (pull_request) Failing after 1m5s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 1m13s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
runPreActionBackup() only enqueued a message when the backup failed, so a
successful pre-update backup produced no admin notification at all. Now it
surfaces every outcome via the BackupRunner status: complete -> success,
warning (archive made but remote upload failed) -> warning, fail -> error.

Refs #192

Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
2026-07-05 18:57:42 -05:00
mokogitea-actions[bot] 9571b3759a chore(version): pre-release bump to 02.57.08-dev [skip ci] 2026-07-05 23:49:26 +00:00
jmiller 115ccfb069 Merge pull request 'fix(ui): WAM-loaded CSS, per-destination keep-local, tidy destination modal' (#220) from fix/remote-modal-cleanup into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 28s
2026-07-05 23:49:04 +00:00
mokogitea-actions[bot] 2d538d3372 chore(version): pre-release bump to 02.57.07-dev [skip ci]
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
2026-07-05 23:48:51 +00:00
jmiller 97e8d0cbe9 fix(ui): WAM-loaded CSS, per-destination keep-local, tidy destination modal
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Secret Scan (pull_request) Successful in 9s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 25s
Generic: Project CI / Lint & Validate (pull_request) Successful in 12s
Universal: PR Check / Validate PR (pull_request) Failing after 47s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 54s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
- Move component admin CSS to the Joomla Web Asset Manager: new
  media/com_mokosuitebackup/css/admin.css + media/joomla.asset.json, a <media>
  entry in the manifest, and useStyle('com_mokosuitebackup.admin') in the
  profile edit view. Removes the inline <style> block (no more inline CSS).
- Remove the profile-level "Keep local copy" field/"Remote" fieldset from
  forms/profile.xml — it is now per remote destination (modal remoteKeepLocal).
- Clean up the Add/Edit Destination modal padding/margins (in admin.css).

Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
2026-07-05 18:48:33 -05:00
mokogitea-actions[bot] 8d5b33a74d chore(version): pre-release bump to 02.57.06-dev [skip ci] 2026-07-05 23:32:04 +00:00
jmiller 77bfaff8cd Merge pull request 'fix(installer): self-heal admin menu + alias collision + short-constant label' (#219) from fix/admin-menu-selfheal into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 26s
2026-07-05 23:31:41 +00:00
mokogitea-actions[bot] 1c420b2277 chore(version): pre-release bump to 02.57.05-dev [skip ci]
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
2026-07-05 23:31:24 +00:00
jmiller 2af2641712 fix(installer): self-heal admin menu; fix alias collision; short-constant label
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 22s
Fallout of the duplicate-component element bug:

- Preflight now runs removeOrphanedComponent() BEFORE the component install
  recreates its menu, so the orphan's "Backup" menu (alias "backup") no longer
  collides ("The alias backup is already being used by the Backup menu item").
- ensureSubmenuItems() recreates the top-level "Backup" menu when it is missing
  (via new createTopMenu()) instead of bailing out — so a failed install that
  deleted the parent menu no longer leaves Backup gone from the admin menu (which
  also broke the cPanel module and MokoSuiteClient component detection).
- The top-level menu label now uses the short constant COM_MOKOJOOMBACKUP_SHORT
  (manifest <menu> + enforced/normalized in the script).

Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
2026-07-05 18:31:06 -05:00
mokogitea-actions[bot] a3c7183374 chore(version): pre-release bump to 02.57.04-dev [skip ci] 2026-07-05 23:15:31 +00:00
jmiller 4f91d1e432 Merge pull request 'chore(sync): cascade main -> dev' (#212) from main into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 39s
2026-07-05 23:03:57 +00:00
jmiller 604412f82f Merge chore/normalize-docs: normalize doc/config refs
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Cascade Main -> Dev / Cascade main -> dev (push) Successful in 3s
Generic: Project CI / Lint & Validate (pull_request) Successful in 15s
Universal: PR Check / Secret Scan (pull_request) Successful in 11s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 15s
Universal: PR Check / Validate PR (pull_request) Failing after 50s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-07-05 22:50:52 +00:00
jmiller 94ff15c128 chore(docs): normalize refs — MokoStandards->org wiki, moko-platform->mokocli, residual MokoGitea/MokoSuite
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 34s
Non-workflow docs/config only (CLAUDE.md, README, branch-protection, ISSUE_TEMPLATE/config.yml,
ci-issue-reporter). Workflow files, manifest schema, and Makefile install paths left for the
forge-rebrand gate. Authored-by: Moko Consulting
2026-07-05 22:50:50 +00:00
mokogitea-actions[bot] a92f423767 chore(version): pre-release bump to 02.57.02-dev [skip ci] 2026-07-05 22:44:13 +00:00
jmiller ba2cda1385 Merge pull request 'fix(installer): drop legacy remote columns in PHP, not PREPARE-based SQL' (#218) from fix/sql-prepared-statement-protocol into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 21s
2026-07-05 22:43:53 +00:00
mokogitea-actions[bot] 72aeea6955 chore(version): pre-release bump to 02.57.01-dev [skip ci]
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 3s
2026-07-05 22:41:55 +00:00
jmiller 8a85370e32 fix(installer): drop legacy remote columns in PHP, not PREPARE-based SQL
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 34s
02.56.01.sql used PREPARE/EXECUTE/DEALLOCATE to conditionally drop the 26 legacy
remote_storage/ftp_*/sftp_*/gdrive_*/s3_* columns portably. Joomla's installer
rejects those statements on MySQL 8 (error 1295: "This command is not supported
in the prepared statement protocol yet"), aborting the whole component install
when updating from an old schema.

Neutralize 02.56.01.sql (now a no-op comment) and move the purge into
Pkg_MokoSuiteBackupInstallerScript::dropLegacyRemoteColumns(): gate on
INFORMATION_SCHEMA, then issue one plain ALTER dropping only the columns that
still exist — portable on MariaDB and MySQL 8, idempotent, non-fatal.

Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
2026-07-05 17:41:26 -05:00
gitea-actions[bot] ea91b49e50 chore(release): build 02.57.00 [skip ci] 2026-07-05 22:30:31 +00:00
jmiller 99d8e954bd Merge pull request 'feat: BackupRunner helper — unify backup run/status/notification' (#214) from feat/backup-runner-helper into main
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Universal: PR Check / Branch Policy (pull_request) Successful in 3s
Universal: PR Check / Secret Scan (pull_request) Successful in 10s
Cascade Main -> Dev / Cascade main -> dev (push) Successful in 9s
Universal: PR Check / Validate PR (pull_request) Failing after 15s
Generic: Project CI / Lint & Validate (pull_request) Successful in 55s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 59s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-07-05 22:29:38 +00:00
jmiller 28ca110d7b docs(changelog): add BackupRunner entry (#214)
Universal: PR Check / Branch Policy (pull_request) Failing after 4s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 7s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 11s
Universal: PR Check / Wiki Update Reminder (pull_request) Successful in 2s
Universal: PR Check / Require Docs Update (pull_request) Failing after 8s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 3s
Universal: PR Check / Secret Scan (pull_request) Successful in 11s
Branch Cleanup / Delete merged branch (pull_request) Successful in 4s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Failing after 15s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 15s
Generic: Project CI / Lint & Validate (pull_request) Successful in 1m3s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 51s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
2026-07-05 17:29:28 -05:00
jmiller 307067580c feat: BackupRunner helper — unify backup run/status/notification
Every non-interactive backup trigger used a slightly different path, so
final status and notification gating behaved inconsistently depending on
what started the backup (this is why pre-update backups did not gate
notifications the way "Backup Now" does).

Add src/Service/BackupRunner.php as the single synchronous entry point.
It delegates to BackupEngine (which already sends notifications gated by
the profile's notify_on_success/notify_on_failure and applies retention —
so there is exactly ONE notification layer), and normalises the result,
including the real complete/warning/fail status the engine records but did
not return. BackupRunner self-loads BackupEngine so callers require one file.

Routed through BackupRunner:
- plg_system  runPreActionBackup() (preaction) + web-cron handler (webcron)
- plg_content triggerAutoBackup() (pre-install)
- plg_task    scheduled task run
- plg_console RunCommand (cli)

The dashboard AJAX/stepped "Backup Now" flow is unchanged (it is the
interactive equivalent). The installer progress popup is deferred — the
installer request cannot drive the AJAX modal (TODO(#196) noted in code).

php -l clean on all changed files.

Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
2026-07-05 17:28:59 -05:00
jmiller 7f5f041588 Merge pull request 'fix(release): idempotent changelog promote (no duplicate version headers)' (#217) from fix/changelog-promote-idempotent into main
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Secret Scan (pull_request) Successful in 8s
Cascade Main -> Dev / Cascade main -> dev (push) Successful in 6s
Universal: PR Check / Validate PR (pull_request) Failing after 14s
Sync Workflows to Repos / sync (push) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 14s
Generic: Project CI / Lint & Validate (pull_request) Successful in 1m6s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-07-05 22:28:19 +00:00
jmiller 129be7ef9d fix(release): idempotent changelog promote + dedupe 02.56.11 header
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Wiki Update Reminder (pull_request) Successful in 2s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 4s
Universal: PR Check / Require Docs Update (pull_request) Failing after 5s
Generic: Project CI / Lint & Validate (pull_request) Successful in 11s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 2s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 9s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 35s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 1m13s
Universal: PR Check / Validate PR (pull_request) Failing after 1m11s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 1m22s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
Guard the promote so it only inserts a version header when absent (stops the
empty duplicate headers each build was appending), and remove the duplicate
02.56.11 header the non-idempotent promote just created.

Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
2026-07-05 17:28:08 -05:00
jmiller 14392de078 Merge pull request 'docs(changelog): backfill 02.56.07 + 02.56.08 (shipped with empty changelogs)' (#215) from fix/changelog-backfill into main
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 10s
Generic: Project CI / Lint & Validate (pull_request) Successful in 15s
Universal: PR Check / Validate PR (pull_request) Failing after 13s
Cascade Main -> Dev / Cascade main -> dev (push) Successful in 5s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 14s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-07-05 22:26:17 +00:00
jmiller 8bdadb68c2 docs(changelog): backfill 02.56.07/08 + dedupe blank duplicate headers
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Wiki Update Reminder (pull_request) Successful in 1s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 5s
Universal: PR Check / Require Docs Update (pull_request) Failing after 5s
Generic: Repo Health / Access control (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 6s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 12s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 31s
Generic: Project CI / Lint & Validate (pull_request) Successful in 52s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 56s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 58s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
2026-07-05 17:26:05 -05:00
gitea-actions[bot] bcc4054ced chore: promote changelog [Unreleased] → [02.56.11]
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 9s
Generic: Project CI / Lint & Validate (pull_request) Successful in 13s
Cascade Main -> Dev / Cascade main -> dev (push) Successful in 3s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 10s
Universal: PR Check / Validate PR (pull_request) Failing after 33s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-07-05 22:23:35 +00:00
gitea-actions[bot] 0cba7f81e8 chore(release): build 02.56.11 [skip ci] 2026-07-05 22:23:26 +00:00
jmiller 2688ea352b Merge pull request 'fix(installer): self-heal orphaned com_component-mokosuitebackup on update' (#216) from fix/orphan-component-cleanup into main
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Cascade Main -> Dev / Cascade main -> dev (push) Successful in 4s
Sync Workflows to Repos / sync (push) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 7s
Generic: Project CI / Lint & Validate (pull_request) Successful in 49s
Universal: PR Check / Validate PR (pull_request) Failing after 46s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Failing after 58s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-07-05 22:23:08 +00:00
mokogitea-actions[bot] 39d94a31d6 chore(version): pre-release bump to 02.56.11-dev [skip ci]
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 31s
2026-07-05 22:14:22 +00:00
jmiller 1029e40908 fix(installer): self-heal orphaned com_component-mokosuitebackup on update
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 7s
Generic: Project CI / Lint & Validate (pull_request) Successful in 16s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Wiki Update Reminder (pull_request) Successful in 3s
Universal: PR Check / Require Docs Update (pull_request) Failing after 7s
Universal: PR Check / Secret Scan (pull_request) Successful in 9s
Universal: PR Check / Validate PR (pull_request) Failing after 13s
Generic: Repo Health / Access control (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 52s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 50s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 29s
Universal: Build & Release / Promote to RC (pull_request) Failing after 15s
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
The old "Type - Name" component <name> made Joomla register a duplicate
component under element com_component-mokosuitebackup (its own extension row,
admin menu, schema rows and administrator/ folder), orphaning the real
com_mokosuitebackup on the old version. The manifest fix (#213) prevents new
occurrences; this reconciles already-affected sites automatically.

Package postflight now removes any component whose element matches
%component%mokosuitebackup% (excluding com_mokosuitebackup): deletes its
#__menu, #__schemas and #__update_sites_extensions rows, the #__extensions
record, and the stray admin folder. Idempotent and non-fatal.

Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
2026-07-05 17:11:51 -05:00
gitea-actions[bot] ec3094385f chore: promote changelog [Unreleased] → [02.56.08]
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Universal: PR Check / Branch Policy (pull_request) Successful in 3s
Universal: PR Check / Secret Scan (pull_request) Successful in 8s
Cascade Main -> Dev / Cascade main -> dev (push) Successful in 4s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 17s
Generic: Project CI / Lint & Validate (pull_request) Successful in 1m17s
Universal: PR Check / Validate PR (pull_request) Failing after 1m13s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-07-05 22:02:08 +00:00
gitea-actions[bot] 4a2bb1b19d chore(release): build 02.56.08 [skip ci] 2026-07-05 22:01:48 +00:00
jmiller 3c5ad43e97 Merge pull request 'fix(manifest): component &lt;name&gt; must be element-safe (com_mokosuitebackup)' (#213) from fix/component-element-name into main
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 8s
Generic: Project CI / Lint & Validate (pull_request) Successful in 15s
Cascade Main -> Dev / Cascade main -> dev (push) Successful in 5s
Universal: PR Check / Validate PR (pull_request) Failing after 14s
Sync Workflows to Repos / sync (push) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 14s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-07-05 22:01:17 +00:00
mokogitea-actions[bot] f92e5227dc chore(version): pre-release bump to 02.56.08-dev [skip ci]
Branch Cleanup / Delete merged branch (pull_request) Successful in 3s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 53s
2026-07-05 21:58:57 +00:00
jmiller 9db54ac60c fix(manifest): component <name> must be element-safe (com_mokosuitebackup)
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 34s
The "Type - Name" convention (commit d155958) set the component <name> to
"Component - MokoSuiteBackup". Joomla derives a component's element from its
<name> (com_ + sanitized name), so this produced element
`com_component-mokosuitebackup` instead of `com_mokosuitebackup`. On update,
Joomla registered a NEW component (new element + folder) at the current
version and orphaned the real `com_mokosuitebackup` at its old version — which
is what `?option=com_mokosuitebackup` and the admin menu still load. Net
effect: the component appears "stuck" on the old version with the old UI.

Revert the component <name> to "MokoSuiteBackup" (-> com_mokosuitebackup) and
document why the display convention must not be applied to a component's
<name>. Packages are exempt (they use <packagename>); plugins/modules are
exempt (<name> is only a display label there).

Refs #171-area remote tab reports; fixes the duplicate-component registration.

Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
2026-07-05 16:58:37 -05:00
jmiller 0c7c3552ed chore: sync workflow-sync-trigger.yml from Template-Generic [skip ci] 2026-07-05 21:49:42 +00:00
jmiller 351321161a chore: sync version-set.yml from Template-Generic [skip ci] 2026-07-05 21:49:40 +00:00
jmiller d2cc234fce chore: sync repo-health.yml from Template-Generic [skip ci] 2026-07-05 21:49:37 +00:00
jmiller 2389df8670 chore: sync rc-revert.yml from Template-Generic [skip ci] 2026-07-05 21:49:34 +00:00
jmiller 55f29498b0 chore: sync pre-release.yml from Template-Generic [skip ci] 2026-07-05 21:49:31 +00:00
jmiller a5397c0f16 chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-05 21:49:28 +00:00
jmiller c0792a6ba0 chore: sync notify.yml from Template-Generic [skip ci] 2026-07-05 21:49:26 +00:00
jmiller 7a3f0f914e chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-07-05 21:49:24 +00:00
jmiller cc7f18ae45 chore: sync gitleaks.yml from Template-Generic [skip ci] 2026-07-05 21:49:22 +00:00
jmiller 4cf8f8243d chore: sync cleanup.yml from Template-Generic [skip ci] 2026-07-05 21:49:20 +00:00
jmiller efb28fa386 chore: sync ci-issue-reporter.yml from Template-Generic [skip ci] 2026-07-05 21:49:17 +00:00
jmiller 68043c9a37 chore: sync ci-generic.yml from Template-Generic [skip ci] 2026-07-05 21:49:15 +00:00
jmiller e5558fad26 chore: sync cascade-dev.yml from Template-Generic [skip ci] 2026-07-05 21:49:12 +00:00
jmiller 60c5c00333 chore: sync branch-cleanup.yml from Template-Generic [skip ci] 2026-07-05 21:49:10 +00:00
jmiller f9169fd9f7 chore: sync auto-release.yml from Template-Generic [skip ci] 2026-07-05 21:49:07 +00:00
jmiller d69db6fac3 chore: sync auto-bump.yml from Template-Generic [skip ci] 2026-07-05 21:49:05 +00:00
gitea-actions[bot] 1f7c2ef1ba chore: promote changelog [Unreleased] → [02.56.07]
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 7s
Generic: Project CI / Lint & Validate (pull_request) Successful in 12s
Cascade Main -> Dev / Cascade main -> dev (push) Successful in 4s
Universal: PR Check / Validate PR (pull_request) Failing after 12s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 11s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-07-05 21:34:17 +00:00
gitea-actions[bot] 24d7dc0064 chore(release): build 02.56.07 [skip ci] 2026-07-05 21:34:06 +00:00
jmiller f4bc1d128c Merge pull request 'fix: security + data-integrity fixes (P0/P1)' (#211) from fix/security-integrity-p0p1 into main
Sync Workflows to Repos / sync (push) Has been skipped
Cascade Main -> Dev / Cascade main -> dev (push) Successful in 5s
Universal: PR Check / Require Docs Update (pull_request) Has been skipped
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Wiki Update Reminder (pull_request) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 5s
Generic: Project CI / Lint & Validate (pull_request) Successful in 49s
Universal: PR Check / Validate PR (pull_request) Failing after 48s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 54s
Generic: Project CI / Tests (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-07-05 21:33:49 +00:00
gitea-actions[bot] 6ab31c12be chore(version): pre-release bump to 02.56.07-dev [skip ci]
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 32s
2026-07-05 21:33:32 +00:00
jmiller 99b844e04a fix: security + data-integrity fixes (P0/P1)
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 6s
Universal: PR Check / Wiki Update Reminder (pull_request) Successful in 2s
Universal: PR Check / Require Docs Update (pull_request) Failing after 8s
Universal: PR Check / Secret Scan (pull_request) Successful in 9s
Generic: Repo Health / Access control (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Failing after 13s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 12s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 28s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Generic: Project CI / Lint & Validate (pull_request) Successful in 46s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 50s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
Security (P0):
- #169 mask FTP password in AjaxController maskSecrets()/mergeExistingSecrets()
- #187 stop leaking absolute_path in API item view (JsonapiView)
- #182 SftpUploader StrictHostKeyChecking=no -> accept-new (MITM)

Data integrity / correctness (P1):
- #179 DatabaseDumper: real newline after DROP TABLE (was literal backslash-n)
- #180 profile-picker forms ORDER BY id (the 'ordering' column is dropped on
  upgraded sites, breaking the query) — run_profile.xml + plg_content xml
- #181 uninstall.mysql.sql: add missing DROP for snapshots table
- #184 CLI snapshot delete uses data_file column (file_path does not exist,
  so snapshot files were never deleted)
- #186 remove duplicate pre-update backup: content plugin no longer subscribes
  to onExtensionBeforeUpdate (owned by the system plugin); keeps pre-install
- #188 DatabaseImporter now collects non-fatal statement errors
  (getErrors()/hasErrors()) so restores are no longer silent and callers can
  surface a warning status

Also folds in the .mokogitea/CLAUDE.md mokoplatform -> mokocli fix (stale repo
name after the rename).

Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
2026-07-05 16:32:56 -05:00
jmiller 75bbb55e29 chore: sync workflow-sync-trigger.yml from Template-Generic [skip ci] 2026-07-05 21:10:07 +00:00
jmiller 11b0ea3c21 chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-05 21:10:04 +00:00
jmiller bcb4368bd1 chore: sync version-set.yml from Template-Generic [skip ci] 2026-07-05 20:46:36 +00:00
jmiller 8ac3bedff3 chore: sync sync-on-merge.yml from Template-Generic [skip ci] 2026-07-05 20:46:35 +00:00
jmiller 4ab9ab3806 chore: sync repo-health.yml from Template-Generic [skip ci] 2026-07-05 20:46:33 +00:00
jmiller 4740a09d79 chore: sync rc-revert.yml from Template-Generic [skip ci] 2026-07-05 20:46:31 +00:00
jmiller 26121e3628 chore: sync pre-release.yml from Template-Generic [skip ci] 2026-07-05 20:46:29 +00:00
jmiller 478adfcde8 chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-05 20:46:27 +00:00
jmiller f4b6e23d58 chore: sync gitleaks.yml from Template-Generic [skip ci] 2026-07-05 20:46:25 +00:00
jmiller af215482bd chore: sync ci-issue-reporter.yml from Template-Generic [skip ci] 2026-07-05 20:46:22 +00:00
jmiller cd721d450e chore: sync cascade-dev.yml from Template-Generic [skip ci] 2026-07-05 20:46:20 +00:00
jmiller b38ddb5b62 chore: sync branch-cleanup.yml from Template-Generic [skip ci] 2026-07-05 20:46:18 +00:00
jmiller 6e66de4c65 chore: sync auto-release.yml from Template-Generic [skip ci] 2026-07-05 20:46:16 +00:00
jmiller b2d35bc9b3 chore: sync auto-bump.yml from Template-Generic [skip ci] 2026-07-05 20:46:14 +00:00
jmiller d780e10a2f chore: sync notify.yml from Template-Generic [skip ci] 2026-07-05 00:06:25 +00:00
jmiller b2770df80f chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-07-05 00:06:23 +00:00
jmiller 1c643b097f chore: sync cleanup.yml from Template-Generic [skip ci] 2026-07-05 00:06:21 +00:00
gitea-actions[bot] ee293e8038 chore: promote changelog [Unreleased] → [02.56.05] 2026-07-05 00:03:28 +00:00
gitea-actions[bot] 8e3e473426 chore(release): build 02.56.05 [skip ci] 2026-07-05 00:03:11 +00:00
jmiller 2a7fb74ef9 Merge pull request 'fix(sql): purge stranded legacy remote-storage columns (MySQL 8 safe)' (#210) from fix/purge-legacy-remote-columns into main
Sync Workflows to Repos / sync (push) Failing after 3s
2026-07-05 00:02:28 +00:00
gitea-actions[bot] c7a57116a7 chore(version): pre-release bump to 02.56.05-dev [skip ci]
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 3s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 44s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Successful in 9m41s
2026-07-05 00:02:14 +00:00
jmiller 6a62868881 fix(sql): purge stranded legacy remote-storage columns (MySQL 8 safe)
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 8s
Universal: PR Check / Secret Scan (pull_request) Successful in 9s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 34s
Universal: PR Check / Validate PR (pull_request) Failing after 15s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 2s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 15s
Universal: Build & Release / Promote to RC (pull_request) Failing after 17s
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Generic: Project CI / Lint & Validate (pull_request) Successful in 1m2s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 1m6s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
02.52.25.sql used `DROP COLUMN IF EXISTS` (MariaDB-only), which errors on
Oracle MySQL 8.x — so on MySQL 8 installs the 26 legacy remote_storage/ftp_*/
sftp_*/gdrive_*/s3_* columns were never dropped, yet Joomla recorded the schema
as applied (confirmed on suite.dev: MySQL 8.0.41, all 26 columns still present,
0 profiles with legacy remote data).

New 02.56.01 migration removes them portably: an INFORMATION_SCHEMA-gated
prepared-statement ALTER that drops all 26 columns where present (plain
DROP COLUMN, valid on MySQL 8 + MariaDB) and is a no-op where already gone
(so it's safe on already-migrated installs too). Validated non-destructively
against suite.dev (gate=1, ALTER PREPAREs cleanly).

Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
2026-07-04 19:01:50 -05:00
jmiller 0926e82465 chore: sync auto-release.yml from Template-Generic [skip ci] 2026-07-04 23:28:45 +00:00
gitea-actions[bot] e37a52df4e chore: promote changelog [Unreleased] → [02.56.00] 2026-07-04 22:01:21 +00:00
gitea-actions[bot] a7611d17d9 chore(release): build 02.56.00 [skip ci] 2026-07-04 22:01:12 +00:00
jmiller 183b2d2d6f Merge pull request 'fix: remote destinations tab broken (Add Destination + stuck loading)' (#208) from fix/remote-destinations-modal into main 2026-07-04 22:00:44 +00:00
jmiller 4ca9e23630 fix(profile): remote destinations tab broken — lazy-init Bootstrap modal
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 7s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 11s
Universal: PR Check / Branch Policy (pull_request) Successful in 3s
Universal: PR Check / Secret Scan (pull_request) Successful in 10s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Failing after 14s
Generic: Repo Health / Access control (pull_request) Successful in 3s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 14s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 39s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Generic: Project CI / Lint & Validate (pull_request) Successful in 45s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
The remote destinations table stayed stuck at "Loading…" and the "Add
Destination" button did nothing. Root cause: the profile-edit DOMContentLoaded
handler instantiated the Bootstrap modal eagerly at the top
(`bootstrap.Modal.getOrCreateInstance`). In Joomla 6, Bootstrap loads as a
deferred ES module, so `bootstrap` is undefined at DOMContentLoaded — the
reference threw a ReferenceError that aborted the entire handler, so
loadRemotes() never ran and the Add button was never bound. (The purge and
stepped-backup modals worked because they resolve the modal lazily inside
click handlers.)

- Resolve the modal lazily via getModal() at click-time (matches the working modals)
- Explicitly load the bootstrap.modal web asset so window.bootstrap.Modal is registered

Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
2026-07-04 17:00:15 -05:00
jmiller d0ce09abf0 chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-07-04 21:52:23 +00:00
gitea-actions[bot] 1dde736225 chore: promote changelog [Unreleased] → [02.56.00] 2026-07-04 21:51:30 +00:00
gitea-actions[bot] 6074aa55ae chore(release): build 02.56.00 [skip ci] 2026-07-04 21:51:20 +00:00
jmiller 939964bff9 Merge pull request 'chore: remove stray root services/provider.php' (#207) from chore/remove-stray-provider into main
Sync Workflows to Repos / sync (push) Failing after 3s
2026-07-04 21:50:47 +00:00
gitea-actions[bot] 5363a85b92 chore(version): pre-release bump to 02.55.03-dev [skip ci]
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 30s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Successful in 4m44s
2026-07-04 21:50:36 +00:00
jmiller c12d207a96 chore: remove stray root services/provider.php
Universal: PR Check / Branch Policy (pull_request) Successful in 3s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 6s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 12s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 3s
Universal: PR Check / Secret Scan (pull_request) Successful in 11s
Generic: Project CI / Lint & Validate (pull_request) Successful in 18s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 34s
Universal: Build & Release / Promote to RC (pull_request) Failing after 12s
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Failing after 41s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 45s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
The canonical webservices provider lives in
source/packages/plg_webservices_mokosuitebackup/services/provider.php.
This root-level copy is an orphaned duplicate — nothing references it and
it is not part of any packaged extension. Recovered from a stash of
previously-set-aside cleanup.

Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
2026-07-04 16:50:11 -05:00
jmiller ee11ec8ef7 Merge pull request 'docs(changelog): document 02.53.00–02.55.00 releases' (#205) from docs/changelog-update into main 2026-07-04 20:54:58 +00:00
jmiller 0c9d9a6336 docs(changelog): document 02.53.00–02.55.00 and pending remote-storage removal [skip ci]
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 3s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Successful in 3m24s
Populate the empty CI-generated version sections and dedupe headers:
- 02.53.00: short-name branding
- 02.54.00: per-profile retention enforcement, Purge button fix, manifest naming convention
- 02.55.00: installer licensing + install-completion pattern
- Unreleased: legacy single-remote storage removal (#204)

Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
2026-07-04 15:54:17 -05:00
jmiller 882cb2c48c chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-07-04 20:40:14 +00:00
gitea-actions[bot] 0578f2deed chore: promote changelog [Unreleased] → [02.55.00] 2026-07-04 20:37:49 +00:00
gitea-actions[bot] eecb8c8c72 chore(release): build 02.55.00 [skip ci] 2026-07-04 20:37:39 +00:00
jmiller f0fa645e51 Merge pull request 'Remove legacy single-remote storage in favor of remotes table' (#204) from fix/remote-storage-cleanup into main
Sync Workflows to Repos / sync (push) Failing after 4s
2026-07-04 20:36:31 +00:00
jmiller 6f7dc6766d Merge CI version bump (superseded by main's 02.55.00)
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 7s
Universal: PR Check / Secret Scan (pull_request) Successful in 12s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 41s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 3s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 3s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Generic: Project CI / Lint & Validate (pull_request) Successful in 1m11s
Universal: PR Check / Validate PR (pull_request) Failing after 1m5s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 1m14s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 1m8s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 41s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Successful in 8m24s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
2026-07-04 15:36:16 -05:00
jmiller 6cef8fa9f7 Merge remote-tracking branch 'origin/main' into fix/remote-storage-cleanup
# Conflicts:
#	SECURITY.md
#	source/packages/MokoSuiteClient
#	source/packages/com_mokosuitebackup/mokosuitebackup.xml
#	source/packages/mod_mokosuitebackup_cpanel/mod_mokosuitebackup_cpanel.xml
#	source/packages/plg_actionlog_mokosuitebackup/mokosuitebackup.xml
#	source/packages/plg_console_mokosuitebackup/mokosuitebackup.xml
#	source/packages/plg_content_mokosuitebackup/mokosuitebackup.xml
#	source/packages/plg_quickicon_mokosuitebackup/mokosuitebackup.xml
#	source/packages/plg_system_mokosuitebackup/mokosuitebackup.xml
#	source/packages/plg_task_mokosuitebackup/mokosuitebackup.xml
#	source/packages/plg_webservices_mokosuitebackup/mokosuitebackup.xml
#	source/pkg_mokosuitebackup.xml
#	source/script.php
2026-07-04 15:34:41 -05:00
jmiller 278c572e0f chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-07-04 20:28:29 +00:00
gitea-actions[bot] 5615468042 chore: promote changelog [Unreleased] → [02.55.00] 2026-07-04 20:28:12 +00:00
gitea-actions[bot] 4dc8bc6912 chore(release): build 02.55.00 [skip ci] 2026-07-04 20:28:01 +00:00
jmiller 23fa4884bd Merge pull request 'Apply standard licensing + install-completion installer script pattern' (#202) from chore/installer-script-template into main 2026-07-04 20:27:26 +00:00
gitea-actions[bot] 772f2b75a1 chore(release): build 02.54.00 [skip ci] 2026-07-04 20:27:20 +00:00
jmiller 1758694893 fix(installer): apply standard licensing + install-completion script pattern
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 6s
Universal: PR Check / Secret Scan (pull_request) Successful in 7s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 11s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Failing after 6s
Generic: Repo Health / Access control (pull_request) Successful in 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Generic: Project CI / Lint & Validate (pull_request) Successful in 45s
Universal: PR Check / Validate PR (pull_request) Failing after 40s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 49s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 31s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Successful in 3m0s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
Adopts the Template-Joomla package-script pattern for download-key handling
and post-install messaging, while preserving all MokoSuiteBackup-specific
postflight steps (plugins, webcron secret, scheduled task, submenus,
client_id fix, icon sync, backup_dir migration).

- preflight (update): backupDownloadKey() caches the bare dlid value
- postflight (update): restoreDownloadKey() re-writes extra_query as dlid=<key>
- postflight (install): installSuccessful() + warnMissingLicenseKey()
- postflight (update): installSuccessful()
- License nag now runs on install only (a fresh install never has a key),
  removing the previous always-run "is a key present?" guard
- Licensing methods log via Joomla\CMS\Log\Log instead of error_log
2026-07-04 15:27:05 -05:00
jmiller 2de2c5f917 Merge pull request 'Enforce per-profile retention and repair Purge Old Backups button' (#203) from fix/backup-retention-purge into main 2026-07-04 20:26:20 +00:00
jmiller 5c5af532bb chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-04 20:26:05 +00:00
jmiller 03bf5dff7b chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-07-04 20:26:04 +00:00
jmiller 10248b284a fix: enforce per-profile retention and repair Purge Old Backups button
Universal: PR Check / Branch Policy (pull_request) Failing after 2s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 5s
Generic: Project CI / Lint & Validate (pull_request) Successful in 12s
Universal: PR Check / Secret Scan (pull_request) Successful in 6s
Universal: PR Check / Validate PR (pull_request) Failing after 4s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 2s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 9s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 27s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 39s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 30s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Successful in 4m0s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
Two related backup-management fixes.

Retention (records/days to keep):
- The retention fieldset was defined in profile.xml but never rendered
  in the profile editor, so retention_days/retention_count were invisible.
  Render the retention fieldset on the Archive tab.
- retention_days/retention_count were read by nothing, so they pruned no
  backups. Add RetentionManager::prune(), called from completeRecord() in
  both BackupEngine and SteppedBackupEngine after a backup finishes.
  Policy: delete a completed/warning backup when EITHER it is older than
  retention_days OR it falls outside the newest retention_count copies
  (0 = unlimited for that rule). Deleting a record also removes its
  archive and log file.
- Correct misleading language/schema text ("use global default" — no such
  global backup-retention setting exists) to "0 = unlimited".

Purge Old Backups button:
- The modal only opened via a fragile selector match on the toolbar
  button's inline onclick, which Joomla 6's Atum toolbar does not render,
  so the button did nothing. Wrap Joomla.submitbutton to open the modal
  for the backups.purgeModal task, keeping the selector as a fallback.
2026-07-04 15:25:43 -05:00
gitea-actions[bot] 4b2bb8b655 chore: promote changelog [Unreleased] → [02.54.00] 2026-07-04 20:25:31 +00:00
gitea-actions[bot] 2e5b57fe5d chore(release): build 02.54.00 [skip ci] 2026-07-04 20:25:20 +00:00
jmiller bdbbe74021 Merge pull request 'Hardcode manifest names/descriptions and enforce Type - Name convention' (#201) from chore/manifest-naming-convention into main 2026-07-04 20:24:46 +00:00
jmiller d155958be3 chore(manifests): hardcode names/descriptions and enforce Type - Name convention
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 6s
Generic: Project CI / Lint & Validate (pull_request) Successful in 11s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 8s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 8s
Generic: Repo Health / Access control (pull_request) Successful in 2s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 28s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 45s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 31s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Successful in 4m23s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
Per the package-XML convention, manifests must not use language strings for
titles/descriptions, and <name> must follow "Type - Name".

- Component <name> "MokoSuiteBackup" → "Component - MokoSuiteBackup"
- Module <name> "mod_mokosuitebackup_cpanel" → "Module - MokoSuiteBackup - cPanel"
- Hardcode every <description> (pkg, com, mod, all 7 plugins) with the literal
  text previously stored in the *_DESCRIPTION language constants
- Hardcode the component admin submenu titles (Dashboard, Backup Records,
  Content Snapshots, Backup Profiles)

Plugin <name> values already followed the Group - Name format and are
unchanged. All manifests validated as well-formed XML.
2026-07-04 15:24:18 -05:00
jmiller 0df6008a3b chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-04 20:23:20 +00:00
jmiller 145155d06e chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-07-04 20:23:18 +00:00
jmiller 84f37a8b51 chore: sync ci-generic.yml from Template-Generic [skip ci] 2026-07-04 20:23:16 +00:00
gitea-actions[bot] 6ff350fb1c chore: promote changelog [Unreleased] → [02.53.00] 2026-07-04 20:21:10 +00:00
gitea-actions[bot] c492d30b1c chore(release): build 02.53.00 [skip ci] 2026-07-04 20:20:57 +00:00
jmiller 23360f4cbc Merge pull request 'Add COM_MOKOJOOMBACKUP_SHORT and apply short name to views and admin menu' (#200) from chore/short-name-branding into main
Sync Workflows to Repos / sync (push) Failing after 2s
2026-07-04 20:20:37 +00:00
gitea-actions[bot] d3e3fd25e7 chore(version): pre-release bump to 02.52.30-dev [skip ci] 2026-07-04 20:18:21 +00:00
jmiller 46daabc34f fix(remote-cleanup): resolve dropped-column references found in review
Universal: PR Check / Branch Policy (pull_request) Failing after 1s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 6s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 2s
Universal: PR Check / Secret Scan (pull_request) Successful in 10s
Generic: Project CI / Lint & Validate (pull_request) Successful in 13s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 27s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 40s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 41s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
Follow-up to the legacy remote-storage removal — three consumers still
referenced columns this branch drops:

- 02.52.25.sql: use plain DROP COLUMN instead of DROP COLUMN IF EXISTS.
  IF EXISTS on DROP COLUMN is a MariaDB-only extension and errors on
  Oracle MySQL 8.x (which Joomla also supports); the columns always exist
  here, so the guard is unnecessary and the migration is now portable.
- AkeebaImporter::mapToMokoProfile(): stop inserting the 19 dropped
  remote_storage/ftp_*/gdrive_*/s3_* columns (would fatal with "Unknown
  column" on Akeeba import). Remote settings now live in the remotes
  table and are re-added on the profile Remote tab after import.
- AjaxController::browseSftpDir() + SftpPathField: remove. These were the
  legacy single-SFTP path picker, orphaned when the SftpPath form field
  was removed; they read now-dropped sftp_* columns.

Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
2026-07-04 15:17:54 -05:00
jmiller ece864329e chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-04 19:39:08 +00:00
jmiller 6cf34ea2ed chore: sync ci-generic.yml from Template-Generic [skip ci] 2026-07-04 19:39:06 +00:00
jmiller 1ee5e6ba9b chore: sync branch-cleanup.yml from Template-Generic [skip ci] 2026-07-04 19:39:05 +00:00
gitea-actions[bot] 1be16af5a4 chore(version): pre-release bump to 02.52.27-dev [skip ci]
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 35s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Successful in 5m7s
2026-07-04 19:21:24 +00:00
jmiller a808789acb feat: add COM_MOKOJOOMBACKUP_SHORT and apply short name to views and admin menu
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 23s
- Add COM_MOKOJOOMBACKUP_SHORT="Backup" to the component .ini and .sys.ini
  (en-GB + en-US) so both view titles and the admin sidebar menu resolve it.
- Prefix every admin view's toolbar title with the short brand via the
  constant (e.g. "Backup: Dashboard", "Backup: Records"), and tighten the
  view title strings that redundantly led with "Backup"/"MokoSuiteBackup".
- Admin sidebar top-level menu now shows the short name. Hardcoded as
  "Backup" in the manifest per the package-xml convention (no language
  strings in package XML).
2026-07-04 14:20:54 -05:00
jmiller 406b666486 chore: sync sync-on-merge.yml from Template-Generic [skip ci] 2026-07-04 19:06:42 +00:00
jmiller 77d93602d6 chore: sync pre-release.yml from Template-Generic [skip ci] 2026-07-04 19:06:41 +00:00
jmiller c5f4daa2e6 chore: sync pr-check.yml from Template-Generic [skip ci] 2026-07-04 19:06:40 +00:00
jmiller caaedfdff5 chore: sync notify.yml from Template-Generic [skip ci] 2026-07-04 19:06:39 +00:00
jmiller 6792688740 chore: sync cleanup.yml from Template-Generic [skip ci] 2026-07-04 19:06:38 +00:00
jmiller 318b1469e3 chore: sync ci-generic.yml from Template-Generic [skip ci] 2026-07-04 19:06:37 +00:00
jmiller b6b101be3a chore: sync auto-release.yml from Template-Generic [skip ci] 2026-07-04 19:06:36 +00:00
gitea-actions[bot] 5d4662342f chore(version): pre-release bump to 02.52.25-dev [skip ci] 2026-07-04 18:23:15 +00:00
jmiller 68605ffc05 refactor(remote): remove legacy single-remote storage in favor of remotes table
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 25s
Drops the per-profile remote_storage column and all legacy FTP/SFTP/S3/
Google Drive credential columns. Remote destinations are now sourced
exclusively from #__mokosuitebackup_remotes (multi-remote), which is
created at install time — so the backward-compat fallback branches in
BackupEngine, SteppedBackupEngine and loadRemoteDestinations are removed.

- sql: drop 26 legacy columns (install.mysql.sql + 02.52.25.sql migration)
- forms/profile.xml: remove legacy remote fields and ftp/gdrive/s3 fieldsets
- tmpl/profile/edit.php: drop legacy UI, add save-first prompt, use
  getOrCreateInstance for the modal, read item.params (was item.config)
- PreflightCheck: validate credentials from the remotes table; curl
  warning now applies to ntfy only
- SteppedSession: drop remoteStorage property
- language: add backup-record delete-count strings
- script.php: simplify postflight license-key prompt
2026-07-04 13:22:44 -05:00
jmiller 13af787c13 chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-06-30 19:19:09 +00:00
gitea-actions[bot] 481e395624 chore: promote changelog [Unreleased] → [02.52.24] 2026-06-30 19:18:28 +00:00
gitea-actions[bot] 202a26847b chore(release): build 02.52.24 [skip ci] 2026-06-30 19:18:21 +00:00
jmiller 7b38e238f5 Merge pull request 'fix: use warning status when backup succeeds but upload fails' (#199) from fix/upload-fail-warning-status into main 2026-06-30 19:18:06 +00:00
gitea-actions[bot] 9820d75212 chore(version): pre-release bump to 02.52.24-dev [skip ci]
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 24s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Successful in 2m56s
2026-06-30 19:17:57 +00:00
jmiller 9c0c6eae15 docs: add warning status changes to changelog
Universal: PR Check / Branch Policy (pull_request) Failing after 2s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 6s
Generic: Repo Health / Access control (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 6s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Universal: PR Check / Secret Scan (pull_request) Successful in 10s
Generic: Project CI / Lint & Validate (pull_request) Successful in 16s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 23s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 36s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
2026-06-30 14:17:34 -05:00
gitea-actions[bot] 1daa6869cc chore(version): pre-release bump to 02.52.23-dev [skip ci] 2026-06-30 19:14:33 +00:00
jmiller aefa46e0c4 fix: use warning status when backup succeeds but remote upload fails
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 19s
Previously a successful backup with a failed remote upload was marked
as "complete", hiding the upload failure. Now these records get a
"warning" status with a yellow badge so operators can see at a glance
which backups didn't reach their remote destination.

Warning-status records are treated as usable backups throughout:
- Downloadable, browsable, and restorable (the archive is intact)
- Counted in dashboard stats, storage totals, and success streaks
- Included in purge operations and differential base lookups
- Shown with yellow "warning" badge in list, detail, and cpanel module
- Filterable via the status dropdown on Backup Records

Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
2026-06-30 14:14:06 -05:00
jmiller ed55ab068b chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-06-30 18:56:24 +00:00
gitea-actions[bot] 765e6feea6 chore: promote changelog [Unreleased] → [02.52.22] 2026-06-30 18:53:53 +00:00
gitea-actions[bot] 007036301d chore(release): build 02.52.22 [skip ci] 2026-06-30 18:53:45 +00:00
jmiller 1db4015003 Merge pull request 'fix: cancel stalled backups with ACL + auto-timeout failsafe' (#197) from fix/cancel-stalled-backup into main 2026-06-30 18:53:15 +00:00
gitea-actions[bot] 8dac5a7448 chore(version): pre-release bump to 02.52.22-dev [skip ci]
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 22s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Failing after 11m45s
2026-06-30 18:53:06 +00:00
jmiller 4560ffb84b docs: update changelog with cancel stalled and pre-update modal
Universal: PR Check / Branch Policy (pull_request) Failing after 1s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 4s
Generic: Project CI / Lint & Validate (pull_request) Successful in 11s
Universal: PR Check / Secret Scan (pull_request) Successful in 9s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 3s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 11s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 29s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 34s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
2026-06-30 13:52:42 -05:00
gitea-actions[bot] 5be922613f chore(version): pre-release bump to 02.52.21-dev [skip ci] 2026-06-30 18:50:40 +00:00
jmiller b26a21820b fix: auto-cancel stalled backups after 30 min timeout
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 5s
Universal: PR Check / Branch Policy (pull_request) Failing after 1s
Universal: PR Check / Secret Scan (pull_request) Successful in 6s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 29s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Generic: Repo Health / Access control (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: Build & Release / Promote to RC (pull_request) Failing after 14s
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 13s
Generic: Project CI / Lint & Validate (pull_request) Successful in 43s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 47s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
PreflightCheck now auto-cancels "running" backup records that have
exceeded 30 minutes, treating them as stalled. Partial archive files
are cleaned up. The auto-cancelled records are surfaced as warnings
so the user knows what happened.

Records younger than 30 minutes are assumed to be legitimately running
and still block new backups for the same profile.

Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
2026-06-30 13:50:18 -05:00
gitea-actions[bot] a56f72b186 chore(version): pre-release bump to 02.52.20-dev [skip ci] 2026-06-30 18:49:16 +00:00
jmiller 1eb1c18bdf fix: add cancel stalled backup action with ACL permission
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 18s
Backups stuck in "running" status block all future backups for the same
profile via the preflight check. Previously the only fix was a manual
DB update.

Adds a toolbar button and AJAX endpoint to cancel stalled backups:
- New ACL permission: mokosuitebackup.backup.cancel
- BackupsController::cancelStalled() for toolbar (multi-select)
- AjaxController::cancelBackup() for AJAX/API use
- Sets status to "fail", cleans up partial archive files
- Updated preflight error message to mention the cancel action
- Language keys for en-GB and en-US

Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
2026-06-30 13:48:51 -05:00
jmiller eea1a40265 Merge pull request 'fix: remove orphaned deploy-manual workflow' (#195) from fix/remove-deploy-manual into main
fix: remove orphaned deploy-manual workflow [skip ci]
2026-06-30 18:33:51 +00:00
jmiller ebc692789c chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-06-30 18:12:34 +00:00
gitea-actions[bot] 983ec77dbd chore: promote changelog [Unreleased] → [02.52.18] 2026-06-30 18:12:06 +00:00
gitea-actions[bot] 25cf65f4cf chore(release): build 02.52.18 [skip ci] 2026-06-30 18:11:56 +00:00
jmiller 2d3a697f22 Merge pull request 'fix: remote upload prefix mismatch and restore security file' (#193) from fix/sftp-upload-and-restore-security into main 2026-06-30 18:11:32 +00:00
jmiller a4df3a651d fix: remove orphaned deploy-manual workflow [skip ci] 2026-06-30 18:07:18 +00:00
gitea-actions[bot] 3d9c48f40f chore(version): pre-release bump to 02.52.18-dev [skip ci]
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 33s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Successful in 2m23s
2026-06-30 18:00:27 +00:00
jmiller 4093267984 fix: add verbose error_log throughout restore script
Universal: PR Check / Branch Policy (pull_request) Failing after 2s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 8s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 7s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 8s
Generic: Project CI / Lint & Validate (pull_request) Successful in 16s
Universal: PR Check / Secret Scan (pull_request) Successful in 11s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 30s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 41s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
Every action handler now logs entry, key parameters, outcomes, and
failures to PHP error_log. Security file creation logs directory
permissions, PHP user, and the specific error when file_put_contents
fails. Database import logs SQL file size, statement counts, and
individual errors. Cleanup logs each file removal success/failure.

Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
2026-06-30 12:59:59 -05:00
gitea-actions[bot] 236609341f chore(version): pre-release bump to 02.52.17-dev [skip ci] 2026-06-30 17:53:59 +00:00
jmiller 20ce945e73 fix: recreate security file if missing while verification is pending
Universal: PR Check / Branch Policy (pull_request) Failing after 1s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 6s
Generic: Repo Health / Access control (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 8s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 9s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 11s
Generic: Project CI / Lint & Validate (pull_request) Successful in 13s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 22s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 34s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
The security file was only written inside the code-generation block
(first page load). If the file was deleted or failed to write, it
was never recreated because the session already held the code. Now
file writing is a separate check that runs whenever verification is
pending and the file is missing.

Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
2026-06-30 12:53:36 -05:00
gitea-actions[bot] f2f424a565 chore(version): pre-release bump to 02.52.16-dev [skip ci] 2026-06-30 17:50:30 +00:00
jmiller 3a6bb1c783 fix: remote upload prefix mismatch and restore security file visibility
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 23s
Remote uploaders (SFTP, FTP, S3, Google Drive) expect type-prefixed
property names (sftp_host, ftp_port, etc.) but createUploaderFromParams
passes unprefixed keys from the remotes table params JSON. Add prefix
mapping in createUploaderFromParams to bridge the naming gap.

Rename .mokorestore-security.php to mokorestore-security.php (no leading
dot) so the file is visible in file managers and not blocked by web
server dotfile rules. Also clean it up in actionCleanup.

Closes #13

Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
2026-06-30 12:50:02 -05:00
jmiller 785ffd85a3 chore: sync auto-release.yml from Template-Generic [skip ci] 2026-06-28 20:10:19 +00:00
jmiller 71da4af64b chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-06-28 19:39:25 +00:00
jmiller 4d5711c304 chore: sync auto-release.yml from Template-Generic [skip ci] 2026-06-28 19:39:22 +00:00
gitea-actions[bot] 1a4bb32c6c chore: promote changelog [Unreleased] → [01.45.00] 2026-06-28 19:31:25 +00:00
gitea-actions[bot] 13a526d6be chore(release): build 01.45.00 [skip ci] 2026-06-28 19:31:21 +00:00
jmiller babdb9e390 ci: add submodules: recursive to checkout (fixes MokoSuiteClient packaging) 2026-06-28 19:30:15 +00:00
jmiller 57c9ea600b ci: add submodules: recursive to checkout (fixes MokoSuiteClient packaging) 2026-06-28 19:25:18 +00:00
jmiller afffef78bd chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-06-28 19:12:12 +00:00
jmiller 720f008050 Merge pull request 'release: promote dev to main (v01.43.37)' (#159) from dev into main 2026-06-28 19:03:51 +00:00
jmiller cd1d3241bd Merge branch 'dev' of https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteBackup into dev
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 10s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 16s
Generic: Project CI / Lint & Validate (pull_request) Successful in 20s
Universal: PR Check / Validate PR (pull_request) Failing after 8s
Universal: PR Check / Secret Scan (pull_request) Successful in 11s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 3s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 16s
Universal: Auto Version Bump / Version Bump (push) Successful in 8s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 20s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 17s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Failing after 29m21s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
2026-06-28 14:03:25 -05:00
jmiller e2d88313cf merge: resolve version conflicts (keep dev's 01.43.37)
Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
2026-06-28 14:02:44 -05:00
gitea-actions[bot] 256d79a270 chore(version): pre-release bump to 01.44.01-dev [skip ci] 2026-06-28 18:57:02 +00:00
gitea-actions[bot] d8d5a1e48e chore(version): auto-bump patch 01.43.38-dev [skip ci] 2026-06-28 18:56:50 +00:00
jmiller 330cfa9dc5 chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-06-28 18:56:20 +00:00
jmiller 8485f24342 docs: update changelog for v01.43.35, add retention to README
Universal: Auto Version Bump / Version Bump (push) Successful in 9s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 21s
Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
2026-06-28 13:56:17 -05:00
gitea-actions[bot] 51c4db5115 chore: promote changelog [Unreleased] → [01.44.00] 2026-06-28 18:52:14 +00:00
gitea-actions[bot] fd33c86157 chore(release): build 01.44.00 [skip ci] 2026-06-28 18:52:07 +00:00
gitea-actions[bot] ac7673805e chore(version): pre-release bump to 01.43.37-dev [skip ci] 2026-06-28 18:51:38 +00:00
gitea-actions[bot] 428e217b56 chore(version): auto-bump patch 01.43.36-dev [skip ci] 2026-06-28 18:51:13 +00:00
jmiller c0ba29aca8 Merge pull request 'release: promote dev to main (v01.43.x)' (#157) from dev into main 2026-06-28 18:50:58 +00:00
jmiller 81a72d466b merge: resolve workflow file conflicts (take main's v05.02.00)
Universal: Auto Version Bump / Version Bump (push) Successful in 16s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 6s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Generic: Project CI / Lint & Validate (pull_request) Successful in 1m0s
Universal: PR Check / Secret Scan (pull_request) Successful in 7s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 34s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Generic: Repo Health / Access control (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 11s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 1m0s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 29s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Failing after 21m34s
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report: Scripts Governance (pull_request) Has been cancelled
Generic: Repo Health / Report: Repository Health (pull_request) Has been cancelled
Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
2026-06-28 13:50:24 -05:00
gitea-actions[bot] 942b33f9ce chore(version): pre-release bump to 01.43.35-dev [skip ci] 2026-06-28 18:46:50 +00:00
jmiller 60e04cfd0a Merge pull request 'fix: remove ordering column from profiles table' (#158) from fix/remove-profiles-ordering into dev
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 5s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Universal: PR Check / Secret Scan (pull_request) Successful in 9s
Generic: Repo Health / Access control (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 12s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 44s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 31s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
2026-06-28 18:46:09 +00:00
gitea-actions[bot] 672b953ef5 chore(version): pre-release bump to 01.43.34-dev [skip ci]
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Failing after 2s
2026-06-28 18:45:40 +00:00
jmiller 1b481f2e2c fix: remove ordering column from profiles table
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 18s
The ordering column was unused in the profiles UI — profiles sort by ID.
Drops the column via migration, removes all references from model,
config query, importer, and install SQL.

Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
2026-06-28 13:45:01 -05:00
gitea-actions[bot] 4a027d6245 chore(version): pre-release bump to 01.43.32-dev [skip ci] 2026-06-28 07:49:06 +00:00
jmiller 8af19f875c chore: add SECURITY.md from Template-Joomla
Universal: Auto Version Bump / Version Bump (push) Has been cancelled
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Has been cancelled
2026-06-28 07:25:44 +00:00
jmiller b56e4060bf chore: add SECURITY.md from Template-Joomla
Universal: Auto Version Bump / Version Bump (push) Successful in 14s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 29s
2026-06-28 07:15:34 +00:00
jmiller 9b5d0475f5 chore: sync ci-generic.yml from Template-Generic [skip ci] 2026-06-27 20:45:20 +00:00
jmiller 53e11fe9ad chore: sync rc-revert.yml from Template-Generic [skip ci] 2026-06-27 05:32:40 +00:00
gitea-actions[bot] 9757658c34 chore(version): pre-release bump to 01.43.31-dev [skip ci] 2026-06-27 02:33:25 +00:00
gitea-actions[bot] c82378128a chore(version): auto-bump patch 01.43.30-dev [skip ci] 2026-06-27 02:33:14 +00:00
jmiller f95505704a fix: add submodule checkout to pre-release workflow
Universal: Auto Version Bump / Version Bump (push) Successful in 11s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 13s
The CI checkout step was missing submodules: recursive, causing
MokoSuiteClient to be an empty gitlink during builds. This resulted
in broken MokoSuiteClient.zip and "Install path does not exist" errors.

Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
2026-06-26 21:32:49 -05:00
gitea-actions[bot] 6cdc9b04d0 chore(version): pre-release bump to 01.43.29-dev [skip ci] 2026-06-27 02:20:50 +00:00
jmiller bad73529ae Merge pull request 'fix: SSH key indicator, schema alignment, MokoSuiteClient bundle' (#155) from fix/ssh-key-indicator into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 11s
2026-06-27 02:20:30 +00:00
jmiller 288baf41d3 fix: remove duplicate version tags from 8 manifests, align AjaxController to params column
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 4s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: PR Check / Secret Scan (pull_request) Successful in 5s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 13s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 30s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
CI version_bump was creating duplicate <version> lines in all
sub-extension manifests. Also AjaxController still referenced the old
`config` column and removed `keep_local` column on the remotes table.

Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
2026-06-26 21:19:21 -05:00
gitea-actions[bot] 7d1dcf3e1c chore(version): pre-release bump to 01.43.26-dev [skip ci] 2026-06-26 21:19:20 -05:00
jmiller 2002c1fcad fix: remove stray 't' in package manifest and duplicate version in component manifest
The CI version_bump wrote 't' instead of a tab before <version> in
pkg_mokosuitebackup.xml, and appended a duplicate <version> line in
mokosuitebackup.xml instead of replacing the existing one.

Claude-Session: https://claude.ai/code/session_01MbEjBtsSjPuTWhqqrMS2wG
2026-06-26 21:19:19 -05:00
gitea-actions[bot] 4abe81f916 chore(version): pre-release bump to 01.43.25-dev [skip ci] 2026-06-26 21:19:19 -05:00
jmiller 571b03743f docs: update README with multi-remote, MokoSuiteClient, sub-extension count 2026-06-26 21:19:18 -05:00
gitea-actions[bot] 7fc1cad305 chore(version): pre-release bump to 01.43.24-dev [skip ci] 2026-06-26 21:19:18 -05:00
jmiller 03a1dd75c9 feat: bundle MokoSuiteClient as nested package in release ZIP
- Add MokoSuiteClient as git submodule under source/packages/
- Add pkg_mokosuiteclient entry to pkg_mokosuitebackup.xml
- Fix duplicate <version> tag in package manifest
2026-06-26 21:19:17 -05:00
gitea-actions[bot] 02d8312d1b chore(version): pre-release bump to 01.43.23-dev [skip ci] 2026-06-26 21:19:16 -05:00
jmiller c508fcc8d5 fix: align remotes table schema, add restore_script_name column, profile ordering
- install.mysql.sql: rename `config` → `params` and drop `keep_local` from remotes
  table to match update file 01.41.00 and RemoteTable.php code (fixes Joomla
  database maintenance "one problem")
- install.mysql.sql: fix idx_enabled index to use composite (profile_id, enabled)
- install.mysql.sql: add restore_script_name column to profiles table
- 01.43.22.sql: ALTER TABLE to add restore_script_name for existing installs
- DashboardModel: order profile dropdown by ID instead of ordering column
- SteppedBackupEngine: add stack trace logging around MokoRestore standalone
  generation to debug str_replace FATAL on SFTP profiles
2026-06-26 21:18:47 -05:00
jmiller 3af3708020 chore: sync pre-release.yml from Template-Generic [skip ci] 2026-06-27 00:49:34 +00:00
jmiller 3098b7ad40 chore: sync repo-health.yml from Template-Generic [skip ci] 2026-06-25 19:47:25 +00:00
jmiller d10bda3321 chore: sync pr-check.yml from Template-Generic [skip ci] 2026-06-25 19:47:24 +00:00
jmiller 12214bade1 chore: sync ci-issue-reporter.yml from Template-Generic [skip ci] 2026-06-25 19:47:22 +00:00
gitea-actions[bot] d104b7b936 chore(version): pre-release bump to 01.43.22-dev [skip ci] 2026-06-25 17:18:29 +00:00
jmiller 80110ac111 Merge pull request 'fix: SSH key indicator and missing delete language key' (#154) from fix/ssh-key-indicator into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 9s
2026-06-25 17:18:21 +00:00
gitea-actions[bot] 3bd1f63833 chore(version): pre-release bump to 01.43.21-dev [skip ci]
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
2026-06-25 17:18:03 +00:00
jmiller 93f0fa0a47 fix: SSH key indicator detection and missing delete language key
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 9s
- SshKeyField: detect base64-encoded keys from DB so the "Key loaded"
  badge displays correctly after initial upload
- Add COM_MOKOJOOMBACKUP_BACKUPS_N_ITEMS_DELETED language keys for
  Joomla's AdminController delete feedback message
2026-06-25 12:17:45 -05:00
jmiller ee1de178b1 chore: sync workflow-sync-trigger.yml from Template-Generic [skip ci] 2026-06-25 17:12:17 +00:00
jmiller 014d659908 chore: sync version-set.yml from Template-Generic [skip ci] 2026-06-25 17:12:17 +00:00
jmiller 113febad3f chore: sync repo-health.yml from Template-Generic [skip ci] 2026-06-25 17:12:16 +00:00
jmiller 18a3a524f2 chore: sync pre-release.yml from Template-Generic [skip ci] 2026-06-25 17:12:16 +00:00
jmiller 659fc6e274 chore: sync pr-check.yml from Template-Generic [skip ci] 2026-06-25 17:12:15 +00:00
jmiller 89af9fa14c chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-06-25 17:12:14 +00:00
jmiller d60535ae64 chore: sync deploy-manual.yml from Template-Generic [skip ci] 2026-06-25 17:12:14 +00:00
jmiller b9ef947feb chore: sync cleanup.yml from Template-Generic [skip ci] 2026-06-25 17:12:13 +00:00
jmiller e7ab83c5fb chore: sync auto-release.yml from Template-Generic [skip ci] 2026-06-25 17:12:12 +00:00
jmiller dc81cd7cc8 chore: sync auto-bump.yml from Template-Generic [skip ci] 2026-06-25 17:12:11 +00:00
gitea-actions[bot] 268b3d54d7 chore(version): pre-release bump to 01.43.20-dev [skip ci] 2026-06-25 16:27:48 +00:00
jmiller 1cfe7c6c6e Merge pull request 'fix: add SQL update file to match manifest version' (#153) from fix/schema-version-file-2 into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 19s
fix: add SQL update file to match manifest version
2026-06-25 16:26:38 +00:00
jmiller f0da0c02b4 fix: add SQL update file to match manifest version
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Secret Scan (pull_request) Successful in 6s
Universal: PR Check / Validate PR (pull_request) Failing after 4s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Failing after 7s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 46s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Joomla's Database view requires a SQL update file matching the manifest
version. Missing file causes persistent schema version mismatch warning.
2026-06-25 11:25:56 -05:00
gitea-actions[bot] 2f8a65388c chore(version): pre-release bump to 01.43.19-dev [skip ci] 2026-06-25 16:13:23 +00:00
gitea-actions[bot] 9978622960 chore(version): pre-release bump to 01.43.18-dev [skip ci] 2026-06-25 16:13:03 +00:00
jmiller 35e5fc1503 Merge pull request 'fix(db): add 01.43.11 schema update file' (#152) from fix/schema-version-file into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 23s
2026-06-25 16:12:46 +00:00
gitea-actions[bot] 2338ba5197 chore(version): pre-release bump to 01.43.17-dev [skip ci]
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
2026-06-25 16:12:33 +00:00
jmiller e67eedbc93 fix(db): add 01.43.11 schema update file to resolve version mismatch
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 10s
Joomla's database checker requires a SQL update file matching the manifest
version. Missing file caused schema version to stay at 01.41.00.
2026-06-25 11:12:22 -05:00
gitea-actions[bot] d812aca832 chore(version): pre-release bump to 01.43.15-dev [skip ci] 2026-06-25 16:00:54 +00:00
gitea-actions[bot] 4315f36c6a chore(version): pre-release bump to 01.43.14-dev [skip ci] 2026-06-25 15:59:41 +00:00
jmiller 10467835ac Merge pull request 'fix: UI cleanup, custom restore script name, version bump 01.43.11-dev' (#150) from fix/ui-cleanup-restore-name into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 10s
2026-06-25 15:59:30 +00:00
gitea-actions[bot] f26d58504e chore(version): pre-release bump to 01.43.13-dev [skip ci]
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
2026-06-25 15:58:38 +00:00
jmiller 07fb4dcc24 fix: remove run/backup buttons, move actions to detail view, custom restore script name, version bump 01.43.11-dev
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 10s
- Remove Run Backup / Backup Now buttons from profiles list, profile edit toolbar, and backup records view
- Move download, browse archive, and view log from backup list rows into individual backup record detail view
- Add download button to backup detail toolbar
- Link profile column in backup records list to profile edit
- Complete restore script filename customization across BackupEngine, SteppedBackupEngine, and MokoRestore
- Remove ordering field from profiles, default sort by ID ascending
- Fix untranslated JFIELD language keys
- Bump all manifests to 01.43.11-dev
2026-06-25 10:54:35 -05:00
gitea-actions[bot] 21a4352b3b chore(version): pre-release bump to 01.43.10-dev [skip ci] 2026-06-25 15:02:09 +00:00
gitea-actions[bot] 9d26f59f98 chore(version): pre-release bump to 01.43.09-dev [skip ci] 2026-06-25 15:01:45 +00:00
jmiller 3488434f28 Merge pull request 'fix(mokorestore): Joomla detection, multi-zip selector, standalone backup scan' (#148) from fix/mokorestore-improvements into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 18s
2026-06-25 15:01:14 +00:00
gitea-actions[bot] f97cd30c95 chore(version): pre-release bump to 01.43.08-dev [skip ci]
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
2026-06-25 15:00:33 +00:00
jmiller 836d1bc8b7 fix(mokorestore): add Joomla detection warning, multi-zip selector, and standalone backup scan
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 13s
- Preflight now detects existing Joomla installation (configuration.php / Version.php)
  and shows a yellow warning — does not block, but alerts the user
- Standalone mode: backup archive check scans for all ZIPs instead of hardcoded name
- Multi-zip selector integrated into extract step with radio buttons
- Selected backup file passed through to extract action
- Added warn-style CSS class (yellow) for preflight warnings
2026-06-25 10:00:07 -05:00
gitea-actions[bot] 79b3caa35a chore(version): pre-release bump to 01.43.05-dev [skip ci] 2026-06-25 13:39:28 +00:00
gitea-actions[bot] 6102c8f590 chore(version): pre-release bump to 01.43.04-dev [skip ci] 2026-06-25 13:39:01 +00:00
jmiller 88e53c5698 Merge pull request 'fix: Bootstrap 5 modals, language keys, ntfy default, MokoRestore error handling' (#146) from fix/bootstrap-modals into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 18s
2026-06-25 13:38:43 +00:00
gitea-actions[bot] ec1c3486c5 chore(version): pre-release bump to 01.43.03-dev [skip ci]
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
2026-06-25 13:38:28 +00:00
jmiller 3742477aef fix: convert inline modals to Bootstrap 5, fix language keys, ntfy default, and MokoRestore error handling
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 19s
Universal: PR Check / Secret Scan (pull_request) Successful in 9s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 29s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
- Convert 10 inline CSS modals to Bootstrap 5 (backups: 7, snapshots: 3)
- Replace style.display show/hide with Bootstrap Modal API
- Fix JFIELD_ORDERING_LABEL_ASC → JFIELD_ORDERING_ASC in profile filter
- Add COM_MOKOJOOMBACKUP_CONFIGURATION key for Options page title
- Change ntfy default server to ntfy.mokoconsulting.tech
- Add profile ID to dropdown labels across backups, dashboard, cpanel module
- Add error handling to MokoRestore post() and runPreflight() to prevent UI stalling
- Remove outdated SSH auth pattern references from field descriptions
2026-06-25 08:35:40 -05:00
jmiller 1c256bba7a chore: sync version-set.yml from Template-Generic [skip ci] 2026-06-24 11:51:45 +00:00
jmiller cd4dc6efd2 chore: sync repo-health.yml from Template-Generic [skip ci] 2026-06-24 11:51:44 +00:00
jmiller 2e6b71ac97 chore: sync pr-check.yml from Template-Generic [skip ci] 2026-06-24 11:51:41 +00:00
jmiller 5b4f84bad7 chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-06-24 11:51:39 +00:00
jmiller 847bb9bd0f chore: sync deploy-manual.yml from Template-Generic [skip ci] 2026-06-24 11:51:37 +00:00
jmiller ebcaf44b63 chore: sync auto-release.yml from Template-Generic [skip ci] 2026-06-24 11:51:32 +00:00
jmiller 17b05f9a13 chore: sync auto-bump.yml from Template-Generic [skip ci] 2026-06-24 11:51:30 +00:00
gitea-actions[bot] bb8e4a258a chore(version): pre-release bump to 01.43.02-dev [skip ci] 2026-06-24 11:49:56 +00:00
gitea-actions[bot] e6d646011a chore(version): auto-bump patch 01.43.01-dev [skip ci] 2026-06-24 11:49:37 +00:00
jmiller 726291995c chore: sync main into dev (#145)
Universal: Auto Version Bump / Version Bump (push) Successful in 16s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 19s
2026-06-24 11:49:19 +00:00
gitea-actions[bot] 2ac4923d74 chore: promote changelog [Unreleased] → [01.43.00]
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Failing after 4s
Universal: PR Check / Secret Scan (pull_request) Successful in 6s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 43s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-06-24 11:49:15 +00:00
gitea-actions[bot] adc4935587 chore(release): build 01.43.00 [skip ci] 2026-06-24 11:49:12 +00:00
jmiller 8f7b747c59 fix: add missing module entry point for cpanel module install (#144)
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Universal: PR Check / Secret Scan (pull_request) Successful in 8s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 47s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-06-24 11:49:01 +00:00
gitea-actions[bot] 42b7503d7b chore(version): pre-release bump to 01.42.04-dev [skip ci]
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 17s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Failing after 4m51s
2026-06-24 00:05:44 +00:00
jmiller 9ac8757a8c Merge pull request 'fix: add missing module entry point for cpanel module install' (#143) from fix/cpanel-module-install into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 12s
fix: add missing module entry point for cpanel module install (#143)
2026-06-24 00:05:30 +00:00
gitea-actions[bot] ef3fde1c39 chore(version): pre-release bump to 01.42.03-dev [skip ci]
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
2026-06-23 23:53:35 +00:00
Jonathan Miller 5750e71d15 fix: add missing module entry point for cpanel module install
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 15s
Joomla's module installer requires a <filename module="..."> element
in the manifest's <files> section. Without it, installation fails with
"No module file specified." Added the stub PHP file and manifest entry.
2026-06-23 18:53:00 -05:00
gitea-actions[bot] c8e022d46b chore(version): pre-release bump to 01.42.02-dev [skip ci] 2026-06-23 23:06:28 +00:00
jmiller 21f2ba0eff Merge pull request 'chore: sync main into dev (preserves dev-only changes)' (#142) from chore/sync-main-to-dev into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 15s
2026-06-23 23:06:15 +00:00
gitea-actions[bot] 821c4bae11 chore(version): pre-release bump to 01.42.01-dev [skip ci]
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
2026-06-23 23:05:52 +00:00
Jonathan Miller e86c104276 Merge remote-tracking branch 'origin/main' into chore/sync-main-to-dev
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 16s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Universal: PR Check / Secret Scan (pull_request) Successful in 7s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 41s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-06-23 18:05:20 -05:00
gitea-actions[bot] af2a1a2dae chore: promote changelog [Unreleased] → [01.42.00]
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 4s
Universal: PR Check / Secret Scan (pull_request) Successful in 7s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 36s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
2026-06-23 23:00:23 +00:00
gitea-actions[bot] c88b163de0 chore(release): build 01.42.00 [skip ci] 2026-06-23 23:00:20 +00:00
jmiller 358a7eb68a Merge pull request 'docs: Comprehensive CHANGELOG consolidation + wiki update + testing parameters' (#140) from chore/changelog-wiki-testing into main 2026-06-23 23:00:08 +00:00
Jonathan Miller 898520d1db chore: sync auto-release.yml from Template-Generic [skip ci]
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Failing after 3s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 18s
2026-06-23 17:58:49 -05:00
gitea-actions[bot] e633d0cc0a chore(version): pre-release bump to 01.41.03-dev [skip ci] 2026-06-23 22:20:21 +00:00
Jonathan Miller ff7418721d fix: review findings — key desc, missing changelog, [HOST] domain resolution
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Generic: Repo Health / Access control (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 4s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 7s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Universal: PR Check / Secret Scan (pull_request) Successful in 8s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 11s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 14s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
- Language: "encrypted" → "base64-encoded" for SSH key description
- CHANGELOG: added 3 missing bug fix entries (fields_values scope, CSRF
  token on Run Backup, SFTP showon/required)
- [HOST] placeholder: resolve domain from Joomla live_site config when
  HTTP_HOST is unavailable (CLI), instead of falling back to system
  hostname (joomla.invalid). Applied to both PlaceholderResolver and
  FolderPickerField.
2026-06-23 17:20:05 -05:00
gitea-actions[bot] 0b2b885163 chore(version): pre-release bump to 01.41.02-dev [skip ci] 2026-06-23 22:10:35 +00:00
Jonathan Miller 6c47838b30 fix: clean up wordy field descriptions — shorter, punchier text
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 5s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Secret Scan (pull_request) Successful in 7s
Universal: PR Check / Validate PR (pull_request) Failing after 4s
Generic: Repo Health / Access control (pull_request) Successful in 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 13s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 18s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 48s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
Backup dir, archive name, MokoRestore, SFTP key, sanitization,
encryption descriptions all shortened. Removed redundant placeholder
lists (now handled by clickable pills and help modal).
2026-06-23 17:09:59 -05:00
gitea-actions[bot] 0f95cb6e9f chore(version): pre-release bump to 01.41.01-dev [skip ci] 2026-06-23 22:01:24 +00:00
Jonathan Miller 1da2fdb856 docs: comprehensive CHANGELOG consolidation for v01.41.00
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 12s
Consolidated all fragmented changelog entries from the session into
a single clean v01.41.00 release entry organized by feature area.
Covers: multi-remote, snapshots, SFTP, MokoRestore, sanitization,
engine improvements, admin UI, CLI/API, notifications, security.
2026-06-23 17:01:11 -05:00
gitea-actions[bot] 4bafaa519a chore: promote changelog [Unreleased] → [01.41.00] 2026-06-23 21:54:11 +00:00
gitea-actions[bot] 3c32bd93e9 chore(release): build 01.41.00 [skip ci] 2026-06-23 21:54:07 +00:00
jmiller ef17873448 Merge pull request 'feat: Multi-remote storage — multiple destinations per profile (#97)' (#139) from feat/multi-remote-storage into main 2026-06-23 21:53:51 +00:00
Jonathan Miller dae30161ae feat: multi-remote storage — multiple destinations per profile (#97)
Universal: PR Check / Branch Policy (pull_request) Failing after 2s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 8s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 5s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Universal: PR Check / Secret Scan (pull_request) Successful in 8s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Failing after 5s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 41s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 22s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
New #__mokosuitebackup_remotes table stores remote destinations with
JSON params per type (SFTP/S3/GDrive/FTP). Each profile can have
multiple enabled destinations — the engine uploads to all of them.

Database:
- New table with profile_id FK, type, enabled, params JSON, ordering
- Migration auto-converts existing profile remote columns to new table
- RemoteTable, RemoteModel, RemotesModel classes

Engine:
- BackupEngine: loadRemoteDestinations() + createUploaderFromParams()
  iterates all enabled remotes, falls back to legacy columns
- SteppedBackupEngine: one upload step per remote destination, persisted
  via session.remoteDestinations + remoteIndex
- Local copy only deleted when ALL uploads succeed

UI:
- Profile edit: "Remote Destinations" linked table with AJAX CRUD
- Add/edit modal with type selector showing dynamic fields
- Toggle enabled/disabled, delete with confirmation
- Legacy fields hidden when remotes configured, shown as fallback
- Secrets masked in responses, merged from DB on save

Closes #97
2026-06-23 16:53:08 -05:00
jmiller 8e70bfb723 chore: sync repo-health.yml from Template-Generic [skip ci] 2026-06-23 21:52:37 +00:00
jmiller dcd772018e chore: sync pr-check.yml from Template-Generic [skip ci] 2026-06-23 21:52:36 +00:00
jmiller 26d765b74e chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-06-23 21:52:35 +00:00
jmiller 78b68d2647 chore: sync auto-bump.yml from Template-Generic [skip ci] 2026-06-23 21:52:34 +00:00
gitea-actions[bot] 50a879155d chore: promote changelog [Unreleased] → [01.40.00] 2026-06-23 19:18:42 +00:00
gitea-actions[bot] b4fb674566 chore(release): build 01.40.00 [skip ci] 2026-06-23 19:18:28 +00:00
jmiller 1b93d2ac21 Merge pull request 'feat: Complete config.xml, access.xml + ACL enforcement audit (#137)' (#138) from feat/config-acl-audit into main 2026-06-23 19:17:48 +00:00
Jonathan Miller 8e5913d706 fix: enforce correct ACL permissions across all controllers (#137)
Universal: PR Check / Branch Policy (pull_request) Failing after 1s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 7s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 11s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 2s
Universal: PR Check / Secret Scan (pull_request) Successful in 10s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 33s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Failing after 5s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 54s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
13 ACL fixes across 5 files:
- BackupsController: purge() uses backup.purge (was core.delete)
- SnapshotsController: delete() uses snapshot.manage (was core.delete)
- AjaxController: restoreInit/Step use backup.restore (was backup.run),
  browseArchive uses backup.browse (was core.manage),
  countPurge uses backup.purge (was core.delete),
  compareBackups uses backup.compare (was core.manage)
- API SnapshotsController: displayList/download use snapshot.manage
  (was core.manage)
- HtmlView: verify gated by core.manage, compare by backup.compare,
  purge separated from delete with backup.purge

Closes #137
2026-06-23 14:16:54 -05:00
Jonathan Miller 1f7def05c1 feat: complete config.xml and access.xml (#137)
config.xml:
- Defaults fieldset: archive format, MokoRestore mode, sanitization
  defaults (passwords, emails, sessions), log retention days
- Global ntfy fieldset: server, topic, token (fallback for profiles)

access.xml:
- mokosuitebackup.backup.purge — bulk delete old backups
- mokosuitebackup.backup.compare — compare two backups
- mokosuitebackup.backup.browse — browse archive file listings

30+ new language strings for all fields and ACL actions.

Partial #137 (ACL enforcement audit in separate commit)
2026-06-23 14:04:12 -05:00
gitea-actions[bot] 95317fb707 chore: promote changelog [Unreleased] → [01.39.01] 2026-06-23 18:37:04 +00:00
gitea-actions[bot] cb5ff2843d chore(release): build 01.39.01 [skip ci] 2026-06-23 18:36:54 +00:00
jmiller 4e6369094b Merge pull request 'fix: Resolve merge conflict markers in script.php' (#136) from fix/script-merge-conflicts into main 2026-06-23 18:32:45 +00:00
Jonathan Miller 0fbcc861d9 fix: resolve merge conflict markers in script.php
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Failing after 10s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 44s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 9s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 7s
Universal: PR Check / Branch Policy (pull_request) Failing after 3s
Universal: PR Check / Secret Scan (pull_request) Successful in 10s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 12s
Generic: Repo Health / Access control (pull_request) Successful in 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Failing after 3m49s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
12 conflict markers from a stale stash pop were accidentally
committed to main in PR #135. Resolved all by keeping the
"Updated upstream" blocks which include both error_log() and
user-facing enqueueMessage() calls.
2026-06-23 13:32:03 -05:00
jmiller 8cea58d1f6 chore: remove security-audit.yml -- handled by MokoGitea 2026-06-23 18:27:10 +00:00
gitea-actions[bot] 4df70531e2 chore(version): pre-release bump to 01.39.02-dev [skip ci]
Publish to Composer / Publish Package (release) Failing after 7s
2026-06-23 18:13:45 +00:00
gitea-actions[bot] 845b856cda chore(version): auto-bump patch 01.28.03-dev [skip ci] 2026-06-23 18:12:45 +00:00
jmiller 84511b08d2 Merge pull request 'feat: Purge, CPanel module, 7z format, SFTP browser (#119, #105, #122, #98)' (#135) from feat/final-batch into main 2026-06-23 18:06:23 +00:00
Jonathan Miller 899a33bc58 feat: purge, CPanel module, 7z format, SFTP browser (#119, #105, #122, #98)
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Failing after 10s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 3s
Universal: PR Check / Branch Policy (pull_request) Failing after 1s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 4s
Universal: PR Check / Validate PR (pull_request) Failing after 3s
Universal: PR Check / Secret Scan (pull_request) Successful in 5s
Generic: Repo Health / Access control (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 13s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Failing after 4m50s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
#119: Manual purge — toolbar button opens modal with date picker,
AJAX count preview, confirmation before bulk delete.

#105: CPanel admin dashboard module (mod_mokosuitebackup_cpanel) —
backup status, quick action buttons per profile, next scheduled,
stats, and quick links. Registered in package manifest.

#122: 7z archive format via system 7za/7z CLI binary with optional
password encryption. New SevenZipArchiver engine class.

#98: SFTP remote file browser — custom SftpPathField with "Browse
Remote" button, modal directory listing via SSH ls, click to navigate,
double-click to select.

Also: CHANGELOG updated, wiki Home updated, #121 verified (encryption
field already visible in Archive Settings tab).

Closes #119, closes #105, closes #122, closes #98, closes #121
2026-06-23 13:05:42 -05:00
jmiller 633e9b7f1e chore: remove security-audit.yml -- handled by MokoGitea
Universal: Auto Version Bump / Version Bump (push) Successful in 20s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 43s
2026-06-23 18:05:04 +00:00
gitea-actions[bot] ec0b7eb8a4 chore(version): auto-bump patch 01.28.02-dev [skip ci] 2026-06-23 18:04:50 +00:00
jmiller 7d119565da chore: remove deploy-manual.yml -- no longer needed
Universal: Auto Version Bump / Version Bump (push) Successful in 14s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Failing after 21s
2026-06-23 17:59:42 +00:00
jmiller 7970597fb8 chore: sync repo-health.yml from Template-Generic [skip ci] 2026-06-23 17:51:32 +00:00
jmiller 13f1c1db5e chore: sync pr-check.yml from Template-Generic [skip ci] 2026-06-23 17:51:30 +00:00
jmiller 7ea30aa146 chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-06-23 17:51:30 +00:00
jmiller d96f3e7760 chore: sync deploy-manual.yml from Template-Generic [skip ci] 2026-06-23 17:51:29 +00:00
jmiller 10b31fea84 chore: sync auto-bump.yml from Template-Generic [skip ci] 2026-06-23 17:51:28 +00:00
jmiller 997924a107 Merge pull request 'fix: MokoRestore review findings + README rewrite' (#134) from fix/mokorestore-review-findings into main 2026-06-23 17:49:49 +00:00
gitea-actions[bot] 9319abec41 chore(version): pre-release bump to 01.39.01-dev [skip ci]
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Successful in 3s
Universal: Build & Release / Build & Release Pipeline (pull_request) Failing after 8s
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Failing after 4m25s
2026-06-23 17:49:32 +00:00
Jonathan Miller 7e404b0246 fix: MokoRestore review findings + update README
Universal: PR Check / Branch Policy (pull_request) Failing after 2s
Generic: Repo Health / Access control (pull_request) Successful in 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 5s
Universal: PR Check / Validate PR (pull_request) Failing after 4s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 13s
Universal: PR Check / Secret Scan (pull_request) Successful in 10s
Universal: Build & Release / Promote to RC (pull_request) Failing after 10s
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 42s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 50s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
Review fixes:
- data-only mode uses REPLACE INTO (was INSERT INTO, broke on dupes)
- temporary password is random 16-char hex (was hardcoded "changeme")

README rewritten with all features: snapshots, SFTP, MokoRestore
wizard, sanitization, dashboard, CLI, API.
2026-06-23 12:49:17 -05:00
jmiller 6638577cf5 Merge pull request 'feat: MokoRestore post-restore resets + per-table conflict resolution' (#133) from feat/mokorestore-enhancements into main 2026-06-23 17:37:49 +00:00
Jonathan Miller 114995242d chore: merge main, resolve conflicts, remove stale files
Universal: PR Check / Branch Policy (pull_request) Failing after 2s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 5s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 8s
Generic: Repo Health / Access control (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Universal: PR Check / Secret Scan (pull_request) Successful in 7s
Branch Cleanup / Delete merged branch (pull_request) Failing after 2s
RC Revert / Rename rc/ back to dev/ (pull_request) Has been skipped
Universal: Workflow Sync Trigger / Sync workflows to live repos (pull_request) Failing after 7s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 58s
Universal: Build & Release / Build & Release Pipeline (pull_request) Failing after 5s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
2026-06-23 12:37:29 -05:00
jmiller 3d6c0974fa chore: remove deprecated .mokogitea/workflows/composer-publish.yml [skip ci] 2026-06-23 17:36:30 +00:00
jmiller 8aefc1d702 chore: remove deprecated .mokogitea/workflows/deploy-manual.yml [skip ci] 2026-06-23 17:36:27 +00:00
Jonathan Miller da52a9d2f9 Merge remote-tracking branch 'origin/main' into feat/mokorestore-enhancements
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 6s
Universal: PR Check / Branch Policy (pull_request) Failing after 3s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Universal: PR Check / Secret Scan (pull_request) Successful in 10s
Generic: Repo Health / Access control (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 17s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 51s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
2026-06-23 12:33:59 -05:00
Jonathan Miller 0dc0eb1bef feat: MokoRestore post-restore resets + per-table conflict resolution (#131, #132)
Universal: PR Check / Branch Policy (pull_request) Failing after 1s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 5s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 1s
Universal: PR Check / Secret Scan (pull_request) Successful in 6s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Universal: Build & Release / Promote to RC (pull_request) Failing after 13s
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 53s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 1m0s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
#131: Post-restore actions step in MokoRestore wizard:
- Reset all passwords to temporary "changeme" with requireReset flag
- Reset article hit counters to zero
- Clear content versions (#__history)
- Clear sessions (#__session)
- Clear cache tables and filesystem cache
- Auto-detect sanitized password hashes and prompt for reset

#132: Per-table conflict resolution during database import:
- New "Tables" step shows all tables from database.sql
- Per-table dropdown: Replace / Skip / Merge / Data Only
- Preset buttons: All Replace, All Skip, Everything except users
- Skip mode skips all statements for that table
- Merge mode uses INSERT IGNORE instead of INSERT INTO
- Data Only skips DROP/CREATE, inserts data only

Wizard now has 9 steps: Pre-check → Extract → Tables → Database →
Config → Admin → Post-Restore → Provisioning → Complete

Closes #131, closes #132
2026-06-23 12:33:18 -05:00
jmiller 1def73df19 chore: sync repo-health.yml from Template-Generic [skip ci] 2026-06-23 17:11:33 +00:00
jmiller 48f132ecf9 chore: sync pr-check.yml from Template-Generic [skip ci] 2026-06-23 17:11:32 +00:00
jmiller c17349277d chore: sync issue-branch.yml from Template-Generic [skip ci] 2026-06-23 17:11:31 +00:00
jmiller 5a6ad02b53 chore: sync auto-bump.yml from Template-Generic [skip ci] 2026-06-23 17:11:29 +00:00
gitea-actions[bot] 9db7331a72 chore(version): pre-release bump to 01.28.01-dev [skip ci]
Publish to Composer / Publish Package (release) Failing after 5s
2026-06-21 23:58:07 +00:00
gitea-actions[bot] 32931c1e37 chore(version): auto-bump patch 01.27.04-dev [skip ci] 2026-06-21 23:57:56 +00:00
168 changed files with 6079 additions and 1892 deletions
+3
View File
@@ -0,0 +1,3 @@
[submodule "source/packages/MokoSuiteClient"]
path = source/packages/MokoSuiteClient
url = https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteClient.git
+2 -2
View File
@@ -59,8 +59,8 @@ Joomla **package** with four sub-extensions:
- **Attribution**: `Authored-by: Moko Consulting`
- **Workflow directory**: `.mokogitea/` (not `.gitea/` or `.github/`)
- **Minification**: handled at build time (CI)
- **Wiki**: documentation lives in the Gitea wiki, not `docs/` files
- **Standards**: [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home)
- **Wiki**: documentation lives in the MokoGitea wiki, not `docs/` files
- **Standards**: [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/.mokogitea/wiki)
## Coding Standards
+6 -5
View File
@@ -3,9 +3,9 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/auto-bump.yml
# VERSION: 09.02.00
# BRIEF: Auto patch-bump version on every push to dev (skips merge commits)
@@ -22,7 +22,7 @@ on:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
permissions:
contents: write
@@ -34,7 +34,8 @@ jobs:
if: >-
!contains(github.event.head_commit.message, '[skip ci]') &&
!contains(github.event.head_commit.message, '[skip bump]') &&
!startsWith(github.event.head_commit.message, 'Merge pull request')
!startsWith(github.event.head_commit.message, 'Merge pull request') &&
!startsWith(github.event.repository.name, 'Template-')
steps:
- name: Checkout
@@ -52,7 +53,7 @@ jobs:
echo "MOKO_CLI=/opt/mokocli/cli" >> "$GITHUB_ENV"
else
git clone --depth 1 --branch main --quiet \
"https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/MokoConsulting/mokocli.git" \
"https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/MokoConsulting/MokoCLI.git" \
/tmp/mokocli
cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet
echo "MOKO_CLI=/tmp/mokocli/cli" >> "$GITHUB_ENV"
+79 -45
View File
@@ -3,11 +3,11 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Release
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokocli
# PATH: /templates/workflows/universal/auto-release.yml.template
# VERSION: 05.00.00
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/auto-release.yml
# VERSION: 05.01.00
# BRIEF: Universal build & release detects platform from manifest.xml
#
# +=======================================================================+
@@ -27,7 +27,7 @@ name: "Universal: Build & Release"
on:
pull_request:
types: [opened, closed]
types: [opened, synchronize, closed]
branches:
- main
paths-ignore:
@@ -52,7 +52,7 @@ on:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }}
GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }}
@@ -64,9 +64,14 @@ jobs:
promote-rc:
name: Promote to RC
runs-on: release
# Skip on template repos (Template-*) — they scaffold other repos and do not release.
if: >-
(github.event.action == 'opened' && github.event.pull_request.merged != true) ||
(github.event_name == 'workflow_dispatch' && inputs.action == 'promote-rc')
!startsWith(github.event.repository.name, 'Template-') &&
(
(github.event.action == 'opened' && github.event.pull_request.merged != true) ||
(github.event.action == 'synchronize' && github.event.pull_request.merged != true) ||
(github.event_name == 'workflow_dispatch' && inputs.action == 'promote-rc')
)
steps:
- name: Checkout repository
@@ -74,6 +79,7 @@ jobs:
with:
token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 1
submodules: recursive
- name: Setup mokocli tools
env:
@@ -89,7 +95,7 @@ jobs:
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
fi
rm -rf /tmp/mokocli
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoCLI.git
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
cd /tmp/mokocli
composer install --no-dev --no-interaction --quiet
@@ -98,18 +104,46 @@ jobs:
- name: Rename branch to rc
run: |
php ${MOKO_CLI}/branch_rename.php \
--from "${{ github.event.pull_request.head.ref || 'dev' }}" --to rc \
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
--api-base "${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" \
--pr "${{ github.event.pull_request.number }}"
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
AUTH="Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}"
FROM="${{ github.event.pull_request.head.ref || 'dev' }}"
PR="${{ github.event.pull_request.number }}"
# Resolve the source branch HEAD commit.
SRC_JSON=$(curl -sf -H "$AUTH" "${API_BASE}/branches/${FROM}") \
|| { echo "::error::Source branch ${FROM} not found"; exit 1; }
SRC_SHA=$(printf '%s' "$SRC_JSON" | python3 -c "import sys, json; print(json.load(sys.stdin)['commit']['id'])" 2>/dev/null || true)
[ -n "$SRC_SHA" ] || { echo "::error::Could not resolve HEAD of ${FROM}"; exit 1; }
# Point rc at the source commit. If rc already exists (a protected branch that
# cannot be deleted), force-update its ref in place instead of delete+recreate:
# deleting a protected branch fails, which then makes the recreate return HTTP 409.
if curl -sf -o /dev/null -H "$AUTH" "${API_BASE}/branches/rc"; then
echo "rc exists - force-updating to ${FROM} (${SRC_SHA})"
curl -sf -X PATCH -H "$AUTH" -H "Content-Type: application/json" \
"${API_BASE}/git/refs/heads/rc" -d "{\"sha\":\"${SRC_SHA}\",\"force\":true}" \
|| { echo "::error::Failed to force-update rc (CI token needs force-push on the protected rc branch)"; exit 1; }
else
echo "Creating rc from ${FROM}"
curl -sf -X POST -H "$AUTH" -H "Content-Type: application/json" \
"${API_BASE}/branches" -d "{\"new_branch_name\":\"rc\",\"old_branch_name\":\"${FROM}\"}" \
|| { echo "::error::Failed to create rc from ${FROM}"; exit 1; }
fi
# Repoint the PR at rc, then delete the old source branch (non-fatal).
if [ -n "$PR" ]; then
curl -s -X PATCH -H "$AUTH" -H "Content-Type: application/json" \
"${API_BASE}/pulls/${PR}" -d '{"head":"rc"}' >/dev/null || true
fi
curl -s -X DELETE -H "$AUTH" "${API_BASE}/branches/${FROM}" >/dev/null || true
echo "Renamed ${FROM} -> rc"
- name: Checkout rc and configure git
run: |
git fetch origin rc
git checkout rc
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "gitea-actions[bot]"
git config --local user.email "mokogitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "mokogitea-actions[bot]"
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
- name: Publish RC release
@@ -120,7 +154,7 @@ jobs:
- name: Update RC release notes from CHANGELOG.md
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
# Extract [Unreleased] section from changelog
@@ -162,9 +196,13 @@ jobs:
release:
name: Build & Release Pipeline
runs-on: release
# Skip on template repos (Template-*) — they scaffold other repos and do not release.
if: >-
github.event.pull_request.merged == true ||
(github.event_name == 'workflow_dispatch' && inputs.action != 'promote-rc')
!startsWith(github.event.repository.name, 'Template-') &&
(
github.event.pull_request.merged == true ||
(github.event_name == 'workflow_dispatch' && inputs.action != 'promote-rc')
)
steps:
- name: Checkout repository
@@ -172,11 +210,12 @@ jobs:
with:
token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 0
submodules: recursive
- name: Configure git for bot pushes
run: |
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "gitea-actions[bot]"
git config --local user.email "mokogitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "mokogitea-actions[bot]"
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
- name: Check for merge conflict markers
@@ -207,7 +246,7 @@ jobs:
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
fi
rm -rf /tmp/mokocli
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoCLI.git
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
cd /tmp/mokocli
composer install --no-dev --no-interaction --quiet
@@ -268,7 +307,7 @@ jobs:
!startsWith(steps.platform.outputs.platform, 'joomla')
run: |
VERSION="${{ steps.version.outputs.version }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
SEMVER_TAG="v${VERSION}"
@@ -293,7 +332,7 @@ jobs:
- name: Update release notes and promote changelog
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
# Get the stable release info (version and ID)
@@ -341,10 +380,13 @@ jobs:
import sys
version, date = sys.argv[1], sys.argv[2]
content = open('CHANGELOG.md').read()
old = '## [Unreleased]'
new = f'## [Unreleased]\n\n## [{version}] --- {date}'
content = content.replace(old, new, 1)
open('CHANGELOG.md', 'w').write(content)
marker = f'## [{version}]'
# Idempotent: only promote when this version header isn't already present,
# otherwise re-runs (or same-version builds) create empty duplicate headers.
if marker not in content:
new = f'## [Unreleased]\n\n{marker} --- {date}'
content = content.replace('## [Unreleased]', new, 1)
open('CHANGELOG.md', 'w').write(content)
" "$VERSION" "$DATE"
git add CHANGELOG.md
git commit -m "chore: promote changelog [Unreleased] → [${VERSION}]" || true
@@ -362,7 +404,7 @@ jobs:
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
php ${MOKO_CLI}/release_mirror.php \
--version "$VERSION" --tag "$RELEASE_TAG" \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
@@ -387,11 +429,11 @@ jobs:
&& echo "main branch pushed to GitHub mirror" \
|| echo "WARNING: GitHub mirror push failed"
- name: "Step 11: Delete rc branch and recreate dev from main"
- name: "Step 11: Delete rc branch (dev reset moved to cascade-dev.yml)"
if: steps.version.outputs.skip != 'true'
continue-on-error: true
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
# Delete rc branch (ephemeral — created by promote-rc)
@@ -399,23 +441,15 @@ jobs:
"${API_BASE}/branches/rc" 2>/dev/null \
&& echo "Deleted rc branch" || echo "rc branch not found"
# Delete dev branch
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
"${API_BASE}/branches/dev" 2>/dev/null && echo "Deleted dev branch"
# Recreate dev from main (now includes version bump + changelog promotion)
curl -sf -X POST -H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
"${API_BASE}/branches" \
-d '{"new_branch_name":"dev","old_branch_name":"main"}' 2>/dev/null && echo "Recreated dev from main"
echo "Pre-release branches cleaned, dev reset from main" >> $GITHUB_STEP_SUMMARY
# dev is reset from main by the dedicated "Cascade Main -> Dev" workflow
# (cascade-dev.yml), which runs after this release completes.
echo "rc cleaned; dev reset handled by cascade-dev.yml" >> $GITHUB_STEP_SUMMARY
- name: "Step 12: Create version branch from main"
if: steps.version.outputs.skip != 'true'
continue-on-error: true
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
BRANCH_NAME="version/${VERSION}"
@@ -436,7 +470,7 @@ jobs:
if: steps.version.outputs.skip != 'true'
continue-on-error: true
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
php ${MOKO_CLI}/version_reset_dev.php \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "${API_BASE}" \
--branch dev --path . 2>&1 || true
@@ -462,5 +496,5 @@ jobs:
echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Branch | \`${{ steps.version.outputs.branch }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Tag | \`${{ steps.version.outputs.tag }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Release | [View](${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
echo "| Release | [View](${MOKOGITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
fi
+4 -3
View File
@@ -3,9 +3,9 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# DEFGROUP: MokoGitea.Workflow
# INGROUP: MokoStandards.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/branch-cleanup.yml
# VERSION: 01.00.00
# BRIEF: Delete feature branches after PR merge
@@ -33,7 +33,8 @@ jobs:
run: |
BRANCH="${{ github.event.pull_request.head.ref }}"
API="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}/api/v1/repos/${{ github.repository }}/branches"
ENCODED=$(php -r "echo rawurlencode('${BRANCH}');")
# URL-encode the branch name's slashes (no PHP dependency on the runner)
ENCODED=$(printf '%s' "${BRANCH}" | sed 's|/|%2F|g')
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X DELETE \
-H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
+103 -7
View File
@@ -1,10 +1,106 @@
# DISABLED — auto-release Step 11 recreates dev from main after every release.
# Cascade-dev is redundant and causes version conflicts when both main and dev
# have different version numbers in templateDetails.xml / manifest.xml.
name: "Cascade Main → Dev (DISABLED)"
on: workflow_dispatch
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow
# INGROUP: MokoStandards.Cascade
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/cascade-dev.yml
# VERSION: 02.00.00
# BRIEF: Cascade main -> dev via PR; auto-merge only if conflict-free, else notify
name: "Cascade Main -> Dev"
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: write
pull-requests: write
env:
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
# ntfy destination is configured via repo or org variables (org vars are inherited).
NTFY_URL: ${{ vars.NTFY_URL || 'https://ntfy.mokoconsulting.tech' }}
NTFY_TOPIC: ${{ vars.CASCADE_NTFY_TOPIC || vars.NTFY_TOPIC || 'gitea-releases' }}
jobs:
noop:
cascade:
name: Cascade main -> dev
runs-on: ubuntu-latest
steps:
- run: echo "Cascade disabled — auto-release handles dev recreation"
- name: Open main -> dev PR (auto-merge if clean, else notify)
env:
TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
REPO: ${{ github.repository }}
run: |
set -uo pipefail
API="${MOKOGITEA_URL}/api/v1/repos/${REPO}"
AUTH="Authorization: token ${TOKEN}"
jqnum() { python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('$1',''))" 2>/dev/null; }
# 0. dev must exist
if ! curl -sf -H "$AUTH" "${API}/branches/dev" >/dev/null 2>&1; then
echo "No dev branch - nothing to cascade."; exit 0
fi
# 1. is main ahead of dev?
AHEAD=$(curl -sf -H "$AUTH" "${API}/compare/dev...main" \
| python3 -c "import sys,json; print(json.load(sys.stdin).get('total_commits',0))" 2>/dev/null || echo 0)
if [ "${AHEAD:-0}" -eq 0 ]; then
echo "dev already up to date with main."; exit 0
fi
echo "main is ${AHEAD} commit(s) ahead of dev."
# 2. reuse an open main->dev PR, else create one
PR=$(curl -sf -H "$AUTH" "${API}/pulls?state=open&base=dev" \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(next((str(p['number']) for p in d if p.get('head',{}).get('ref')=='main'), ''))" 2>/dev/null || echo "")
if [ -z "$PR" ]; then
RESP=$(curl -s -H "$AUTH" -H "Content-Type: application/json" -X POST "${API}/pulls" \
-d '{"head":"main","base":"dev","title":"chore(sync): cascade main -> dev","body":"Automated cascade of main into dev. Auto-merges only if conflict-free; otherwise left open for manual resolution."}')
PR=$(printf '%s' "$RESP" | jqnum number)
if [ -z "$PR" ]; then
echo "::warning::Could not open cascade PR: $RESP"; exit 0
fi
echo "Opened cascade PR #${PR}"
else
echo "Reusing open cascade PR #${PR}"
fi
# 3. wait for MokoGitea to compute mergeability (conflict detection)
MERGEABLE=""
for _ in 1 2 3 4 5 6; do
MERGEABLE=$(curl -sf -H "$AUTH" "${API}/pulls/${PR}" | jqnum mergeable)
case "$MERGEABLE" in True|False) break ;; esac
sleep 3
done
echo "mergeable=${MERGEABLE}"
notify() {
curl -sS \
-H "Title: ${REPO}: dev cascade needs manual merge" \
-H "Tags: warning,twisted_rightwards_arrows" \
-H "Priority: high" \
-H "Click: ${MOKOGITEA_URL}/${REPO}/pulls/${PR}" \
-d "main -> dev cascade PR #${PR} $1 It was NOT auto-merged; resolve it manually." \
"${NTFY_URL}/${NTFY_TOPIC}" || true
}
# 4. auto-merge only if conflict-free; otherwise notify
if [ "$MERGEABLE" = "True" ]; then
CODE=$(curl -s -o /tmp/merge.json -w "%{http_code}" -H "$AUTH" -H "Content-Type: application/json" \
-X POST "${API}/pulls/${PR}/merge" -d '{"Do":"merge","merge_when_checks_succeed":true}')
if [ "$CODE" -ge 200 ] && [ "$CODE" -lt 300 ]; then
echo "Cascade PR #${PR} merged (or scheduled to merge when checks pass)."
else
echo "::warning::Auto-merge returned HTTP ${CODE}: $(cat /tmp/merge.json)"
notify "could not be auto-merged (HTTP ${CODE})."
fi
else
echo "::warning::Cascade PR #${PR} has conflicts (mergeable=${MERGEABLE}); sending notification."
notify "has conflicts and cannot be merged automatically."
fi
+13 -2
View File
@@ -3,16 +3,22 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# DEFGROUP: MokoGitea.Workflow
# INGROUP: MokoStandards.CI
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.gitea/workflows/ci-generic.yml
# PATH: /.mokogitea/workflows/ci-generic.yml
# VERSION: 01.00.00
# BRIEF: CI pipeline — lint, validate, and test for generic projects (PHP + Node.js)
name: "Generic: Project CI"
on:
pull_request:
branches:
- main
- dev
- dev/**
- rc/**
workflow_dispatch:
permissions:
@@ -26,6 +32,8 @@ jobs:
lint:
name: Lint & Validate
runs-on: ubuntu-latest
# Skip on template repos (Template-*) — they hold placeholder scaffolding, not buildable source.
if: ${{ !startsWith(github.event.repository.name, 'Template-') }}
steps:
- name: Checkout
@@ -124,6 +132,9 @@ jobs:
name: Tests
runs-on: ubuntu-latest
needs: lint
# Run only when lint succeeded; always() forces evaluation so a skipped
# lint (e.g. template repos) skips this job cleanly instead of hanging.
if: ${{ always() && needs.lint.result == 'success' }}
steps:
- name: Checkout
@@ -0,0 +1,68 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/ci-issue-reporter.yml
# VERSION: 01.00.00
# BRIEF: Reusable workflow — creates/updates a MokoGitea issue when a CI gate fails.
# Clones MokoCLI and runs cli/ci_issue_reporter.sh.
name: "Universal: CI Issue Reporter"
on:
workflow_call:
inputs:
gate:
description: "CI gate name (e.g. PR Validation, Repository Health)"
required: true
type: string
details:
description: "Human-readable failure description"
required: true
type: string
severity:
description: "error or warning"
required: false
type: string
default: "error"
workflow:
description: "Workflow name for the issue title"
required: false
type: string
default: ""
secrets:
MOKOGITEA_TOKEN:
required: true
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
report:
name: "Report: ${{ inputs.gate }}"
runs-on: ubuntu-latest
steps:
- name: Clone MokoCLI
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: |
MOKOGITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}"
git clone --depth 1 --filter=blob:none --sparse "${MOKOGITEA_URL}/MokoConsulting/MokoCLI.git" /tmp/mokocli
cd /tmp/mokocli && git sparse-checkout set cli/ci_issue_reporter.sh
- name: Report CI failure
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
run: |
chmod +x /tmp/mokocli/cli/ci_issue_reporter.sh
/tmp/mokocli/cli/ci_issue_reporter.sh \
--gate "${{ inputs.gate }}" \
--details "${{ inputs.details }}" \
--severity "${{ inputs.severity }}" \
--workflow "${{ inputs.workflow }}"
+13 -13
View File
@@ -3,10 +3,10 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# DEFGROUP: MokoGitea.Workflow
# INGROUP: MokoStandards.Maintenance
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards
# PATH: /.gitea/workflows/cleanup.yml
# PATH: /.mokogitea/workflows/cleanup.yml
# VERSION: 01.00.00
# BRIEF: Scheduled cleanup — delete merged branches and old workflow runs
@@ -21,7 +21,7 @@ permissions:
contents: write
env:
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
jobs:
cleanup:
@@ -33,30 +33,30 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GA_TOKEN }}
token: ${{ secrets.MOKOGITEA_TOKEN }}
- name: Delete merged branches
env:
GA_TOKEN: ${{ secrets.GA_TOKEN }}
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: |
echo "=== Merged Branch Cleanup ==="
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
API="${MOKOGITEA_URL}/api/v1/repos/${{ github.repository }}"
# List branches via API
BRANCHES=$(curl -sS -H "Authorization: token ${GA_TOKEN}" \
BRANCHES=$(curl -sS -H "Authorization: token ${MOKOGITEA_TOKEN}" \
"${API}/branches?limit=50" | jq -r '.[].name')
DELETED=0
for BRANCH in $BRANCHES; do
# Skip protected branches
case "$BRANCH" in
main|master|develop|release/*|hotfix/*) continue ;;
main|master|dev|develop|rc|beta|alpha|release|release/*|production|stable|staging|hotfix/*|version/*) continue ;;
esac
# Check if branch is merged into main
if git merge-base --is-ancestor "origin/${BRANCH}" origin/main 2>/dev/null; then
echo " Deleting merged branch: ${BRANCH}"
curl -sS -X DELETE -H "Authorization: token ${GA_TOKEN}" \
curl -sS -X DELETE -H "Authorization: token ${MOKOGITEA_TOKEN}" \
"${API}/branches/${BRANCH}" 2>/dev/null || true
DELETED=$((DELETED + 1))
fi
@@ -66,20 +66,20 @@ jobs:
- name: Clean old workflow runs
env:
GA_TOKEN: ${{ secrets.GA_TOKEN }}
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: |
echo "=== Workflow Run Cleanup ==="
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
API="${MOKOGITEA_URL}/api/v1/repos/${{ github.repository }}"
CUTOFF=$(date -d "30 days ago" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -v-30d +%Y-%m-%dT%H:%M:%SZ)
# Get old completed runs
RUNS=$(curl -sS -H "Authorization: token ${GA_TOKEN}" \
RUNS=$(curl -sS -H "Authorization: token ${MOKOGITEA_TOKEN}" \
"${API}/actions/runs?status=completed&limit=50" | \
jq -r ".workflow_runs[] | select(.created_at < \"${CUTOFF}\") | .id" 2>/dev/null)
DELETED=0
for RUN_ID in $RUNS; do
curl -sS -X DELETE -H "Authorization: token ${GA_TOKEN}" \
curl -sS -X DELETE -H "Authorization: token ${MOKOGITEA_TOKEN}" \
"${API}/actions/runs/${RUN_ID}" 2>/dev/null || true
DELETED=$((DELETED + 1))
done
-76
View File
@@ -1,76 +0,0 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
name: "Publish to Composer"
on:
push:
tags:
- 'v*'
- '[0-9]*.[0-9]*.[0-9]*'
release:
types: [published]
workflow_dispatch:
env:
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
jobs:
publish:
name: Publish Package
runs-on: ubuntu-latest
if: >-
!contains(github.event.head_commit.message, '[skip ci]') &&
!contains(github.event.head_commit.message, '[skip publish]')
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup PHP
run: |
if ! command -v php &> /dev/null; then
sudo apt-get update -qq
sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer >/dev/null 2>&1
fi
- name: Install dependencies
run: composer install --no-dev --no-interaction --prefer-dist --quiet
- name: Determine version
id: version
run: |
VERSION=$(php -r "echo json_decode(file_get_contents('composer.json'))->version;")
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "Package version: ${VERSION}"
# Gitea Composer Registry — auto-publishes from tags
# The tag push itself registers the package at:
# https://git.mokoconsulting.tech/api/packages/MokoConsulting/composer
- name: Verify Gitea registry
run: |
echo "Gitea Composer registry auto-publishes from tags."
echo "Package available at: ${GITEA_URL}/api/packages/MokoConsulting/composer"
echo "Install: composer require mokoconsulting/mokocli"
# Packagist — notify of new version
- name: Notify Packagist
if: secrets.PACKAGIST_TOKEN != ''
run: |
VERSION="${{ steps.version.outputs.version }}"
echo "Notifying Packagist of version ${VERSION}..."
curl -sf -X POST \
-H "Content-Type: application/json" \
-d '{"repository":{"url":"https://git.mokoconsulting.tech/MokoConsulting/mokocli"}}' \
"https://packagist.org/api/update-package?username=mokoconsulting&apiToken=${{ secrets.PACKAGIST_TOKEN }}" \
&& echo "Packagist notified" \
|| echo "::warning::Packagist notification failed (package may not be registered yet)"
- name: Summary
run: |
VERSION="${{ steps.version.outputs.version }}"
echo "## Composer Package Published" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Registry | Status |" >> $GITHUB_STEP_SUMMARY
echo "|----------|--------|" >> $GITHUB_STEP_SUMMARY
echo "| Gitea | \`composer require mokoconsulting/mokocli:${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Packagist | \`composer require mokoconsulting/mokocli\` |" >> $GITHUB_STEP_SUMMARY
-126
View File
@@ -1,126 +0,0 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Deploy
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
# PATH: /templates/workflows/joomla/deploy-manual.yml.template
# VERSION: 04.07.00
# BRIEF: Manual SFTP deploy to dev server for Joomla repos
name: "Universal: Deploy to Dev (Manual)"
on:
workflow_dispatch:
inputs:
clear_remote:
description: 'Delete all remote files before uploading'
required: false
default: 'false'
type: boolean
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
permissions:
contents: read
jobs:
deploy:
name: SFTP Deploy to Dev
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Setup PHP
run: |
php -v && composer --version
- name: Setup MokoStandards tools
env:
GA_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
MOKO_CLONE_HOST: ${{ secrets.GA_TOKEN && 'git.mokoconsulting.tech/MokoConsulting' || 'github.com/mokoconsulting-tech' }}
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GA_TOKEN || github.token }}"}}'
run: |
git clone --depth 1 --branch main --quiet \
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoStandards-API.git" \
/tmp/mokostandards-api 2>/dev/null || true
if [ -d "/tmp/mokostandards-api" ] && [ -f "/tmp/mokostandards-api/composer.json" ]; then
cd /tmp/mokostandards-api && composer install --no-dev --no-interaction --quiet 2>/dev/null || true
fi
- name: Check FTP configuration
id: check
env:
HOST: ${{ vars.DEV_FTP_HOST }}
PATH_VAR: ${{ vars.DEV_FTP_PATH }}
PORT: ${{ vars.DEV_FTP_PORT }}
run: |
if [ -z "$HOST" ] || [ -z "$PATH_VAR" ]; then
echo "DEV_FTP_HOST or DEV_FTP_PATH not configured -- cannot deploy"
echo "skip=true" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "skip=false" >> "$GITHUB_OUTPUT"
echo "host=$HOST" >> "$GITHUB_OUTPUT"
REMOTE="${PATH_VAR%/}"
echo "remote=$REMOTE" >> "$GITHUB_OUTPUT"
[ -z "$PORT" ] && PORT="22"
echo "port=$PORT" >> "$GITHUB_OUTPUT"
- name: Deploy via SFTP
if: steps.check.outputs.skip != 'true'
env:
SFTP_KEY: ${{ secrets.DEV_FTP_KEY }}
SFTP_PASS: ${{ secrets.DEV_FTP_PASSWORD }}
SFTP_USER: ${{ vars.DEV_FTP_USERNAME }}
run: |
SOURCE_DIR="src"
[ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs"
[ ! -d "$SOURCE_DIR" ] && { echo "No src/ or htdocs/ -- nothing to deploy"; exit 0; }
printf '{"host":"%s","port":%s,"username":"%s","remotePath":"%s"' \
"${{ steps.check.outputs.host }}" "${{ steps.check.outputs.port }}" "$SFTP_USER" "${{ steps.check.outputs.remote }}" \
> /tmp/sftp-config.json
if [ -n "$SFTP_KEY" ]; then
echo "$SFTP_KEY" > /tmp/deploy_key
chmod 600 /tmp/deploy_key
printf ',"privateKeyPath":"/tmp/deploy_key"}' >> /tmp/sftp-config.json
else
printf ',"password":"%s"}' "$SFTP_PASS" >> /tmp/sftp-config.json
fi
DEPLOY_ARGS=(--path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json)
[ "${{ inputs.clear_remote }}" = "true" ] && DEPLOY_ARGS+=(--clear-remote)
PLATFORM=$(php /tmp/mokostandards-api/cli/platform_detect.php --path . 2>/dev/null || true)
if [ "$PLATFORM" = "waas-component" ] && [ -f "/tmp/mokostandards-api/deploy/deploy-joomla.php" ]; then
php /tmp/mokostandards-api/deploy/deploy-joomla.php "${DEPLOY_ARGS[@]}"
else
php /tmp/mokostandards-api/deploy/deploy-sftp.php "${DEPLOY_ARGS[@]}"
fi
rm -f /tmp/deploy_key /tmp/sftp-config.json
- name: Summary
if: always()
run: |
if [ "${{ steps.check.outputs.skip }}" = "true" ]; then
echo "### Deploy Skipped -- FTP not configured" >> $GITHUB_STEP_SUMMARY
else
echo "### Manual Dev Deploy Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| Host | \`${{ steps.check.outputs.host }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Remote | \`${{ steps.check.outputs.remote }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Clear | ${{ inputs.clear_remote }} |" >> $GITHUB_STEP_SUMMARY
fi
+3 -3
View File
@@ -3,10 +3,10 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# DEFGROUP: MokoGitea.Workflow
# INGROUP: MokoStandards.Security
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API
# PATH: /templates/workflows/gitleaks.yml.template
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
# PATH: /.mokogitea/workflows/gitleaks.yml
# VERSION: 01.00.00
# BRIEF: Secret scanning — detect leaked credentials, API keys, and tokens
#
+6 -6
View File
@@ -3,9 +3,9 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Automation
# VERSION: 01.39.00
# VERSION: 02.58.05
# BRIEF: Auto-create feature branch when an issue is opened
name: "Universal: Issue Branch"
@@ -19,7 +19,7 @@ permissions:
issues: write
env:
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
jobs:
create-branch:
@@ -28,8 +28,8 @@ jobs:
steps:
- name: Create branch and comment
run: |
TOKEN="${{ secrets.GA_TOKEN }}"
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
API="${MOKOGITEA_URL}/api/v1/repos/${{ github.repository }}"
ISSUE_NUM="${{ github.event.issue.number }}"
ISSUE_TITLE="${{ github.event.issue.title }}"
@@ -58,7 +58,7 @@ jobs:
echo "Created branch: ${BRANCH}"
# Comment on issue with branch link
REPO_URL="${GITEA_URL}/${{ github.repository }}"
REPO_URL="${MOKOGITEA_URL}/${{ github.repository }}"
BODY="Branch created: [\`${BRANCH}\`](${REPO_URL}/src/branch/${BRANCH})\n\n\`\`\`bash\ngit fetch origin\ngit checkout ${BRANCH}\n\`\`\`"
curl -sf -X POST \
+5 -5
View File
@@ -3,10 +3,10 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# DEFGROUP: MokoGitea.Workflow
# INGROUP: MokoStandards.Notifications
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards
# PATH: /.gitea/workflows/notify.yml
# PATH: /.mokogitea/workflows/notify.yml
# VERSION: 01.00.00
# BRIEF: Push notifications via ntfy on release success or workflow failure
@@ -15,9 +15,9 @@ name: "Universal: Notifications"
on:
workflow_run:
workflows:
- "Joomla Build & Release"
- "Joomla Extension CI"
- "Deploy"
- "Universal: Build & Release"
- "Joomla: Extension CI"
- "Generic: Project CI"
types:
- completed
+105 -37
View File
@@ -3,10 +3,10 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.CI
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/moko-platform
# PATH: /templates/workflows/universal/pr-check.yml.template
# DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.CI
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/pr-check.yml
# VERSION: 09.23.00
# BRIEF: PR gate — branch policy + code validation before merge
@@ -47,15 +47,15 @@ jobs:
fi
;;
fix/*|bugfix/*)
if [ "$BASE" != "dev" ]; then
if [ "$BASE" != "dev" ] && [ "$BASE" != "main" ]; then
ALLOWED=false
REASON="Fix branches must target 'dev', not '${BASE}'"
REASON="Fix branches must target 'dev' or 'main', not '${BASE}'"
fi
;;
patch/*)
if [ "$BASE" != "dev" ] && [ "$BASE" != "rc" ]; then
if [ "$BASE" != "dev" ] && [ "$BASE" != "rc" ] && [ "$BASE" != "main" ]; then
ALLOWED=false
REASON="Patch branches must target 'dev' or 'rc', not '${BASE}'"
REASON="Patch branches must target 'dev', 'rc', or 'main', not '${BASE}'"
fi
;;
hotfix/*)
@@ -86,7 +86,8 @@ jobs:
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Allowed merge paths:" >> $GITHUB_STEP_SUMMARY
echo "- \`feature/*\` → \`dev\`" >> $GITHUB_STEP_SUMMARY
echo "- \`fix/*\` → \`dev\`" >> $GITHUB_STEP_SUMMARY
echo "- \`fix/*\` → \`dev\` or \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`patch/*\` → \`dev\`, \`rc\`, or \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`hotfix/*\` → \`dev\` or \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`dev\` → \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`rc/*\` → \`main\`" >> $GITHUB_STEP_SUMMARY
@@ -96,6 +97,80 @@ jobs:
echo "Branch policy: OK (${HEAD} → ${BASE})"
echo "## Branch Policy: Passed" >> $GITHUB_STEP_SUMMARY
# ── Docs Update Gate (main PRs) ─────────────────────────────────────────
require-docs:
name: Require Docs Update
runs-on: ubuntu-latest
# Enforce only on PRs merging into main: README.md + CHANGELOG.md must both be updated.
if: ${{ github.base_ref == 'main' }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Require README.md and CHANGELOG.md in the PR diff
run: |
BASE="${{ github.event.pull_request.base.sha }}"
HEAD="${{ github.event.pull_request.head.sha }}"
CHANGED="$(git diff --name-only "$BASE" "$HEAD" 2>/dev/null || true)"
if [ -z "$CHANGED" ]; then
git fetch -q origin "${{ github.base_ref }}" 2>/dev/null || true
CHANGED="$(git diff --name-only "origin/${{ github.base_ref }}...HEAD" 2>/dev/null || true)"
fi
echo "Changed files in PR:"
echo "$CHANGED"
MISSING=""
echo "$CHANGED" | grep -qxE 'README\.md' || MISSING="README.md"
echo "$CHANGED" | grep -qxE 'CHANGELOG\.md' || MISSING="${MISSING:+$MISSING, }CHANGELOG.md"
if [ -n "$MISSING" ]; then
echo "::error::PRs into main must update: ${MISSING}"
{
echo "## Docs Update Required"
echo ""
echo "PRs merging into \`main\` must update both **README.md** and **CHANGELOG.md**."
echo ""
echo "Not updated in this PR: **${MISSING}**"
} >> "$GITHUB_STEP_SUMMARY"
exit 1
fi
echo "Docs update present (README.md + CHANGELOG.md)"
echo "## Docs Update: Passed" >> "$GITHUB_STEP_SUMMARY"
# ── Wiki Update Reminder (main PRs, non-blocking) ───────────────────────
wiki-reminder:
name: Wiki Update Reminder
runs-on: ubuntu-latest
if: ${{ github.base_ref == 'main' }}
steps:
- name: Remind to update the wiki
env:
TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
SERVER: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
REPO: ${{ github.repository }}
PR: ${{ github.event.pull_request.number }}
run: |
set -uo pipefail
{
echo "## Wiki Update Reminder"
echo ""
echo "Docs are **wiki-first** at MokoConsulting. If this change affects behavior, usage, configuration, or standards, update the repo wiki:"
echo ""
echo "- ${SERVER}/${REPO}/wiki"
echo ""
echo "_Non-blocking reminder._"
} >> "$GITHUB_STEP_SUMMARY"
# Post a single PR comment (idempotent via hidden marker); best-effort, never fails.
API="${SERVER}/api/v1/repos/${REPO}/issues/${PR}/comments"
if [ -n "${TOKEN:-}" ] && [ -n "${PR:-}" ]; then
existing="$(curl -sf -H "Authorization: token ${TOKEN}" "$API" 2>/dev/null | grep -c 'wiki-reminder' || true)"
if [ "${existing:-0}" -eq 0 ]; then
curl -sf -H "Authorization: token ${TOKEN}" -H "Content-Type: application/json" -X POST "$API" \
-d '{"body":"<!-- wiki-reminder -->\n\n**Wiki reminder:** docs are wiki-first -- if this PR changes behavior, usage, config, or standards, please update the repo wiki before/after merge. _(non-blocking)_"}' >/dev/null 2>&1 || true
fi
fi
echo "Wiki reminder emitted (non-blocking)."
# ── Secret Scanning ──────────────────────────────────────────────────
gitleaks:
name: Secret Scan
@@ -126,6 +201,8 @@ jobs:
validate:
name: Validate PR
runs-on: ubuntu-latest
# Skip on template repos (Template-*) — no real manifest/source/changelog to validate.
if: ${{ !startsWith(github.event.repository.name, 'Template-') }}
steps:
- name: Checkout
@@ -147,11 +224,12 @@ jobs:
- name: Detect platform
id: platform
run: |
# Read platform from XML manifest (<platform> tag) or plain text fallback
PLATFORM=$(sed -n 's/.*<platform>\([^<]*\)<\/platform>.*/\1/p' .mokogitea/manifest.xml 2>/dev/null | head -1)
[ -z "$PLATFORM" ] && PLATFORM=$(cat .mokogitea/manifest.xml 2>/dev/null | tr -d '[:space:]')
# Platform comes from the MokoGitea metadata API (public GET); manifest.xml is no longer used.
API="${GITHUB_SERVER_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${GITHUB_REPOSITORY}/metadata"
PLATFORM="$(curl -sf "$API" 2>/dev/null | python3 -c "import sys, json; print(json.load(sys.stdin).get('platform') or '')" 2>/dev/null || true)"
[ -z "$PLATFORM" ] && PLATFORM="generic"
echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT"
echo "Detected platform: $PLATFORM"
- name: Setup PHP
if: steps.platform.outputs.platform == 'joomla' || steps.platform.outputs.platform == 'dolibarr'
@@ -272,7 +350,7 @@ jobs:
joomla)
MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
if [ -z "$MANIFEST" ]; then
echo "::warning::No Joomla manifest found (WaaS site)"
echo "::warning::No Joomla manifest found (MokoSuite site)"
exit 0
fi
echo "Manifest: ${MANIFEST}"
@@ -285,7 +363,7 @@ jobs:
# Block legacy raw/branch update server URLs on MokoGitea
RAW_URLS=$(grep -n 'raw/branch' "$MANIFEST" | grep -i 'mokoconsulting\|mokogitea\|git\.mokoconsulting\.tech' || true)
if [ -n "$RAW_URLS" ]; then
echo "::error::Manifest contains legacy raw/branch update server URL on MokoGitea. Use the Gitea Pages URL instead (e.g. /{REPO}/updates.xml not /{REPO}/raw/branch/main/updates.xml)"
echo "::error::Manifest contains legacy raw/branch update server URL on MokoGitea. Use the MokoGitea Pages URL instead (e.g. /{REPO}/updates.xml not /{REPO}/raw/branch/main/updates.xml)"
echo "$RAW_URLS"
exit 1
fi
@@ -492,43 +570,33 @@ jobs:
name: Build RC Package
runs-on: ubuntu-latest
needs: [branch-policy, validate]
# Run only when both gates succeeded; always() forces evaluation so a skipped
# validate (e.g. template repos) skips this job cleanly instead of hanging.
if: ${{ always() && needs.branch-policy.result == 'success' && needs.validate.result == 'success' }}
steps:
- name: Trigger RC pre-release
env:
GA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
REPO: ${{ github.repository }}
BRANCH: ${{ github.head_ref }}
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
run: |
curl -s -X POST "${GITEA_URL}/api/v1/repos/${REPO}/actions/workflows/pre-release.yml/dispatches" -H "Authorization: token ${GITEA_TOKEN}" -H "Content-Type: application/json" -d "{\"ref\":\"${BRANCH}\",\"inputs\":{\"stability\":\"release-candidate\"}}"
curl -s -X POST "${MOKOGITEA_URL}/api/v1/repos/${REPO}/actions/workflows/pre-release.yml/dispatches" -H "Authorization: token ${MOKOGITEA_TOKEN}" -H "Content-Type: application/json" -d "{\"ref\":\"${BRANCH}\",\"inputs\":{\"stability\":\"release-candidate\"}}"
echo "### Pre-Release" >> $GITHUB_STEP_SUMMARY
echo "Triggered RC build on branch \`${BRANCH}\`" >> $GITHUB_STEP_SUMMARY
# ── Issue Reporter ──────────────────────────────────────────────────────
report-issues:
name: Report Issues
runs-on: ubuntu-latest
needs: [branch-policy, validate]
if: >-
always() &&
needs.validate.result == 'failure'
steps:
- name: Checkout
uses: actions/checkout@v4
with:
sparse-checkout: automation/ci-issue-reporter.sh
sparse-checkout-cone-mode: false
- name: "File issue for PR validation failure"
env:
GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
run: |
chmod +x automation/ci-issue-reporter.sh
./automation/ci-issue-reporter.sh \
--gate "PR Validation" \
--workflow "PR Check" \
--severity error \
--details "PR validation failed (syntax, manifest, changelog, or source checks). See the CI run for the specific check that failed."
uses: ./.mokogitea/workflows/ci-issue-reporter.yml
with:
gate: "PR Validation"
workflow: "PR Check"
severity: error
details: "PR validation failed (syntax, manifest, changelog, or source checks). See the CI run for the specific check that failed."
secrets: inherit
+18 -9
View File
@@ -3,11 +3,11 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# PATH: /templates/workflows/universal/pre-release.yml.template
# VERSION: 05.01.00
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/pre-release.yml
# VERSION: 05.02.00
# BRIEF: Auto pre-release on push to dev/alpha/beta/rc branches
name: "Universal: Pre-Release"
@@ -48,9 +48,13 @@ jobs:
build:
name: "Build Pre-Release (${{ inputs.stability || github.ref_name }})"
runs-on: release
# Skip on template repos (Template-*) — they scaffold other repos and do not release.
if: >-
github.event_name == 'workflow_dispatch' ||
github.event_name == 'push'
!startsWith(github.event.repository.name, 'Template-') &&
(
github.event_name == 'workflow_dispatch' ||
github.event_name == 'push'
)
steps:
- name: Checkout
@@ -59,6 +63,11 @@ jobs:
fetch-depth: 0
token: ${{ secrets.MOKOGITEA_TOKEN }}
ref: ${{ github.ref_name }}
submodules: recursive
- name: Update submodules to main
run: |
git submodule foreach --quiet 'git checkout main && git pull --quiet origin main' 2>/dev/null || true
- name: Setup mokocli tools
env:
@@ -75,7 +84,7 @@ jobs:
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
fi
rm -rf /tmp/mokocli
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoCLI.git
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet
echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV
@@ -147,8 +156,8 @@ jobs:
fi
# Commit version bump
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "gitea-actions[bot]"
git config --local user.email "mokogitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "mokogitea-actions[bot]"
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
git add -A
git diff --cached --quiet || {
+22 -16
View File
@@ -3,9 +3,9 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/rc-revert.yml
# VERSION: 09.23.00
# BRIEF: Rename rc/ branch back to dev/ when PR is closed without merge
@@ -25,16 +25,25 @@ jobs:
runs-on: ubuntu-latest
if: >-
github.event.pull_request.merged == false &&
startsWith(github.event.pull_request.head.ref, 'rc/')
startsWith(github.event.pull_request.head.ref, 'rc/') &&
!startsWith(github.event.repository.name, 'Template-')
steps:
- name: Rename branch
env:
BRANCH: ${{ github.event.pull_request.head.ref }}
REPO: ${{ github.repository }}
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: |
BRANCH="${{ github.event.pull_request.head.ref }}"
set -euo pipefail
# BRANCH is attacker-controlled (PR head ref). Strict allowlist before ANY use.
if ! printf '%s' "$BRANCH" | grep -Eq '^rc/[A-Za-z0-9._/-]+$'; then
echo "::error::Refusing unsafe branch name: $BRANCH"; exit 1
fi
SUFFIX="${BRANCH#rc/}"
DEV_BRANCH="dev/${SUFFIX}"
API="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}/api/v1/repos/${{ github.repository }}/branches"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
API="${GITEA_URL}/api/v1/repos/${REPO}/branches"
# Create dev/ branch from rc/ branch
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X POST \
@@ -42,25 +51,22 @@ jobs:
-H "Content-Type: application/json" \
-d "{\"new_branch_name\": \"${DEV_BRANCH}\", \"old_branch_name\": \"${BRANCH}\"}" \
"${API}" 2>/dev/null || true)
if [ "$STATUS" = "201" ]; then
echo "Created branch: ${DEV_BRANCH}" >> $GITHUB_STEP_SUMMARY
echo "Created branch: ${DEV_BRANCH}" >> "$GITHUB_STEP_SUMMARY"
else
echo "::error::Failed to create ${DEV_BRANCH} from ${BRANCH} (HTTP ${STATUS})"
exit 1
echo "::error::Failed to create ${DEV_BRANCH} from ${BRANCH} (HTTP ${STATUS})"; exit 1
fi
# Delete rc/ branch
ENCODED=$(php -r "echo rawurlencode('${BRANCH}');")
# Read BRANCH from the environment inside PHP (getenv, no string interpolation -> no PHP injection)
ENCODED=$(php -r 'echo rawurlencode(getenv("BRANCH"));')
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X DELETE \
-H "Authorization: token ${TOKEN}" \
"${API}/${ENCODED}" 2>/dev/null || true)
if [ "$STATUS" = "204" ]; then
echo "Deleted branch: ${BRANCH}" >> $GITHUB_STEP_SUMMARY
echo "Deleted branch: ${BRANCH}" >> "$GITHUB_STEP_SUMMARY"
else
echo "::warning::Failed to delete ${BRANCH} (HTTP ${STATUS})"
fi
echo "### RC Reverted" >> $GITHUB_STEP_SUMMARY
echo "${BRANCH} → ${DEV_BRANCH}" >> $GITHUB_STEP_SUMMARY
echo "### RC Reverted" >> "$GITHUB_STEP_SUMMARY"
echo "${BRANCH} → ${DEV_BRANCH}" >> "$GITHUB_STEP_SUMMARY"
+29 -41
View File
@@ -6,10 +6,10 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Validation
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/mokocli
# PATH: /templates/workflows/joomla/repo_health.yml.template
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/repo-health.yml
# VERSION: 09.23.00
# BRIEF: Enforces repository guardrails by validating scripts governance, tooling availability, and core repository health artifacts.
# ============================================================================
@@ -77,7 +77,7 @@ jobs:
- name: Check actor permission (admin only)
id: perm
env:
TOKEN: ${{ secrets.MOKOGITEA_TOKEN || secrets.MOKOGITEA_TOKEN || github.token }}
TOKEN: ${{ secrets.MOKOGITEA_TOKEN || github.token }}
REPO: ${{ github.repository }}
ACTOR: ${{ github.actor }}
run: |
@@ -88,7 +88,7 @@ jobs:
# Hardcoded authorized users — always allowed
case "$ACTOR" in
jmiller|gitea-actions[bot])
jmiller|mokogitea-actions[bot])
ALLOWED=true
PERMISSION=admin
METHOD="hardcoded allowlist"
@@ -671,42 +671,30 @@ jobs:
# ═══════════════════════════════════════════════════════════════════════
# Issue Reporter — file issues for failed gates
# ═══════════════════════════════════════════════════════════════════════
report-issues:
name: "Report Issues"
runs-on: ubuntu-latest
needs: [access_check, scripts_governance, repo_health]
report-scripts:
name: "Report: Scripts Governance"
needs: [access_check, scripts_governance]
if: >-
always() &&
(needs.scripts_governance.result == 'failure' ||
needs.repo_health.result == 'failure')
needs.scripts_governance.result == 'failure'
uses: ./.mokogitea/workflows/ci-issue-reporter.yml
with:
gate: "Scripts Governance"
workflow: "Repo Health"
severity: error
details: "Scripts directory policy violations detected. Review required and allowed directories."
secrets: inherit
steps:
- name: Checkout
uses: actions/checkout@v4
with:
sparse-checkout: automation/ci-issue-reporter.sh
sparse-checkout-cone-mode: false
- name: "File issues for failed gates"
env:
GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
run: |
chmod +x automation/ci-issue-reporter.sh
REPORTER="./automation/ci-issue-reporter.sh"
WF="Repo Health"
report_gate() {
local gate="$1" result="$2" details="$3"
if [ "$result" = "failure" ]; then
"$REPORTER" --gate "$gate" --details "$details" --workflow "$WF" --severity error
fi
}
report_gate "Scripts Governance" \
"${{ needs.scripts_governance.result }}" \
"Scripts directory policy violations detected. Review required and allowed directories."
report_gate "Repository Health" \
"${{ needs.repo_health.result }}" \
"Repository health checks failed — missing required artifacts, disallowed files, or content warnings. Check the CI run summary."
report-health:
name: "Report: Repository Health"
needs: [access_check, repo_health]
if: >-
always() &&
needs.repo_health.result == 'failure'
uses: ./.mokogitea/workflows/ci-issue-reporter.yml
with:
gate: "Repository Health"
workflow: "Repo Health"
severity: error
details: "Repository health checks failed — missing required artifacts, disallowed files, or content warnings. Check the CI run summary."
secrets: inherit
-82
View File
@@ -1,82 +0,0 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Security
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards
# PATH: /.gitea/workflows/security-audit.yml
# VERSION: 01.00.00
# BRIEF: Dependency vulnerability scanning for composer and npm packages
name: "Universal: Security Audit"
on:
schedule:
- cron: '0 6 * * 1' # Weekly on Monday at 06:00 UTC
pull_request:
branches:
- main
paths:
- 'composer.json'
- 'composer.lock'
- 'package.json'
- 'package-lock.json'
workflow_dispatch:
permissions:
contents: read
env:
NTFY_URL: ${{ vars.NTFY_URL || 'https://ntfy.mokoconsulting.tech' }}
NTFY_TOPIC: ${{ vars.NTFY_TOPIC || 'gitea-security' }}
jobs:
audit:
name: Dependency Audit
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Composer audit
if: hashFiles('composer.lock') != ''
run: |
echo "=== Composer Security Audit ==="
if ! command -v composer &> /dev/null; then
sudo apt-get update -qq
sudo apt-get install -y -qq php-cli composer >/dev/null 2>&1
fi
composer audit --format=plain 2>&1 | tee /tmp/composer-audit.txt
RESULT=$?
if [ $RESULT -ne 0 ]; then
echo "::warning::Composer vulnerabilities found"
echo "composer_vulnerable=true" >> "$GITHUB_ENV"
else
echo "No known vulnerabilities in composer dependencies"
fi
- name: NPM audit
if: hashFiles('package-lock.json') != ''
run: |
echo "=== NPM Security Audit ==="
npm audit --production 2>&1 | tee /tmp/npm-audit.txt || true
if npm audit --production 2>&1 | grep -q "found 0 vulnerabilities"; then
echo "No known vulnerabilities in npm dependencies"
else
echo "::warning::NPM vulnerabilities found"
echo "npm_vulnerable=true" >> "$GITHUB_ENV"
fi
- name: Notify on vulnerabilities
if: env.composer_vulnerable == 'true' || env.npm_vulnerable == 'true'
run: |
REPO="${{ github.event.repository.name }}"
curl -sS \
-H "Title: ${REPO} has vulnerable dependencies" \
-H "Tags: lock,warning" \
-H "Priority: high" \
-d "Security audit found vulnerabilities. Review dependency updates." \
"${NTFY_URL}/${NTFY_TOPIC}" || true
+32
View File
@@ -0,0 +1,32 @@
name: Sync Workflows to Repos
on:
push:
branches:
- main
paths:
- '.mokogitea/workflows/**'
jobs:
sync:
runs-on: ubuntu-latest
if: ${{ startsWith(github.event.repository.name, 'Template-') }}
steps:
- name: Checkout mokocli
uses: actions/checkout@v4
with:
repository: MokoConsulting/MokoCLI
token: ${{ secrets.MOKOGITEA_TOKEN }}
- name: Setup PHP
uses: https://git.mokoconsulting.tech/MokoConsulting/.mokogitea/raw/branch/main/actions/setup-php@v1
with:
php-version: '8.1'
- name: Install dependencies
run: composer install --no-dev --no-interaction
- name: Sync workflows to generic repos
run: php automation/bulk_sync.php --platform generic --org MokoConsulting --workflows-only --auto-merge --token "${{ secrets.MOKOGITEA_TOKEN }}"
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
+131
View File
@@ -0,0 +1,131 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: MokoGitea.Workflow.Template
# INGROUP: MokoStandards.CI
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Joomla
# PATH: /.mokogitea/workflows/version-set.yml
# VERSION: 01.00.00
# BRIEF: Set or reset the extension version across all version-bearing files
name: "Joomla: Set Version"
on:
workflow_dispatch:
inputs:
version:
description: "Version number (e.g. 01.00.00)"
required: true
type: string
branch:
description: "Branch to update (default: current)"
required: false
type: string
permissions:
contents: write
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
set-version:
name: Set Version to ${{ inputs.version }}
runs-on: ubuntu-latest
if: ${{ !startsWith(github.event.repository.name, 'Template-') }}
steps:
- name: Validate version format
run: |
VERSION="${{ inputs.version }}"
if ! echo "$VERSION" | grep -qP '^\d{2}\.\d{2}\.\d{2}$'; then
echo "::error::Invalid version format '${VERSION}' — expected XX.YY.ZZ (e.g. 01.00.00)"
exit 1
fi
echo "VERSION=${VERSION}" >> "$GITHUB_ENV"
- name: Checkout
uses: actions/checkout@v4
with:
token: ${{ secrets.MOKOGITEA_TOKEN || github.token }}
ref: ${{ inputs.branch || github.ref }}
fetch-depth: 1
- name: Update manifest version
run: |
MANIFEST=""
for XML_FILE in $(find . -maxdepth 3 -name "*.xml" -not -path "./.git/*" -not -path "./vendor/*"); do
if grep -q "<extension" "$XML_FILE" 2>/dev/null; then
MANIFEST="$XML_FILE"
break
fi
done
if [ -z "$MANIFEST" ]; then
echo "::warning::No Joomla extension manifest found — skipping manifest update"
else
OLD_VER=$(grep -oP '<version>\K[^<]+' "$MANIFEST" | head -1)
sed -i "s|<version>${OLD_VER}</version>|<version>${VERSION}</version>|" "$MANIFEST"
echo "Manifest: ${OLD_VER} → ${VERSION} (${MANIFEST})"
fi
- name: Update README.md version
run: |
if [ -f "README.md" ]; then
if grep -qP '^\s*VERSION:\s*\d' README.md; then
sed -i -E "s/(VERSION:\s*)[0-9]{2}\.[0-9]{2}\.[0-9]{2}/\1${VERSION}/" README.md
echo "README.md version updated to ${VERSION}"
else
echo "::warning::No VERSION line found in README.md — skipping"
fi
fi
- name: Update CHANGELOG.md
run: |
if [ -f "CHANGELOG.md" ]; then
DATE=$(date +%Y-%m-%d)
# Check if this version already has an entry
if grep -q "^\#\# \[${VERSION}\]" CHANGELOG.md; then
echo "CHANGELOG.md already has entry for ${VERSION} — skipping"
else
# Insert new version entry after [Unreleased] or at the top after header
if grep -q '^\#\# \[Unreleased\]' CHANGELOG.md; then
sed -i "/^\#\# \[Unreleased\]/a\\\\n## [${VERSION}] --- ${DATE}" CHANGELOG.md
else
sed -i "/^\# Changelog/a\\\\n## [Unreleased]\n\n## [${VERSION}] --- ${DATE}" CHANGELOG.md
fi
echo "CHANGELOG.md: added entry for ${VERSION}"
fi
else
echo "::warning::No CHANGELOG.md found — skipping"
fi
- name: Update FILE INFORMATION blocks
run: |
# Update VERSION in file header blocks (# VERSION: XX.YY.ZZ)
find . -maxdepth 1 -type f \( -name "*.yml" -o -name "*.yaml" -o -name "*.php" -o -name "*.md" \) \
-not -path "./.git/*" -not -path "./vendor/*" -print0 2>/dev/null | \
while IFS= read -r -d '' FILE; do
if head -20 "$FILE" | grep -qP '^\s*#?\s*VERSION:\s*\d{2}\.\d{2}\.\d{2}'; then
sed -i -E "s/(#?\s*VERSION:\s*)[0-9]{2}\.[0-9]{2}\.[0-9]{2}/\1${VERSION}/" "$FILE"
echo "Updated FILE INFORMATION VERSION in ${FILE}"
fi
done
- name: Commit and push
run: |
git config user.name "Moko Consulting [bot]"
git config user.email "hello@mokoconsulting.tech"
git add -A
if git diff --cached --quiet; then
echo "No version changes detected — nothing to commit"
else
git commit -m "chore: set version to ${VERSION} [skip bump]
Authored-by: Moko Consulting"
git push
echo "### Version Set" >> $GITHUB_STEP_SUMMARY
echo "Version updated to \`${VERSION}\` on branch \`${GITHUB_REF_NAME}\`" >> $GITHUB_STEP_SUMMARY
fi
+15 -6
View File
@@ -3,9 +3,9 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# DEFGROUP: MokoGitea.Workflow
# INGROUP: mokocli.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/workflow-sync-trigger.yml
# VERSION: 01.01.00
# BRIEF: Trigger workflow sync to live repos when a PR is merged to main
@@ -13,6 +13,7 @@
name: "Universal: Workflow Sync Trigger"
on:
workflow_dispatch:
pull_request:
types: [closed]
branches:
@@ -26,8 +27,10 @@ jobs:
name: Sync workflows to live repos
runs-on: ubuntu-latest
if: >-
github.event.pull_request.merged == true &&
!contains(github.event.pull_request.title, '[skip sync]')
startsWith(github.event.repository.name, 'Template-') &&
(github.event_name == 'workflow_dispatch' ||
(github.event.pull_request.merged == true &&
!contains(github.event.pull_request.title, '[skip sync]')))
steps:
- name: Determine platform from repo name
@@ -49,8 +52,14 @@ jobs:
env:
MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: |
GITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}"
git clone --depth 1 "${GITEA_URL}/MokoConsulting/mokocli.git" /tmp/mokocli
MOKOGITEA_URL="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}"
git clone --depth 1 "${MOKOGITEA_URL}/MokoConsulting/MokoCLI.git" /tmp/mokocli
- name: Install PHP
run: |
if ! command -v php &> /dev/null; then
apt-get update -qq && apt-get install -y -qq php-cli php-json php-curl > /dev/null 2>&1
fi
- name: Install dependencies
run: |
+52 -6
View File
@@ -1,14 +1,60 @@
# Changelog
## [Unreleased]
## [01.39.00] --- 2026-06-23
### Fixed
- Standalone restore script generation no longer aborts backups with `str_replace() expects at least 3 arguments, 2 given`. `MokoRestore::generateStandaloneScript()` had a `str_replace()` call (the "Backup Archive" pre-check rewrite) that was missing its `$php` subject argument, so **every** standalone-mode backup fatally errored while "Generating standalone restore.php…" — the archive still finalized and uploaded, but no `restore.php` was ever produced (the true root cause behind #226). (#226)
- Remote upload: the standalone restore script upload is no longer silent — its result is now checked and logged, and a failed restore-script upload marks the backup as `warning` (previously the result was discarded, so a missing restore script on the remote went unreported while the archive still showed success). (#226)
## [01.39.00] --- 2026-06-23
## [02.58.00] --- 2026-07-06
## [01.38.05] --- 2026-06-23
### Added
- SFTP destinations: **upload an SSH private key file** in the Add/Edit Destination modal instead of pasting it (reads the file into the key field client-side; pasting still works).
## [01.38.05] --- 2026-06-23
### Changed
- Add/Edit Destination modal: wrap the content in a Bootstrap `.container-fluid` and give it a 1rem padding frame via the WAM stylesheet (Bootstrap's `.modal-content` has no padding of its own).
## [01.38.04] --- 2026-06-23
### Fixed
- Pre-update backup now shows an admin notification on **every** outcome (success / warning / failure) — previously a *successful* pre-update backup fired nothing, so it looked like the notification wasn't working. (#192)
## [01.38.04] --- 2026-06-23
### Changed
- Component admin CSS now loads via the Joomla **Web Asset Manager** (`media/com_mokosuitebackup/` + `joomla.asset.json`) instead of an inline `<style>` block.
- "Keep local copy" is configured **per remote destination** (in the Add/Edit Destination modal); the redundant profile-level field and its "Remote" tab are removed.
- Add/Edit Destination modal: cleaned up the cramped padding/margins.
### Fixed
- Admin menu / duplicate-component fallout: (a) the orphaned `com_component-mokosuitebackup` is now removed in **preflight** too, so its "Backup" menu no longer collides on install ("The alias backup is already being used"); (b) `ensureSubmenuItems()` **recreates the top-level "Backup" menu** if it was deleted, instead of giving up — so Backup no longer disappears from the admin menu (and the cPanel module / MokoSuiteClient can find it again); (c) the component menu label now uses the short constant `COM_MOKOJOOMBACKUP_SHORT`. (#213 fallout)
- Installer no longer aborts on MySQL 8 with "This command is not supported in the prepared statement protocol yet" (error 1295). The legacy remote-column purge migration (`02.56.01.sql`) used `PREPARE`/`EXECUTE`/`DEALLOCATE`, which Joomla's installer rejects; the drop now runs in the package installer script via an INFORMATION_SCHEMA-gated plain `ALTER` (portable across MariaDB and MySQL 8). (#213 update path)
## [02.57.00] --- 2026-07-05
### Added
- `BackupRunner` service — a single synchronous entry point for backups that unifies final status and notification gating across the pre-update, web-cron, pre-install, scheduled-task and CLI triggers (delegates to `BackupEngine`; no double-notify). Returns a normalized result including the real complete/warning/fail status. Dashboard "Backup Now" (AJAX) unchanged; installer progress popup deferred to #196. (#214)
### Fixed
- Release automation: the changelog-promote step is now idempotent — it only inserts a `## [version]` header when that version isn't already present, preventing the empty, duplicated version headers that repeated/same-version builds were producing. (workflow)
## [02.56.11] --- 2026-07-05
### Fixed
- Package `postflight` now removes the orphaned `com_component-mokosuitebackup` registration (stray extension record, admin menu items, schema rows, and `administrator/` folder) left behind by the old "Type - Name" component `<name>` — self-healing on update so affected sites reconcile to the real `com_mokosuitebackup`. (#213 follow-up)
## [02.56.08] --- 2026-07-05
### Fixed
- Component manifest `<name>` reverted to the element-safe `MokoSuiteBackup`. The "Type - Name" convention derived element `com_component-mokosuitebackup`, registering a duplicate component and leaving the real `com_mokosuitebackup` orphaned on the old version. (#213)
## [02.56.07] --- 2026-07-05
### Security
- Mask the FTP password in `AjaxController::maskSecrets()`/`mergeExistingSecrets()` — stored FTP remotes no longer leak their password via `listRemotes`. (#169)
- Stop the API single-item view (`Backups/JsonapiView`) leaking the server `absolute_path`. (#187)
- SFTP uploader uses `StrictHostKeyChecking=accept-new` instead of `no`. (#182)
### Fixed
- `DatabaseDumper` writes a real newline after `DROP TABLE` (was a literal `\n`). (#179)
- Profile-picker forms order by `id` instead of the dropped `ordering` column. (#180)
- `uninstall.mysql.sql` now drops the snapshots table. (#181)
- CLI snapshot delete uses the `data_file` column (was non-existent `file_path`). (#184)
- Remove the duplicate pre-update backup (content plugin no longer subscribes to `onExtensionBeforeUpdate`). (#186)
- `DatabaseImporter` collects non-fatal statement errors (`getErrors()`/`hasErrors()`). (#188)
+1 -1
View File
@@ -4,7 +4,7 @@ Thank you for your interest in contributing to MokoSuiteBackup.
## Getting Started
1. Fork the repository on Gitea
1. Fork the repository on MokoGitea
2. Create a feature branch from `dev` (`feature/your-feature`)
3. Make your changes following the coding standards below
4. Submit a pull request targeting `dev`
+70 -34
View File
@@ -1,50 +1,86 @@
# MokoSuiteBackup
<!-- VERSION: 01.39.00 -->
Full-site backup and restore for Joomla — database, files, and configuration.
## Overview
MokoSuiteBackup is a comprehensive backup solution for Joomla 4/5/6 sites. It creates complete site backups including the database, files, and configuration, packaged into downloadable ZIP archives. Supports multiple backup profiles, scheduled backups via CLI/cron, and a REST API for remote management.
| Field | Value |
|---|---|
| **Package** | `pkg_mokosuitebackup` |
| **Type** | Joomla Package (9 sub-extensions + MokoSuiteClient) |
| **Joomla** | 6.x+ |
| **PHP** | 8.1+ |
| **License** | GPL-3.0-or-later |
## Features
- Full site backup (database + files + configuration)
- Database-only backup mode
- Files-only backup mode
- Multiple backup profiles with independent configurations
- File and directory exclusion filters
- Table exclusion filters for database backups
- Step-based backup engine (avoids PHP timeout on large sites)
- CLI script for cron/scheduled backups
- REST API (Joomla Web Services) for remote management
- Backup record management (list, download, delete)
- Automatic old backup cleanup (configurable retention)
- Admin dashboard with backup history and storage usage
### Backup
- Full site, database-only, files-only, and differential backup modes
- Pre-flight validation — checks directory, disk space, extensions, credentials before starting
- Auto-verify archive integrity after creation
- Stepped AJAX engine prevents timeout on shared hosting
- AES-256 ZIP encryption with configurable password
- Configurable archive naming with placeholders ([HOST], [DATE], [SITE_NAME], etc.)
- Per-profile retention — configure max backup count and max age (days) per profile, with global defaults
- Data sanitization — optionally clear user passwords, emails, and sessions in backup
### Content Snapshots
- Lightweight JSON snapshots of articles, categories, and modules
- Includes tags, custom fields, workflow associations
- Restore modes: Replace (clean slate) or Merge (upsert)
- Selective article restore — browse and pick individual items
- Automatic retention (max count + max age)
- Scheduled snapshot task via com_scheduler
### Remote Storage
- Multi-remote — upload to multiple destinations per profile simultaneously
- SFTP with SSH key file auth + remote directory browser
- Amazon S3 and S3-compatible (DigitalOcean Spaces, Wasabi, MinIO)
- Google Drive with OAuth2 and resumable uploads
- Graceful degradation — local backup preserved if upload fails
### MokoRestore Standalone Wizard
- 9-step restore wizard that works without Joomla installed
- Per-table conflict resolution: Replace / Skip / Merge / Data Only
- Post-restore actions: reset passwords, hits, versions, sessions, cache
- Auto-detect sanitized passwords and prompt for reset
- Standalone mode: restore.php scans directory for ZIP files
- Wrapped mode: restore.php bundled inside backup ZIP
- Security gate with filesystem verification
### Notifications
- Email on success/failure per profile
- ntfy push notifications
- Notifications for restore and snapshot operations
### Admin Dashboard
- Last backup status, next scheduled, total count, storage used
- Snapshot widget with latest info and type badges
- 30-day backup trend chart
- Per-profile storage breakdown
- System health checks
### CLI
- `mokosuitebackup:run --profile=1` — run backup
- `mokosuitebackup:restore 1 --files-only --db-only --password=xxx`
- `mokosuitebackup:snapshot create|restore|list|delete`
### REST API
- Backup: start, list, download, delete, profiles
- Snapshots: create, list, restore, delete, download
- Profile credentials masked in API responses
### Bundled: MokoSuiteClient
- Full MokoSuiteClient package installed automatically alongside MokoSuiteBackup
- Provides admin dashboard, security firewall, tenant management, and developer tools
## Installation
1. Download `pkg_mokobackup-*.zip` from [Releases](https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteBackup/releases)
1. Download from [Releases](https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteBackup/releases)
2. Joomla Administrator > Extensions > Install
3. System plugin enabled automatically on install
3. Components > MokoSuiteBackup > Dashboard
## Configuration
## Documentation
- **Component**: Administrator > Components > MokoSuiteBackup
- **Profiles**: Create backup profiles with different file/database filters
- **System Plugin**: Configure scheduled backup triggers and notifications
- **CLI**: `php cli/mokobackup.php --profile=1` for cron-based backups
## REST API
The webservices plugin exposes endpoints compatible with the MokoBackup MCP server:
- `POST /api/index.php/v1/mokobackup/backup` — Start a backup
- `GET /api/index.php/v1/mokobackup/backups` — List backup records
- `GET /api/index.php/v1/mokobackup/backup/:id/download` — Download archive
- `DELETE /api/index.php/v1/mokobackup/backup/:id` — Delete backup record
- `GET /api/index.php/v1/mokobackup/profiles` — List backup profiles
See the [Wiki](https://git.mokoconsulting.tech/MokoConsulting/MokoSuiteBackup/wiki) for guides and reference.
## License
+241
View File
@@ -0,0 +1,241 @@
<!--
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
This file is part of a Moko Consulting project.
SPDX-License-Identifier: GPL-3.0-or-later
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
# FILE INFORMATION
DEFGROUP: Template-Joomla
INGROUP: Template-Joomla.Documentation
REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Joomla
PATH: /SECURITY.md
VERSION: 02.58.05
BRIEF: Security vulnerability reporting and handling policy
-->
# Security Policy
## Purpose and Scope
This document defines the security vulnerability reporting, response, and disclosure policy for this Joomla Plugin template repository. It establishes the authoritative process for responsible disclosure, assessment, remediation, and communication of security issues.
## Supported Versions
Security updates are provided for the following versions:
| Version | Supported |
| ------- | ------------------ |
| 01.x.x | :white_check_mark: |
| < 01.0 | :x: |
Only the current major version receives security updates. Users should upgrade to the latest supported version to receive security patches.
## Reporting a Vulnerability
### Where to Report
**DO NOT** create public GitHub issues for security vulnerabilities.
Report security vulnerabilities privately to:
**Email**: `security@mokoconsulting.tech`
**Subject Line**: `[SECURITY] Template-Joomla - Brief Description`
### What to Include
A complete vulnerability report should include:
1. **Description**: Clear explanation of the vulnerability
2. **Impact**: Potential security impact and severity assessment
3. **Affected Versions**: Which versions are vulnerable
4. **Reproduction Steps**: Detailed steps to reproduce the issue
5. **Proof of Concept**: Code, configuration, or demonstration (if applicable)
6. **Suggested Fix**: Proposed remediation (if known)
7. **Disclosure Timeline**: Your expectations for public disclosure
### Response Timeline
* **Initial Response**: Within 3 business days
* **Assessment Complete**: Within 7 business days
* **Fix Timeline**: Depends on severity (see below)
* **Disclosure**: Coordinated with reporter
## Severity Classification
Vulnerabilities are classified using the following severity levels:
### Critical
* Remote code execution
* Authentication bypass
* Data breach or exposure of sensitive information
* **Fix Timeline**: 7 days
### High
* Privilege escalation
* SQL injection or command injection
* Cross-site scripting (XSS) with significant impact
* **Fix Timeline**: 14 days
### Medium
* Information disclosure (limited scope)
* Denial of service
* Security misconfigurations with moderate impact
* **Fix Timeline**: 30 days
### Low
* Security best practice violations
* Minor information leaks
* Issues requiring user interaction or complex preconditions
* **Fix Timeline**: 60 days or next release
## Remediation Process
1. **Acknowledgment**: Security team confirms receipt and begins investigation
2. **Assessment**: Vulnerability is validated, severity assigned, and impact analyzed
3. **Development**: Security patch is developed and tested
4. **Review**: Patch undergoes security review and validation
5. **Release**: Fixed version is released with security advisory
6. **Disclosure**: Public disclosure follows coordinated timeline
## Security Advisories
Security advisories are published via:
* GitHub Security Advisories
* Release notes and CHANGELOG.md
* Email notification to project users (if mailing list is established)
Advisories include:
* CVE identifier (if applicable)
* Severity rating
* Affected versions
* Fixed versions
* Mitigation steps
* Attribution (with reporter consent)
## Security Best Practices
For projects using this template:
### Required Controls
* Enable GitHub security features (Dependabot, code scanning)
* Implement branch protection on `main`
* Require code review for all changes
* Enforce signed commits (recommended)
* Use secrets management (never commit credentials)
* Maintain security documentation
* Follow secure coding standards defined in MokoStandards
### Joomla Plugin Security
* Follow Joomla security best practices
* Validate and sanitize all user input
* Use Joomla's database API to prevent SQL injection
* Properly escape output to prevent XSS
* Implement proper access control checks
* Use Joomla's session and authentication APIs
* Keep Joomla and dependencies up to date
### CI/CD Security
* Validate all inputs
* Sanitize outputs
* Use least privilege access
* Pin dependencies with hash verification
* Scan for vulnerabilities in dependencies
* Audit third-party actions and tools
#### Automated Security Scanning
All repositories SHOULD implement:
**CodeQL Analysis**:
* Enabled for PHP and other supported languages
* Runs on: push to main, pull requests, weekly schedule
* Query sets: `security-extended` and `security-and-quality`
* Configuration: `.github/workflows/codeql-analysis.yml`
**Dependabot Security Updates**:
* Weekly scans for vulnerable dependencies
* Automated pull requests for security patches
* Configuration: `.github/dependabot.yml`
**Secret Scanning**:
* Enabled by default with push protection
* Prevents accidental credential commits
### Dependency Management
* Keep dependencies up to date
* Monitor security advisories for dependencies
* Remove unused dependencies
* Audit new dependencies before adoption
* Document security-critical dependencies
## Compliance and Governance
This security policy is aligned with MokoStandards. Deviations require documented justification.
Security policies are reviewed and updated at least annually or following significant security incidents.
## Attribution and Recognition
We acknowledge and appreciate responsible disclosure. With your permission, we will:
* Credit you in security advisories
* List you in CHANGELOG.md for the fix release
* Recognize your contribution publicly (if desired)
## Contact and Escalation
* **Security Team**: security@mokoconsulting.tech
* **Primary Contact**: hello@mokoconsulting.tech
* **Escalation**: For urgent matters requiring immediate attention, contact the maintainer directly via GitHub
## Out of Scope
The following are explicitly out of scope:
* Issues in third-party dependencies (report directly to maintainers)
* Social engineering attacks
* Physical security issues
* Denial of service via resource exhaustion without amplification
* Issues requiring physical access to systems
* Theoretical vulnerabilities without proof of exploitability
---
## Metadata
| Field | Value |
| ------------ | ------------------------------------------------------------------------------------------------------------ |
| Document | Security Policy |
| Path | /SECURITY.md |
| Repository | [https://github.com/mokoconsulting-tech/Template-Joomla](https://github.com/mokoconsulting-tech/Template-Joomla) |
| Owner | Moko Consulting |
| Scope | Security vulnerability handling |
| Status | Active |
| Effective | 2026-01-16 |
## Revision History
| Date | Change Description | Author |
| ---------- | ------------------------------------------------- | --------------- |
| 2026-01-16 | Initial creation for template repository | Moko Consulting |
-1
View File
@@ -1 +0,0 @@
<!DOCTYPE html><title></title>
-37
View File
@@ -1,37 +0,0 @@
<?php
/**
* @package MokoSuiteBackup
* @subpackage plg_webservices_mokosuitebackup
* @author Moko Consulting <hello@mokoconsulting.tech>
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
* @license GNU General Public License version 3 or later; see LICENSE
*/
defined('_JEXEC') or die;
use Joomla\CMS\Extension\PluginInterface;
use Joomla\CMS\Factory;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
use Joomla\Event\DispatcherInterface;
use Joomla\Plugin\WebServices\MokoSuiteBackup\Extension\MokoSuiteBackupWebServices;
return new class () implements ServiceProviderInterface {
public function register(Container $container): void
{
$container->set(
PluginInterface::class,
function (Container $container) {
$plugin = new MokoSuiteBackupWebServices(
$container->get(DispatcherInterface::class),
(array) PluginHelper::getPlugin('webservices', 'mokosuitebackup')
);
$plugin->setApplication(Factory::getApplication());
return $plugin;
}
);
}
};
@@ -12,5 +12,9 @@
<action name="mokosuitebackup.backup.download" title="COM_MOKOSUITEBACKUP_ACTION_BACKUP_DOWNLOAD" />
<action name="mokosuitebackup.backup.restore" title="COM_MOKOSUITEBACKUP_ACTION_BACKUP_RESTORE" />
<action name="mokosuitebackup.snapshot.manage" title="COM_MOKOSUITEBACKUP_ACTION_SNAPSHOT_MANAGE" />
<action name="mokosuitebackup.backup.purge" title="COM_MOKOSUITEBACKUP_ACTION_BACKUP_PURGE" />
<action name="mokosuitebackup.backup.compare" title="COM_MOKOSUITEBACKUP_ACTION_BACKUP_COMPARE" />
<action name="mokosuitebackup.backup.browse" title="COM_MOKOSUITEBACKUP_ACTION_BACKUP_BROWSE" />
<action name="mokosuitebackup.backup.cancel" title="COM_MOKOSUITEBACKUP_ACTION_BACKUP_CANCEL" />
</section>
</access>
@@ -36,7 +36,7 @@ class SnapshotsController extends ApiController
*/
public function displayList(): static
{
if (!$this->app->getIdentity()->authorise('core.manage', 'com_mokosuitebackup')) {
if (!$this->app->getIdentity()->authorise('mokosuitebackup.snapshot.manage', 'com_mokosuitebackup')) {
$this->app->setHeader('status', 403);
echo json_encode(['errors' => [['title' => 'Access denied']]]);
$this->app->close();
@@ -250,7 +250,7 @@ class SnapshotsController extends ApiController
*/
public function download(): static
{
if (!$this->app->getIdentity()->authorise('core.manage', 'com_mokosuitebackup')) {
if (!$this->app->getIdentity()->authorise('mokosuitebackup.snapshot.manage', 'com_mokosuitebackup')) {
$this->app->setHeader('status', 403);
echo json_encode(['errors' => [['title' => 'Access denied']]]);
$this->app->close();
@@ -24,7 +24,6 @@ class JsonapiView extends BaseApiView
'origin',
'backup_type',
'archivename',
'absolute_path',
'total_size',
'db_size',
'files_count',
+94 -1
View File
@@ -21,7 +21,7 @@
type="sql"
label="COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_PROFILE"
description="COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_PROFILE_DESC"
query="SELECT id AS value, CONCAT(title, ' (#', id, ')') AS text FROM #__mokosuitebackup_profiles WHERE published = 1 ORDER BY ordering ASC"
query="SELECT id AS value, CONCAT(title, ' (#', id, ')') AS text FROM #__mokosuitebackup_profiles WHERE published = 1 ORDER BY id ASC"
default="1"
>
<option value="1">Default Backup Profile (#1)</option>
@@ -39,6 +39,73 @@
</field>
</fieldset>
<fieldset name="defaults" label="COM_MOKOJOOMBACKUP_CONFIG_DEFAULTS">
<field
name="default_archive_format"
type="list"
label="COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_FORMAT"
description="COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_FORMAT_DESC"
default="zip"
>
<option value="zip">ZIP</option>
<option value="tar.gz">tar.gz</option>
<option value="7z">7z</option>
</field>
<field
name="default_mokorestore"
type="list"
label="COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_MOKORESTORE"
description="COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_MOKORESTORE_DESC"
default="0"
>
<option value="0">COM_MOKOJOOMBACKUP_MOKORESTORE_NONE</option>
<option value="1">COM_MOKOJOOMBACKUP_MOKORESTORE_WRAPPED</option>
<option value="standalone">COM_MOKOJOOMBACKUP_MOKORESTORE_STANDALONE</option>
</field>
<field
name="default_sanitize_passwords"
type="radio"
label="COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_SANITIZE_PW"
description="COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_SANITIZE_PW_DESC"
default="0"
class="btn-group"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="default_sanitize_emails"
type="radio"
label="COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_SANITIZE_EMAIL"
description="COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_SANITIZE_EMAIL_DESC"
default="0"
class="btn-group"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="default_sanitize_sessions"
type="radio"
label="COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_SANITIZE_SESS"
description="COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_SANITIZE_SESS_DESC"
default="1"
class="btn-group"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="log_retention_days"
type="number"
label="COM_MOKOJOOMBACKUP_CONFIG_LOG_RETENTION"
description="COM_MOKOJOOMBACKUP_CONFIG_LOG_RETENTION_DESC"
default="90"
min="0"
max="365"
/>
</fieldset>
<fieldset name="webcron" label="COM_MOKOJOOMBACKUP_CONFIG_WEBCRON">
<field
name="webcron_secret"
@@ -172,6 +239,32 @@
</field>
</fieldset>
<fieldset name="ntfy" label="COM_MOKOJOOMBACKUP_CONFIG_NTFY">
<field
name="ntfy_server"
type="text"
label="COM_MOKOJOOMBACKUP_CONFIG_NTFY_SERVER"
description="COM_MOKOJOOMBACKUP_CONFIG_NTFY_SERVER_DESC"
default="https://ntfy.mokoconsulting.tech"
filter="url"
/>
<field
name="ntfy_topic"
type="text"
label="COM_MOKOJOOMBACKUP_CONFIG_NTFY_TOPIC"
description="COM_MOKOJOOMBACKUP_CONFIG_NTFY_TOPIC_DESC"
default=""
filter="string"
/>
<field
name="ntfy_token"
type="password"
label="COM_MOKOJOOMBACKUP_CONFIG_NTFY_TOKEN"
description="COM_MOKOJOOMBACKUP_CONFIG_NTFY_TOKEN_DESC"
default=""
/>
</fieldset>
<fieldset name="permissions" label="JCONFIG_PERMISSIONS_LABEL"
description="JCONFIG_PERMISSIONS_DESC">
<field
@@ -15,6 +15,7 @@
>
<option value="">COM_MOKOJOOMBACKUP_FILTER_STATUS_ALL</option>
<option value="complete">COM_MOKOJOOMBACKUP_STATUS_COMPLETE</option>
<option value="warning">COM_MOKOJOOMBACKUP_STATUS_WARNING</option>
<option value="running">COM_MOKOJOOMBACKUP_STATUS_RUNNING</option>
<option value="fail">COM_MOKOJOOMBACKUP_STATUS_FAIL</option>
<option value="pending">COM_MOKOJOOMBACKUP_STATUS_PENDING</option>
@@ -24,10 +24,9 @@
name="fullordering"
type="list"
label="JGLOBAL_SORT_BY"
default="a.ordering ASC"
default="a.id ASC"
onchange="this.form.submit();"
>
<option value="a.ordering ASC">JFIELD_ORDERING_LABEL_ASC</option>
<option value="a.title ASC">COM_MOKOJOOMBACKUP_HEADING_TITLE_ASC</option>
<option value="a.title DESC">COM_MOKOJOOMBACKUP_HEADING_TITLE_DESC</option>
<option value="a.id DESC">JGRID_HEADING_ID_DESC</option>
@@ -40,6 +40,7 @@
>
<option value="zip">ZIP</option>
<option value="tar.gz">tar.gz</option>
<option value="7z">COM_MOKOJOOMBACKUP_FORMAT_7Z</option>
</field>
<field
name="compression_level"
@@ -92,6 +93,16 @@
<option value="1">COM_MOKOJOOMBACKUP_MOKORESTORE_WRAPPED</option>
<option value="standalone">COM_MOKOJOOMBACKUP_MOKORESTORE_STANDALONE</option>
</field>
<field
name="restore_script_name"
type="text"
label="COM_MOKOJOOMBACKUP_FIELD_RESTORE_SCRIPT_NAME"
description="COM_MOKOJOOMBACKUP_FIELD_RESTORE_SCRIPT_NAME_DESC"
default="restore.php"
maxlength="128"
filter="string"
showon="include_mokorestore!:0"
/>
<field
name="encryption_password"
type="password"
@@ -163,12 +174,6 @@
<option value="1">JPUBLISHED</option>
<option value="0">JUNPUBLISHED</option>
</field>
<field
name="ordering"
type="number"
label="JFIELD_ORDERING_LABEL"
default="0"
/>
</fieldset>
<fieldset name="filters" label="COM_MOKOJOOMBACKUP_FIELDSET_FILTERS">
@@ -200,105 +205,9 @@
/>
</fieldset>
<fieldset name="remote" label="COM_MOKOJOOMBACKUP_FIELDSET_REMOTE">
<field
name="remote_storage"
type="list"
label="COM_MOKOJOOMBACKUP_FIELD_REMOTE_STORAGE"
description="COM_MOKOJOOMBACKUP_FIELD_REMOTE_STORAGE_DESC"
default="none"
>
<option value="none">COM_MOKOJOOMBACKUP_REMOTE_NONE</option>
<option value="sftp">COM_MOKOJOOMBACKUP_REMOTE_SFTP</option>
<option value="google_drive">COM_MOKOJOOMBACKUP_REMOTE_GDRIVE</option>
<option value="s3">COM_MOKOJOOMBACKUP_REMOTE_S3</option>
</field>
<field
name="remote_keep_local"
type="radio"
label="COM_MOKOJOOMBACKUP_FIELD_KEEP_LOCAL"
description="COM_MOKOJOOMBACKUP_FIELD_KEEP_LOCAL_DESC"
default="1"
class="btn-group"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<!-- SFTP fields (shown when remote_storage = sftp) -->
<field
name="sftp_host"
type="text"
label="COM_MOKOJOOMBACKUP_FIELD_SFTP_HOST"
description="COM_MOKOJOOMBACKUP_FIELD_SFTP_HOST_DESC"
maxlength="255"
showon="remote_storage:sftp"
/>
<field
name="sftp_port"
type="number"
label="COM_MOKOJOOMBACKUP_FIELD_SFTP_PORT"
description="COM_MOKOJOOMBACKUP_FIELD_SFTP_PORT_DESC"
default="22"
min="1"
max="65535"
showon="remote_storage:sftp"
/>
<field
name="sftp_username"
type="text"
label="COM_MOKOJOOMBACKUP_FIELD_SFTP_USERNAME"
description="COM_MOKOJOOMBACKUP_FIELD_SFTP_USERNAME_DESC"
maxlength="255"
showon="remote_storage:sftp"
/>
<field
name="sftp_auth_type"
type="list"
label="COM_MOKOJOOMBACKUP_FIELD_SFTP_AUTH_TYPE"
description="COM_MOKOJOOMBACKUP_FIELD_SFTP_AUTH_TYPE_DESC"
default="key"
showon="remote_storage:sftp"
>
<option value="password">COM_MOKOJOOMBACKUP_SFTP_AUTH_PASSWORD</option>
<option value="key">COM_MOKOJOOMBACKUP_SFTP_AUTH_KEY</option>
<option value="key_passphrase">COM_MOKOJOOMBACKUP_SFTP_AUTH_KEY_PASSPHRASE</option>
</field>
<field
name="sftp_password"
type="password"
label="COM_MOKOJOOMBACKUP_FIELD_SFTP_PASSWORD"
description="COM_MOKOJOOMBACKUP_FIELD_SFTP_PASSWORD_DESC"
maxlength="255"
showon="remote_storage:sftp[AND]sftp_auth_type:password"
/>
<field
name="sftp_key_data"
type="SshKey"
label="COM_MOKOJOOMBACKUP_FIELD_SFTP_KEY"
description="COM_MOKOJOOMBACKUP_FIELD_SFTP_KEY_DESC"
filter="raw"
showon="remote_storage:sftp[AND]sftp_auth_type:key,key_passphrase"
addfieldprefix="Joomla\Component\MokoSuiteBackup\Administrator\Field"
/>
<field
name="sftp_passphrase"
type="password"
label="COM_MOKOJOOMBACKUP_FIELD_SFTP_PASSPHRASE"
description="COM_MOKOJOOMBACKUP_FIELD_SFTP_PASSPHRASE_DESC"
maxlength="255"
showon="remote_storage:sftp[AND]sftp_auth_type:key_passphrase"
/>
<field
name="sftp_path"
type="text"
label="COM_MOKOJOOMBACKUP_FIELD_SFTP_PATH"
description="COM_MOKOJOOMBACKUP_FIELD_SFTP_PATH_DESC"
default="/backups"
maxlength="512"
showon="remote_storage:sftp"
/>
</fieldset>
<!-- The "Keep local copy" setting is now configured per remote destination
(in the Add/Edit Destination modal), so the profile-level field and its
"Remote" tab have been removed. -->
<fieldset name="retention" label="COM_MOKOJOOMBACKUP_FIELDSET_RETENTION">
<field
@@ -395,157 +304,4 @@
/>
</fieldset>
<fieldset name="ftp" label="COM_MOKOJOOMBACKUP_FIELDSET_FTP">
<field
name="ftp_host"
type="text"
label="COM_MOKOJOOMBACKUP_FIELD_FTP_HOST"
description="COM_MOKOJOOMBACKUP_FIELD_FTP_HOST_DESC"
maxlength="255"
showon="remote_storage:ftp"
/>
<field
name="ftp_port"
type="number"
label="COM_MOKOJOOMBACKUP_FIELD_FTP_PORT"
description="COM_MOKOJOOMBACKUP_FIELD_FTP_PORT_DESC"
default="21"
min="1"
max="65535"
showon="remote_storage:ftp"
/>
<field
name="ftp_username"
type="text"
label="COM_MOKOJOOMBACKUP_FIELD_FTP_USERNAME"
maxlength="255"
showon="remote_storage:ftp"
/>
<field
name="ftp_password"
type="password"
label="COM_MOKOJOOMBACKUP_FIELD_FTP_PASSWORD"
maxlength="255"
showon="remote_storage:ftp"
/>
<field
name="ftp_path"
type="text"
label="COM_MOKOJOOMBACKUP_FIELD_FTP_PATH"
description="COM_MOKOJOOMBACKUP_FIELD_FTP_PATH_DESC"
default="/backups"
maxlength="512"
showon="remote_storage:ftp"
/>
<field
name="ftp_passive"
type="radio"
label="COM_MOKOJOOMBACKUP_FIELD_FTP_PASSIVE"
description="COM_MOKOJOOMBACKUP_FIELD_FTP_PASSIVE_DESC"
default="1"
class="btn-group"
showon="remote_storage:ftp"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="ftp_ssl"
type="radio"
label="COM_MOKOJOOMBACKUP_FIELD_FTP_SSL"
description="COM_MOKOJOOMBACKUP_FIELD_FTP_SSL_DESC"
default="0"
class="btn-group"
showon="remote_storage:ftp"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
<fieldset name="google_drive" label="COM_MOKOJOOMBACKUP_FIELDSET_GDRIVE">
<field
name="gdrive_client_id"
type="text"
label="COM_MOKOJOOMBACKUP_FIELD_GDRIVE_CLIENT_ID"
description="COM_MOKOJOOMBACKUP_FIELD_GDRIVE_CLIENT_ID_DESC"
maxlength="255"
showon="remote_storage:google_drive"
/>
<field
name="gdrive_client_secret"
type="password"
label="COM_MOKOJOOMBACKUP_FIELD_GDRIVE_CLIENT_SECRET"
maxlength="255"
showon="remote_storage:google_drive"
/>
<field
name="gdrive_refresh_token"
type="text"
label="COM_MOKOJOOMBACKUP_FIELD_GDRIVE_REFRESH_TOKEN"
description="COM_MOKOJOOMBACKUP_FIELD_GDRIVE_REFRESH_TOKEN_DESC"
maxlength="512"
showon="remote_storage:google_drive"
/>
<field
name="gdrive_folder_id"
type="text"
label="COM_MOKOJOOMBACKUP_FIELD_GDRIVE_FOLDER_ID"
description="COM_MOKOJOOMBACKUP_FIELD_GDRIVE_FOLDER_ID_DESC"
maxlength="255"
showon="remote_storage:google_drive"
/>
</fieldset>
<fieldset name="s3" label="COM_MOKOJOOMBACKUP_FIELDSET_S3">
<field
name="s3_endpoint"
type="text"
label="COM_MOKOJOOMBACKUP_FIELD_S3_ENDPOINT"
description="COM_MOKOJOOMBACKUP_FIELD_S3_ENDPOINT_DESC"
maxlength="512"
hint="https://s3.amazonaws.com"
showon="remote_storage:s3"
/>
<field
name="s3_region"
type="text"
label="COM_MOKOJOOMBACKUP_FIELD_S3_REGION"
description="COM_MOKOJOOMBACKUP_FIELD_S3_REGION_DESC"
default="us-east-1"
maxlength="50"
showon="remote_storage:s3"
/>
<field
name="s3_access_key"
type="text"
label="COM_MOKOJOOMBACKUP_FIELD_S3_ACCESS_KEY"
maxlength="255"
showon="remote_storage:s3"
/>
<field
name="s3_secret_key"
type="password"
label="COM_MOKOJOOMBACKUP_FIELD_S3_SECRET_KEY"
maxlength="255"
showon="remote_storage:s3"
/>
<field
name="s3_bucket"
type="text"
label="COM_MOKOJOOMBACKUP_FIELD_S3_BUCKET"
description="COM_MOKOJOOMBACKUP_FIELD_S3_BUCKET_DESC"
maxlength="255"
showon="remote_storage:s3"
/>
<field
name="s3_path"
type="text"
label="COM_MOKOJOOMBACKUP_FIELD_S3_PATH"
description="COM_MOKOJOOMBACKUP_FIELD_S3_PATH_DESC"
default="/backups"
maxlength="512"
showon="remote_storage:s3"
/>
</fieldset>
</form>
@@ -5,6 +5,8 @@
; @license GPL-3.0-or-later
COM_MOKOJOOMBACKUP="MokoSuiteBackup"
COM_MOKOJOOMBACKUP_SHORT="Backup"
COM_MOKOJOOMBACKUP_CONFIGURATION="MokoSuiteBackup Options"
COM_MOKOJOOMBACKUP_DESCRIPTION="Full-site backup and restore for Joomla"
; Submenu
@@ -21,7 +23,7 @@ COM_MOKOSUITEBACKUP_ACTION_BACKUP_RESTORE="Restore Backup"
COM_MOKOSUITEBACKUP_ACTION_BACKUP_RESTORE_DESC="Allows users in this group to restore the site from a backup archive. This is a destructive operation that overwrites the current site."
; Dashboard view
COM_MOKOJOOMBACKUP_DASHBOARD_TITLE="MokoSuiteBackup Dashboard"
COM_MOKOJOOMBACKUP_DASHBOARD_TITLE="Dashboard"
COM_MOKOJOOMBACKUP_DASHBOARD_LAST_BACKUP="Last Backup"
COM_MOKOJOOMBACKUP_DASHBOARD_NO_BACKUPS="No backups yet"
COM_MOKOJOOMBACKUP_DASHBOARD_NEXT_SCHEDULED="Next Scheduled"
@@ -41,14 +43,16 @@ COM_MOKOJOOMBACKUP_DASHBOARD_STORAGE_BREAKDOWN="Storage by Profile"
COM_MOKOJOOMBACKUP_DASHBOARD_BACKUP_TREND="Backup Trend (30 days)"
; Backups view
COM_MOKOJOOMBACKUP_BACKUPS_TITLE="Backup Records"
COM_MOKOJOOMBACKUP_BACKUPS_N_ITEMS_DELETED="%d backup records deleted."
COM_MOKOJOOMBACKUP_BACKUPS_N_ITEMS_DELETED_1="%d backup record deleted."
COM_MOKOJOOMBACKUP_BACKUPS_TITLE="Records"
COM_MOKOJOOMBACKUP_BACKUPS_TABLE_CAPTION="Table of backup records"
COM_MOKOJOOMBACKUP_NO_BACKUPS="No backups found. Click 'Backup Now' to create your first backup."
COM_MOKOJOOMBACKUP_TOOLBAR_BACKUP_NOW="Backup Now"
COM_MOKOJOOMBACKUP_DOWNLOAD="Download"
; Backup detail view
COM_MOKOJOOMBACKUP_BACKUP_DETAIL="Backup Detail"
COM_MOKOJOOMBACKUP_BACKUP_DETAIL="Detail"
COM_MOKOJOOMBACKUP_VIEW_LOG="Backup Log"
COM_MOKOJOOMBACKUP_BROWSE_ARCHIVE="Browse Archive Contents"
COM_MOKOJOOMBACKUP_BROWSE_COL_NAME="Name"
@@ -72,7 +76,7 @@ COM_MOKOJOOMBACKUP_FIELD_DB_SIZE="DB Size"
COM_MOKOJOOMBACKUP_FIELD_REMOTE="Remote Path"
; Profiles view
COM_MOKOJOOMBACKUP_PROFILES_TITLE="Backup Profiles"
COM_MOKOJOOMBACKUP_PROFILES_TITLE="Profiles"
COM_MOKOJOOMBACKUP_PROFILES_TABLE_CAPTION="Table of backup profiles"
COM_MOKOJOOMBACKUP_NO_PROFILES="No backup profiles found."
COM_MOKOJOOMBACKUP_PROFILE_NEW="New Profile"
@@ -119,6 +123,7 @@ COM_MOKOJOOMBACKUP_FIELD_TABLES_COUNT="Tables Count"
; Archive settings
COM_MOKOJOOMBACKUP_FIELD_ARCHIVE_FORMAT="Archive Format"
COM_MOKOJOOMBACKUP_FIELD_ARCHIVE_FORMAT_DESC="Format for the backup archive file"
COM_MOKOJOOMBACKUP_FORMAT_7Z="7z (requires 7za CLI)"
COM_MOKOJOOMBACKUP_FIELD_COMPRESSION="Compression Level"
COM_MOKOJOOMBACKUP_FIELD_COMPRESSION_DESC="Higher compression = smaller file but slower"
COM_MOKOJOOMBACKUP_COMPRESSION_NONE="None (fastest)"
@@ -126,29 +131,31 @@ COM_MOKOJOOMBACKUP_COMPRESSION_FASTEST="Low (fast)"
COM_MOKOJOOMBACKUP_COMPRESSION_NORMAL="Normal (balanced)"
COM_MOKOJOOMBACKUP_COMPRESSION_BEST="Maximum (smallest)"
COM_MOKOJOOMBACKUP_FIELD_ENCRYPTION_PASSWORD="Encryption Password"
COM_MOKOJOOMBACKUP_FIELD_ENCRYPTION_PASSWORD_DESC="Set a password to encrypt the backup archive with AES-256. Leave blank for no encryption. Required to restore encrypted backups."
COM_MOKOJOOMBACKUP_FIELD_ENCRYPTION_PASSWORD_DESC="AES-256 encryption password. Leave blank for no encryption. Required to restore."
COM_MOKOJOOMBACKUP_FIELD_SPLIT_SIZE="Split Size (MB)"
COM_MOKOJOOMBACKUP_FIELD_SPLIT_SIZE_DESC="Split archive into parts of this size in MB. 0 = no splitting."
COM_MOKOJOOMBACKUP_FIELD_BACKUP_DIR="Backup Directory"
COM_MOKOJOOMBACKUP_FIELD_BACKUP_DIR_DESC="Directory where backup archives are stored. Supports placeholders: [HOME] (user home directory), [HOST], [DATE], [YEAR], [MONTH], [DAY], [PROFILE_NAME], [SITE_NAME], [TYPE]. Use [HOME]/backups to store outside the web root. Absolute paths (starting with /) are used as-is; relative paths resolve from the Joomla root."
COM_MOKOJOOMBACKUP_FIELD_BACKUP_DIR_DESC="Where backups are stored. Use placeholders like [HOME]/backups for portability. Click the ? icon for full documentation."
COM_MOKOJOOMBACKUP_FIELD_ARCHIVE_NAME_FORMAT="Archive Name Format"
COM_MOKOJOOMBACKUP_FIELD_ARCHIVE_NAME_FORMAT_DESC="Filename template for backup archives (without extension). Placeholders: [HOST] hostname, [DATE] Ymd, [TIME] His, [DATETIME] Ymd_His, [YEAR] [MONTH] [DAY] [HOUR] [MINUTE] [SECOND], [PROFILE_ID], [PROFILE_NAME], [SITE_NAME], [TYPE], [RANDOM]."
COM_MOKOJOOMBACKUP_FIELD_ARCHIVE_NAME_FORMAT_DESC="Filename template (without extension). Click the placeholder buttons below to insert tokens."
COM_MOKOJOOMBACKUP_FIELD_INCLUDE_MOKORESTORE="MokoRestore Script"
COM_MOKOJOOMBACKUP_FIELD_INCLUDE_MOKORESTORE_DESC="Include the MokoRestore standalone restore wizard. 'Wrapped' bundles it inside the backup ZIP. 'Standalone' generates a separate restore.php that scans for backup ZIPs in its directory — ideal for remote servers."
COM_MOKOJOOMBACKUP_FIELD_INCLUDE_MOKORESTORE_DESC="None: no restore script. Wrapped: bundled inside the ZIP. Standalone: separate restore.php file (ideal for remote servers)."
COM_MOKOJOOMBACKUP_MOKORESTORE_NONE="None"
COM_MOKOJOOMBACKUP_MOKORESTORE_WRAPPED="Wrapped (inside backup ZIP)"
COM_MOKOJOOMBACKUP_MOKORESTORE_STANDALONE="Standalone (separate restore.php)"
COM_MOKOJOOMBACKUP_FIELD_RESTORE_SCRIPT_NAME="Restore Script Filename"
COM_MOKOJOOMBACKUP_FIELD_RESTORE_SCRIPT_NAME_DESC="Custom filename for the restore script. Must end in .php. Use a non-obvious name to reduce discoverability on remote servers (e.g. moko-install-xyz.php)."
; Data Sanitization
COM_MOKOJOOMBACKUP_FIELDSET_SANITIZATION="Data Sanitization"
COM_MOKOJOOMBACKUP_FIELD_SANITIZE_PASSWORDS="Sanitize User Passwords"
COM_MOKOJOOMBACKUP_FIELD_SANITIZE_PASSWORDS_DESC="Replace all user password hashes with an invalid value. Users will not be able to log in with the restored backup without resetting their password. Ideal for sharing backups, creating demo/staging sites, or GDPR compliance."
COM_MOKOJOOMBACKUP_FIELD_SANITIZE_PASSWORDS_DESC="Replace password hashes with invalid values. Users must reset passwords after restore. For demos, staging, or GDPR."
COM_MOKOJOOMBACKUP_FIELD_PRESERVE_SUPER_ADMIN="Preserve Super Admin Password"
COM_MOKOJOOMBACKUP_FIELD_PRESERVE_SUPER_ADMIN_DESC="Keep the password for Super Users (group ID 8) intact. You will still be able to log in as a Super Admin after restoring."
COM_MOKOJOOMBACKUP_FIELD_SANITIZE_EMAILS="Sanitize User Emails"
COM_MOKOJOOMBACKUP_FIELD_SANITIZE_EMAILS_DESC="Replace all user email addresses with dummy values (user123@sanitized.example.com). Prevents accidental emails being sent to real users from a cloned/staging site. Super admin emails are preserved if 'Preserve Super Admin' is enabled."
COM_MOKOJOOMBACKUP_FIELD_SANITIZE_EMAILS_DESC="Replace emails with dummy values. Prevents accidental emails from cloned sites. Super admin preserved if enabled above."
COM_MOKOJOOMBACKUP_FIELD_SANITIZE_SESSIONS="Clear Session Data"
COM_MOKOJOOMBACKUP_FIELD_SANITIZE_SESSIONS_DESC="Exclude active session data from the backup. This logs out all users and prevents session hijacking when the backup is restored on another server. Enabled by default."
COM_MOKOJOOMBACKUP_FIELD_SANITIZE_SESSIONS_DESC="Exclude session data. Logs out all users on restore, prevents session hijacking. Enabled by default."
; Exclusion filter fields
COM_MOKOJOOMBACKUP_FIELD_EXCLUDE_DIRS="Exclude Directories"
@@ -201,6 +208,7 @@ COM_MOKOJOOMBACKUP_TYPE_DIFFERENTIAL="Differential (changed files + full DB)"
; Status labels
COM_MOKOJOOMBACKUP_STATUS_COMPLETE="Complete"
COM_MOKOJOOMBACKUP_STATUS_WARNING="Warning"
COM_MOKOJOOMBACKUP_STATUS_RUNNING="Running"
COM_MOKOJOOMBACKUP_STATUS_FAIL="Failed"
COM_MOKOJOOMBACKUP_STATUS_PENDING="Pending"
@@ -243,9 +251,9 @@ COM_MOKOJOOMBACKUP_FIELD_NOTIFY_FAILURE_DESC="Send an email when a backup fails.
; Retention
COM_MOKOJOOMBACKUP_FIELDSET_RETENTION="Retention"
COM_MOKOJOOMBACKUP_FIELD_RETENTION_DAYS="Keep Backups (days)"
COM_MOKOJOOMBACKUP_FIELD_RETENTION_DAYS_DESC="Delete completed backups from this profile older than this many days. Set to 0 to use the global default from component options."
COM_MOKOJOOMBACKUP_FIELD_RETENTION_DAYS_DESC="Delete completed backups from this profile older than this many days. Set to 0 for unlimited (keep by age disabled)."
COM_MOKOJOOMBACKUP_FIELD_RETENTION_COUNT="Keep Backups (count)"
COM_MOKOJOOMBACKUP_FIELD_RETENTION_COUNT_DESC="Maximum number of completed backups to keep for this profile. Oldest are removed first. Set to 0 to use the global default from component options."
COM_MOKOJOOMBACKUP_FIELD_RETENTION_COUNT_DESC="Maximum number of completed backups to keep for this profile. Oldest are removed first. Set to 0 for unlimited (keep by count disabled)."
COM_MOKOJOOMBACKUP_FIELD_NTFY_SPACER_DESC="<strong>Push Notifications (ntfy)</strong> — Send instant push notifications to your phone or desktop via <a href='https://ntfy.sh' target='_blank'>ntfy.sh</a> or a self-hosted ntfy server."
COM_MOKOJOOMBACKUP_FIELD_NTFY_TOPIC="ntfy Topic"
@@ -274,9 +282,9 @@ COM_MOKOJOOMBACKUP_FIELD_SFTP_PORT_DESC="SSH port (default: 22)"
COM_MOKOJOOMBACKUP_FIELD_SFTP_USERNAME="SSH Username"
COM_MOKOJOOMBACKUP_FIELD_SFTP_USERNAME_DESC="Username for SSH authentication"
COM_MOKOJOOMBACKUP_FIELD_SFTP_PASSWORD="SSH Password"
COM_MOKOJOOMBACKUP_FIELD_SFTP_PASSWORD_DESC="Password for SSH authentication. Leave blank if using a key file."
COM_MOKOJOOMBACKUP_FIELD_SFTP_PASSWORD_DESC="Password for SSH authentication."
COM_MOKOJOOMBACKUP_FIELD_SFTP_KEY="SSH Private Key"
COM_MOKOJOOMBACKUP_FIELD_SFTP_KEY_DESC="Upload or paste your SSH private key (e.g. id_rsa or id_ed25519). The key is stored securely in the database and written to a temp file with 0600 permissions only during upload, then deleted. Leave blank to use password authentication."
COM_MOKOJOOMBACKUP_FIELD_SFTP_KEY_DESC="Upload your SSH private key (id_rsa, id_ed25519). Stored base64-encoded in DB, written to temp file during upload only."
COM_MOKOJOOMBACKUP_FIELD_SFTP_KEY_UPLOAD="Upload Key File"
COM_MOKOJOOMBACKUP_FIELD_SFTP_KEY_REPLACE="Replace Key"
COM_MOKOJOOMBACKUP_FIELD_SFTP_KEY_LOADED="Key loaded"
@@ -413,6 +421,40 @@ COM_MOKOJOOMBACKUP_SNAPSHOTS_N_DELETED="%d snapshot(s) deleted."
COM_MOKOJOOMBACKUP_SNAPSHOTS_1_DELETED="1 snapshot deleted."
COM_MOKOJOOMBACKUP_SNAPSHOTS_DELETE_ERRORS="Failed to delete snapshot(s): %s"
; Component Options — Defaults
COM_MOKOJOOMBACKUP_CONFIG_DEFAULTS="Profile Defaults"
COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_FORMAT="Default Archive Format"
COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_FORMAT_DESC="Archive format used when creating new profiles. Can be overridden per profile."
COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_MOKORESTORE="Default MokoRestore Mode"
COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_MOKORESTORE_DESC="MokoRestore mode for new profiles. None, Wrapped (inside ZIP), or Standalone (separate file)."
COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_SANITIZE_PW="Default: Sanitize Passwords"
COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_SANITIZE_PW_DESC="Whether new profiles should sanitize user passwords by default."
COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_SANITIZE_EMAIL="Default: Sanitize Emails"
COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_SANITIZE_EMAIL_DESC="Whether new profiles should sanitize user emails by default."
COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_SANITIZE_SESS="Default: Clear Sessions"
COM_MOKOJOOMBACKUP_CONFIG_DEFAULT_SANITIZE_SESS_DESC="Whether new profiles should clear session data by default."
COM_MOKOJOOMBACKUP_CONFIG_LOG_RETENTION="Log Retention (days)"
COM_MOKOJOOMBACKUP_CONFIG_LOG_RETENTION_DESC="Days to keep .log files alongside backup archives. Set to 0 for unlimited."
; Component Options — ntfy
COM_MOKOJOOMBACKUP_CONFIG_NTFY="Push Notifications (ntfy)"
COM_MOKOJOOMBACKUP_CONFIG_NTFY_SERVER="Global ntfy Server"
COM_MOKOJOOMBACKUP_CONFIG_NTFY_SERVER_DESC="Default ntfy server URL. Per-profile settings override this."
COM_MOKOJOOMBACKUP_CONFIG_NTFY_TOPIC="Global ntfy Topic"
COM_MOKOJOOMBACKUP_CONFIG_NTFY_TOPIC_DESC="Default ntfy topic for backup notifications. Per-profile settings override this."
COM_MOKOJOOMBACKUP_CONFIG_NTFY_TOKEN="Global ntfy Token"
COM_MOKOJOOMBACKUP_CONFIG_NTFY_TOKEN_DESC="Default access token for private ntfy topics. Per-profile settings override this."
; ACL — additional actions
COM_MOKOSUITEBACKUP_ACTION_BACKUP_PURGE="Purge Old Backups"
COM_MOKOSUITEBACKUP_ACTION_BACKUP_PURGE_DESC="Allows users to bulk-delete backups older than a specific date."
COM_MOKOSUITEBACKUP_ACTION_BACKUP_COMPARE="Compare Backups"
COM_MOKOSUITEBACKUP_ACTION_BACKUP_COMPARE_DESC="Allows users to compare two backup records side-by-side."
COM_MOKOSUITEBACKUP_ACTION_BACKUP_BROWSE="Browse Archives"
COM_MOKOSUITEBACKUP_ACTION_BACKUP_BROWSE_DESC="Allows users to view file listings inside backup archives without extracting."
COM_MOKOSUITEBACKUP_ACTION_BACKUP_CANCEL="Cancel Stalled Backup"
COM_MOKOSUITEBACKUP_ACTION_BACKUP_CANCEL_DESC="Allows users to cancel backup records stuck in running status and clean up partial archive files."
; Snapshot ACL
COM_MOKOSUITEBACKUP_ACTION_SNAPSHOT_MANAGE="Manage Snapshots"
COM_MOKOSUITEBACKUP_ACTION_SNAPSHOT_MANAGE_DESC="Allows users in this group to create and restore content snapshots. Snapshots only affect articles, categories, and modules — not the full site."
@@ -449,6 +491,34 @@ COM_MOKOJOOMBACKUP_SELECT_ALL="Select All"
COM_MOKOJOOMBACKUP_SNAPSHOT_RESTORE_SELECTED="Restore Selected"
COM_MOKOJOOMBACKUP_SNAPSHOT_NO_ARTICLES_SELECTED="No articles selected for restore."
; Purge
COM_MOKOJOOMBACKUP_TOOLBAR_PURGE="Purge Old Backups"
COM_MOKOJOOMBACKUP_PURGE_TITLE="Purge Old Backups"
COM_MOKOJOOMBACKUP_PURGE_DESC="Delete all completed backup records older than the selected date. This permanently removes archive files, log files, and database records."
COM_MOKOJOOMBACKUP_PURGE_DATE_LABEL="Delete all backups before this date"
COM_MOKOJOOMBACKUP_PURGE_SUBMIT="Purge Backups"
COM_MOKOJOOMBACKUP_PURGE_CONFIRM="Are you sure? This action cannot be undone."
COM_MOKOJOOMBACKUP_PURGE_COUNT_MSG="This will permanently delete %d backup(s) and their archive files."
COM_MOKOJOOMBACKUP_PURGE_NONE_FOUND="No completed backups found before the selected date."
COM_MOKOJOOMBACKUP_PURGE_INVALID_DATE="Invalid date. Please select a valid date."
COM_MOKOJOOMBACKUP_PURGE_SUCCESS="%d backup(s) purged successfully."
COM_MOKOJOOMBACKUP_PURGE_PARTIAL="%d backup(s) purged, but %d could not be deleted."
; Cancel Stalled Backup
COM_MOKOJOOMBACKUP_TOOLBAR_CANCEL_STALLED="Cancel Stalled"
COM_MOKOJOOMBACKUP_CANCEL_NONE_SELECTED="No backup records selected."
COM_MOKOJOOMBACKUP_CANCEL_NONE_RUNNING="None of the selected backups are in running status."
COM_MOKOJOOMBACKUP_CANCEL_SUCCESS="%d stalled backup(s) cancelled."
; Remote Destinations (multi-remote)
COM_MOKOJOOMBACKUP_REMOTE_DESTINATIONS="Remote Destinations"
COM_MOKOJOOMBACKUP_REMOTE_ADD="Add Destination"
COM_MOKOJOOMBACKUP_REMOTE_EDIT="Edit Destination"
COM_MOKOJOOMBACKUP_REMOTE_ENABLED="Enabled"
COM_MOKOJOOMBACKUP_REMOTE_NONE_CONFIGURED="No remote destinations configured. Use 'Add Destination' to send backups to SFTP, S3, or Google Drive."
COM_MOKOJOOMBACKUP_REMOTE_LEGACY_NOTE="Legacy single-remote fields below are hidden when remote destinations are configured above. Existing legacy settings continue to work as a fallback."
COM_MOKOJOOMBACKUP_REMOTE_DELETE_CONFIRM="Are you sure you want to delete this remote destination?"
; Errors
COM_MOKOJOOMBACKUP_ERROR_FILE_NOT_FOUND="Backup archive file not found or has been deleted."
COM_MOKOJOOMBACKUP_ERROR_NO_RECORD_SELECTED="No backup record selected for restore."
@@ -5,6 +5,7 @@
; @license GPL-3.0-or-later
COM_MOKOJOOMBACKUP="MokoSuiteBackup"
COM_MOKOJOOMBACKUP_SHORT="Backup"
COM_MOKOJOOMBACKUP_DESCRIPTION="Full-site backup and restore for Joomla — database, files, and configuration."
COM_MOKOJOOMBACKUP_SUBMENU_DASHBOARD="Dashboard"
COM_MOKOJOOMBACKUP_SUBMENU_BACKUPS="Backup Records"
@@ -5,6 +5,7 @@
; @license GPL-3.0-or-later
COM_MOKOJOOMBACKUP="MokoSuiteBackup"
COM_MOKOJOOMBACKUP_SHORT="Backup"
COM_MOKOJOOMBACKUP_DESCRIPTION="Full-site backup and restore for Joomla"
COM_MOKOJOOMBACKUP_SUBMENU_DASHBOARD="Dashboard"
COM_MOKOJOOMBACKUP_SUBMENU_BACKUPS="Backup Records"
@@ -18,7 +19,7 @@ COM_MOKOSUITEBACKUP_ACTION_BACKUP_DOWNLOAD_DESC="Allows users in this group to d
COM_MOKOSUITEBACKUP_ACTION_BACKUP_RESTORE="Restore Backup"
COM_MOKOSUITEBACKUP_ACTION_BACKUP_RESTORE_DESC="Allows users in this group to restore the site from a backup archive. This is a destructive operation that overwrites the current site."
COM_MOKOJOOMBACKUP_DASHBOARD_TITLE="MokoSuiteBackup Dashboard"
COM_MOKOJOOMBACKUP_DASHBOARD_TITLE="Dashboard"
COM_MOKOJOOMBACKUP_DASHBOARD_LAST_BACKUP="Last Backup"
COM_MOKOJOOMBACKUP_DASHBOARD_NO_BACKUPS="No backups yet"
COM_MOKOJOOMBACKUP_DASHBOARD_NEXT_SCHEDULED="Next Scheduled"
@@ -30,8 +31,8 @@ COM_MOKOJOOMBACKUP_DASHBOARD_QUICK_ACTIONS="Quick Actions"
COM_MOKOJOOMBACKUP_DASHBOARD_SCHEDULED_TASKS="Scheduled Tasks"
COM_MOKOJOOMBACKUP_DASHBOARD_UPDATE_SITE="Update Site"
COM_MOKOJOOMBACKUP_DASHBOARD_SYSTEM_HEALTH="System Health"
COM_MOKOJOOMBACKUP_BACKUPS_TITLE="Backup Records"
COM_MOKOJOOMBACKUP_PROFILES_TITLE="Backup Profiles"
COM_MOKOJOOMBACKUP_BACKUPS_TITLE="Records"
COM_MOKOJOOMBACKUP_PROFILES_TITLE="Profiles"
COM_MOKOJOOMBACKUP_TOOLBAR_BACKUP_NOW="Backup Now"
COM_MOKOJOOMBACKUP_NO_BACKUPS="No backups found. Click 'Backup Now' to create your first backup."
COM_MOKOJOOMBACKUP_NO_PROFILES="No backup profiles found."
@@ -103,3 +104,40 @@ COM_MOKOJOOMBACKUP_FIELD_DB_SIZE="DB Size"
COM_MOKOJOOMBACKUP_FIELD_REMOTE="Remote Path"
COM_MOKOJOOMBACKUP_FIELD_NOTIFY_USER_GROUPS="Notify User Groups"
COM_MOKOJOOMBACKUP_FIELD_NOTIFY_USER_GROUPS_DESC="Select Joomla user groups whose members will receive backup notifications. Combined with email addresses above."
; Purge
COM_MOKOJOOMBACKUP_TOOLBAR_PURGE="Purge Old Backups"
COM_MOKOJOOMBACKUP_PURGE_TITLE="Purge Old Backups"
COM_MOKOJOOMBACKUP_PURGE_DESC="Delete all completed backup records older than the selected date. This permanently removes archive files, log files, and database records."
COM_MOKOJOOMBACKUP_PURGE_DATE_LABEL="Delete all backups before this date"
COM_MOKOJOOMBACKUP_PURGE_SUBMIT="Purge Backups"
COM_MOKOJOOMBACKUP_PURGE_CONFIRM="Are you sure? This action cannot be undone."
COM_MOKOJOOMBACKUP_PURGE_COUNT_MSG="This will permanently delete %d backup(s) and their archive files."
COM_MOKOJOOMBACKUP_PURGE_NONE_FOUND="No completed backups found before the selected date."
COM_MOKOJOOMBACKUP_PURGE_INVALID_DATE="Invalid date. Please select a valid date."
COM_MOKOJOOMBACKUP_PURGE_SUCCESS="%d backup(s) purged successfully."
COM_MOKOJOOMBACKUP_PURGE_PARTIAL="%d backup(s) purged, but %d could not be deleted."
; Cancel Stalled Backup
COM_MOKOJOOMBACKUP_TOOLBAR_CANCEL_STALLED="Cancel Stalled"
COM_MOKOJOOMBACKUP_CANCEL_NONE_SELECTED="No backup records selected."
COM_MOKOJOOMBACKUP_CANCEL_NONE_RUNNING="None of the selected backups are in running status."
COM_MOKOJOOMBACKUP_CANCEL_SUCCESS="%d stalled backup(s) cancelled."
; Backup status
COM_MOKOJOOMBACKUP_STATUS_WARNING="Warning"
; Delete feedback
COM_MOKOJOOMBACKUP_BACKUPS_N_ITEMS_DELETED="%d backup records deleted."
COM_MOKOJOOMBACKUP_BACKUPS_N_ITEMS_DELETED_1="%d backup record deleted."
; ACL - Cancel
COM_MOKOSUITEBACKUP_ACTION_BACKUP_CANCEL="Cancel Stalled Backup"
COM_MOKOSUITEBACKUP_ACTION_BACKUP_CANCEL_DESC="Allows users to cancel backup records stuck in running status and clean up partial archive files."
; Retention (per-profile)
COM_MOKOJOOMBACKUP_FIELDSET_RETENTION="Retention"
COM_MOKOJOOMBACKUP_FIELD_RETENTION_DAYS="Keep Backups (days)"
COM_MOKOJOOMBACKUP_FIELD_RETENTION_DAYS_DESC="Delete completed backups from this profile older than this many days. Set to 0 for unlimited (keep by age disabled)."
COM_MOKOJOOMBACKUP_FIELD_RETENTION_COUNT="Keep Backups (count)"
COM_MOKOJOOMBACKUP_FIELD_RETENTION_COUNT_DESC="Maximum number of completed backups to keep for this profile. Oldest are removed first. Set to 0 for unlimited (keep by count disabled)."
@@ -5,6 +5,7 @@
; @license GPL-3.0-or-later
COM_MOKOJOOMBACKUP="MokoSuiteBackup"
COM_MOKOJOOMBACKUP_SHORT="Backup"
COM_MOKOJOOMBACKUP_DESCRIPTION="Full-site backup and restore for Joomla — database, files, and configuration."
COM_MOKOJOOMBACKUP_SUBMENU_DASHBOARD="Dashboard"
COM_MOKOJOOMBACKUP_SUBMENU_BACKUPS="Backup Records"
@@ -0,0 +1,33 @@
/**
* MokoSuiteBackup — admin styles (loaded via the Joomla Web Asset Manager).
*/
/* Add/Edit Destination modal.
* The modal content is wrapped in a Bootstrap .container-fluid because
* Bootstrap's .modal-content has no padding of its own. Give that container a
* single, comfortable 1rem frame and drop the inner sections' horizontal padding
* so it isn't doubled. */
#remoteModal .modal-content > .container-fluid {
padding: 1rem;
}
#remoteModal .modal-header,
#remoteModal .modal-body,
#remoteModal .modal-footer {
padding-left: 0;
padding-right: 0;
}
#remoteModal .modal-body .row + .row,
#remoteModal .remote-type-fields {
margin-top: 0.25rem;
}
#remoteModal hr {
margin: 1rem 0;
opacity: 0.12;
}
#remoteModal .form-label {
margin-bottom: 0.35rem;
}
@@ -0,0 +1,14 @@
{
"$schema": "https://developer.joomla.org/schemas/json-schema/web_assets.json",
"name": "com_mokosuitebackup",
"version": "1.0.0",
"description": "MokoSuiteBackup web assets",
"license": "GPL-3.0-or-later",
"assets": [
{
"name": "com_mokosuitebackup.admin",
"type": "style",
"uri": "com_mokosuitebackup/css/admin.css"
}
]
}
@@ -6,15 +6,25 @@
* @license GNU General Public License version 3 or later; see LICENSE
-->
<extension type="component" method="upgrade">
<!--
IMPORTANT: a component's <name> drives the Joomla-derived extension
element (com_ + sanitized name), so it MUST stay element-safe:
"MokoSuiteBackup" -> com_mokosuitebackup. Do NOT apply the "Type - Name"
display convention here — "Component - MokoSuiteBackup" derives
com_component-mokosuitebackup, which registers a duplicate component and
orphans the real one. Packages are exempt because they set the element
via <packagename>; plugins/modules are exempt because <name> is only a
display label there.
-->
<name>MokoSuiteBackup</name>
<version>01.39.00</version>
<version>02.58.05</version>
<creationDate>2026-06-02</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
<authorUrl>https://mokoconsulting.tech</authorUrl>
<copyright>Copyright (C) 2026 Moko Consulting. All rights reserved.</copyright>
<license>GPL-3.0-or-later</license>
<description>COM_MOKOJOOMBACKUP_DESCRIPTION</description>
<description>Full-site backup and restore for Joomla — database, files, and configuration.</description>
<namespace path="src">Joomla\Component\MokoSuiteBackup</namespace>
@@ -37,20 +47,20 @@
</update>
<administration>
<menu img="class:archive">COM_MOKOJOOMBACKUP</menu>
<menu img="class:archive">COM_MOKOJOOMBACKUP_SHORT</menu>
<submenu>
<menu link="option=com_mokosuitebackup&amp;view=dashboard"
img="class:home"
alt="Dashboard">COM_MOKOJOOMBACKUP_SUBMENU_DASHBOARD</menu>
alt="Dashboard">Dashboard</menu>
<menu link="option=com_mokosuitebackup&amp;view=backups"
img="class:database"
alt="Backups">COM_MOKOJOOMBACKUP_SUBMENU_BACKUPS</menu>
alt="Backups">Backup Records</menu>
<menu link="option=com_mokosuitebackup&amp;view=snapshots"
img="class:camera"
alt="Snapshots">COM_MOKOJOOMBACKUP_SUBMENU_SNAPSHOTS</menu>
alt="Snapshots">Content Snapshots</menu>
<menu link="option=com_mokosuitebackup&amp;view=profiles"
img="class:cog"
alt="Profiles">COM_MOKOJOOMBACKUP_SUBMENU_PROFILES</menu>
alt="Profiles">Backup Profiles</menu>
</submenu>
<files folder=".">
<filename>access.xml</filename>
@@ -68,6 +78,11 @@
</languages>
</administration>
<media destination="com_mokosuitebackup" folder="media">
<folder>css</folder>
<filename>joomla.asset.json</filename>
</media>
<api>
<files folder="api">
<folder>src</folder>
@@ -11,35 +11,10 @@ CREATE TABLE IF NOT EXISTS `#__mokosuitebackup_profiles` (
`exclude_dirs` TEXT NOT NULL COMMENT 'Newline-separated directory paths to exclude',
`exclude_files` TEXT NOT NULL COMMENT 'Newline-separated filename patterns to exclude',
`exclude_tables` TEXT NOT NULL COMMENT 'Newline-separated table names to exclude',
`remote_storage` VARCHAR(20) NOT NULL DEFAULT 'none' COMMENT 'none, ftp, google_drive, s3',
`ftp_host` VARCHAR(255) NOT NULL DEFAULT '',
`ftp_port` INT(5) UNSIGNED NOT NULL DEFAULT 21,
`ftp_username` VARCHAR(255) NOT NULL DEFAULT '',
`ftp_password` VARCHAR(255) NOT NULL DEFAULT '',
`ftp_path` VARCHAR(512) NOT NULL DEFAULT '/backups',
`ftp_passive` TINYINT(1) NOT NULL DEFAULT 1,
`ftp_ssl` TINYINT(1) NOT NULL DEFAULT 0,
`sftp_host` VARCHAR(255) NOT NULL DEFAULT '',
`sftp_port` INT(5) UNSIGNED NOT NULL DEFAULT 22,
`sftp_username` VARCHAR(255) NOT NULL DEFAULT '',
`sftp_auth_type` VARCHAR(20) NOT NULL DEFAULT 'key',
`sftp_password` VARCHAR(255) NOT NULL DEFAULT '',
`sftp_key_data` MEDIUMTEXT,
`sftp_passphrase` VARCHAR(255) NOT NULL DEFAULT '',
`sftp_path` VARCHAR(512) NOT NULL DEFAULT '/backups',
`gdrive_client_id` VARCHAR(255) NOT NULL DEFAULT '',
`gdrive_client_secret` VARCHAR(255) NOT NULL DEFAULT '',
`gdrive_refresh_token` VARCHAR(512) NOT NULL DEFAULT '',
`gdrive_folder_id` VARCHAR(255) NOT NULL DEFAULT '',
`s3_endpoint` VARCHAR(512) NOT NULL DEFAULT '' COMMENT 'S3 endpoint URL (blank = AWS default)',
`s3_region` VARCHAR(50) NOT NULL DEFAULT 'us-east-1',
`s3_access_key` VARCHAR(255) NOT NULL DEFAULT '',
`s3_secret_key` VARCHAR(255) NOT NULL DEFAULT '',
`s3_bucket` VARCHAR(255) NOT NULL DEFAULT '',
`s3_path` VARCHAR(512) NOT NULL DEFAULT '/backups',
`remote_keep_local` TINYINT(1) NOT NULL DEFAULT 1 COMMENT 'Keep local copy after upload',
`encryption_password` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'AES-256 archive encryption password (blank = no encryption)',
`include_mokorestore` VARCHAR(20) NOT NULL DEFAULT '0' COMMENT 'MokoRestore mode: 0=none, 1=wrapped, standalone',
`restore_script_name` VARCHAR(100) NOT NULL DEFAULT 'restore.php' COMMENT 'Custom restore script filename',
`sanitize_passwords` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Replace user password hashes with invalid value',
`preserve_super_admin` TINYINT(1) NOT NULL DEFAULT 1 COMMENT 'Keep super admin password when sanitizing',
`sanitize_emails` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Replace user emails with dummy values',
@@ -48,13 +23,12 @@ CREATE TABLE IF NOT EXISTS `#__mokosuitebackup_profiles` (
`notify_user_groups` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'Comma-separated Joomla user group IDs',
`notify_on_success` TINYINT(1) NOT NULL DEFAULT 0,
`notify_on_failure` TINYINT(1) NOT NULL DEFAULT 1,
`retention_days` INT(11) NOT NULL DEFAULT 0 COMMENT '0 = use global default',
`retention_count` INT(11) NOT NULL DEFAULT 0 COMMENT '0 = use global default',
`retention_days` INT(11) NOT NULL DEFAULT 0 COMMENT 'Delete backups older than N days; 0 = unlimited',
`retention_count` INT(11) NOT NULL DEFAULT 0 COMMENT 'Keep newest N backups; 0 = unlimited',
`ntfy_topic` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'ntfy topic name',
`ntfy_server` VARCHAR(512) NOT NULL DEFAULT 'https://ntfy.sh' COMMENT 'ntfy server URL',
`ntfy_token` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'ntfy access token (optional)',
`published` TINYINT(1) NOT NULL DEFAULT 1,
`ordering` INT(11) NOT NULL DEFAULT 0,
`created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
`modified` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
@@ -65,7 +39,7 @@ CREATE TABLE IF NOT EXISTS `#__mokosuitebackup_records` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`profile_id` INT(11) UNSIGNED NOT NULL DEFAULT 1,
`description` VARCHAR(255) NOT NULL DEFAULT '',
`status` VARCHAR(20) NOT NULL DEFAULT 'pending' COMMENT 'pending, running, complete, fail',
`status` VARCHAR(20) NOT NULL DEFAULT 'pending' COMMENT 'pending, running, complete, warning, fail',
`origin` VARCHAR(20) NOT NULL DEFAULT 'backend' COMMENT 'backend, cli, api, scheduled',
`backup_type` VARCHAR(20) NOT NULL DEFAULT 'full' COMMENT 'full, database, files',
`archivename` VARCHAR(512) NOT NULL DEFAULT '',
@@ -107,17 +81,32 @@ CREATE TABLE IF NOT EXISTS `#__mokosuitebackup_snapshots` (
KEY `idx_created` (`created`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `#__mokosuitebackup_remotes` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`profile_id` INT(11) UNSIGNED NOT NULL,
`title` VARCHAR(255) NOT NULL DEFAULT '',
`type` VARCHAR(20) NOT NULL DEFAULT 'sftp' COMMENT 'sftp, s3, google_drive',
`enabled` TINYINT(1) NOT NULL DEFAULT 1,
`params` MEDIUMTEXT COMMENT 'JSON: type-specific settings',
`ordering` INT(11) NOT NULL DEFAULT 0,
`created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
`modified` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
KEY `idx_profile` (`profile_id`),
KEY `idx_enabled` (`profile_id`, `enabled`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Insert default backup profile (IGNORE prevents duplicate key error on update)
INSERT IGNORE INTO `#__mokosuitebackup_profiles` (
`id`, `title`, `description`, `backup_type`,
`archive_format`, `compression_level`, `split_size`, `backup_dir`,
`exclude_dirs`, `exclude_files`, `exclude_tables`,
`published`, `ordering`, `created`, `modified`
`published`, `created`, `modified`
) VALUES (
1, 'Default Backup Profile', 'Full site backup with default settings', 'full',
'zip', 5, 0, '[DEFAULT_DIR]',
'administrator/components/com_mokosuitebackup/backups\ntmp\ncache\nlogs\nadministrator/logs',
'.gitignore\n.htaccess.bak',
'#__session',
1, 1, NOW(), NOW()
1, NOW(), NOW()
);
@@ -1,2 +1,4 @@
DROP TABLE IF EXISTS `#__mokosuitebackup_remotes`;
DROP TABLE IF EXISTS `#__mokosuitebackup_records`;
DROP TABLE IF EXISTS `#__mokosuitebackup_snapshots`;
DROP TABLE IF EXISTS `#__mokosuitebackup_profiles`;
@@ -0,0 +1,97 @@
-- MokoSuiteBackup 01.41.00 — Multi-remote storage destinations (#97)
CREATE TABLE IF NOT EXISTS `#__mokosuitebackup_remotes` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`profile_id` INT(11) UNSIGNED NOT NULL,
`title` VARCHAR(255) NOT NULL DEFAULT '',
`type` VARCHAR(20) NOT NULL DEFAULT 'sftp' COMMENT 'sftp, s3, google_drive',
`enabled` TINYINT(1) NOT NULL DEFAULT 1,
`params` MEDIUMTEXT COMMENT 'JSON: type-specific settings',
`ordering` INT(11) NOT NULL DEFAULT 0,
`created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
`modified` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
KEY `idx_profile` (`profile_id`),
KEY `idx_enabled` (`profile_id`, `enabled`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Migrate existing SFTP remote configs into new table
INSERT INTO `#__mokosuitebackup_remotes` (`profile_id`, `title`, `type`, `enabled`, `params`, `ordering`, `created`)
SELECT
`id`,
CONCAT(`title`, ' - SFTP'),
'sftp',
1,
JSON_OBJECT(
'host', `sftp_host`,
'port', `sftp_port`,
'username', `sftp_username`,
'auth_type', `sftp_auth_type`,
'password', `sftp_password`,
'key_data', COALESCE(`sftp_key_data`, ''),
'passphrase', `sftp_passphrase`,
'path', `sftp_path`
),
1,
NOW()
FROM `#__mokosuitebackup_profiles`
WHERE `remote_storage` = 'sftp' AND `sftp_host` != '';
-- Migrate existing S3 remote configs into new table
INSERT INTO `#__mokosuitebackup_remotes` (`profile_id`, `title`, `type`, `enabled`, `params`, `ordering`, `created`)
SELECT
`id`,
CONCAT(`title`, ' - S3'),
's3',
1,
JSON_OBJECT(
'endpoint', `s3_endpoint`,
'region', `s3_region`,
'access_key', `s3_access_key`,
'secret_key', `s3_secret_key`,
'bucket', `s3_bucket`,
'path', `s3_path`
),
1,
NOW()
FROM `#__mokosuitebackup_profiles`
WHERE `remote_storage` = 's3' AND `s3_bucket` != '';
-- Migrate existing Google Drive remote configs into new table
INSERT INTO `#__mokosuitebackup_remotes` (`profile_id`, `title`, `type`, `enabled`, `params`, `ordering`, `created`)
SELECT
`id`,
CONCAT(`title`, ' - Google Drive'),
'google_drive',
1,
JSON_OBJECT(
'client_id', `gdrive_client_id`,
'client_secret', `gdrive_client_secret`,
'refresh_token', `gdrive_refresh_token`,
'folder_id', `gdrive_folder_id`
),
1,
NOW()
FROM `#__mokosuitebackup_profiles`
WHERE `remote_storage` = 'google_drive' AND `gdrive_client_id` != '';
-- Migrate existing FTP remote configs into new table
INSERT INTO `#__mokosuitebackup_remotes` (`profile_id`, `title`, `type`, `enabled`, `params`, `ordering`, `created`)
SELECT
`id`,
CONCAT(`title`, ' - FTP'),
'ftp',
1,
JSON_OBJECT(
'host', `ftp_host`,
'port', `ftp_port`,
'username', `ftp_username`,
'password', `ftp_password`,
'path', `ftp_path`,
'passive', `ftp_passive`,
'ssl', `ftp_ssl`
),
1,
NOW()
FROM `#__mokosuitebackup_profiles`
WHERE `remote_storage` = 'ftp' AND `ftp_host` != '';
@@ -0,0 +1 @@
/* 01.43.11 — no schema changes */
@@ -0,0 +1 @@
/* 01.43.19 — no schema changes */
@@ -0,0 +1 @@
/* 01.43.20 — no schema changes */
@@ -0,0 +1 @@
/* 01.43.21 — no schema changes */
@@ -0,0 +1,5 @@
-- 01.43.22 — Add restore_script_name to profiles, align remotes schema
ALTER TABLE `#__mokosuitebackup_profiles`
ADD COLUMN `restore_script_name` VARCHAR(100) NOT NULL DEFAULT 'restore.php' COMMENT 'Custom restore script filename'
AFTER `include_mokorestore`;
@@ -0,0 +1 @@
/* 01.43.23 — no schema changes */
@@ -0,0 +1 @@
/* 01.43.24 — no schema changes */
@@ -0,0 +1 @@
/* 01.43.25 — no schema changes */
@@ -0,0 +1 @@
/* 01.43.26 — no schema changes */
@@ -0,0 +1 @@
/* 01.43.29 — no schema changes */
@@ -0,0 +1 @@
/* 01.43.30 — no schema changes */
@@ -0,0 +1 @@
/* 01.43.31 — no schema changes */
@@ -0,0 +1 @@
/* 01.43.32 — no schema changes */
@@ -0,0 +1 @@
ALTER TABLE `#__mokosuitebackup_profiles` DROP COLUMN `ordering`;
@@ -0,0 +1 @@
/* 01.43.34 — no schema changes */
@@ -0,0 +1 @@
/* 01.43.35 — no schema changes */
@@ -0,0 +1 @@
/* 01.43.36 — no schema changes */
@@ -0,0 +1 @@
/* 01.43.37 — no schema changes */
@@ -0,0 +1 @@
/* 01.43.38 — no schema changes */
@@ -0,0 +1 @@
/* 01.44.00 — no schema changes */
@@ -0,0 +1 @@
/* 01.44.01 — no schema changes */
@@ -0,0 +1 @@
/* 01.45.00 — no schema changes */
@@ -0,0 +1 @@
/* 02.52.16 — no schema changes */
@@ -0,0 +1 @@
/* 02.52.17 — no schema changes */
@@ -0,0 +1 @@
/* 02.52.18 — no schema changes */
@@ -0,0 +1 @@
/* 02.52.20 — no schema changes */
@@ -0,0 +1 @@
/* 02.52.21 — no schema changes */
@@ -0,0 +1 @@
/* 02.52.22 — no schema changes */
@@ -0,0 +1 @@
/* 02.52.23 — no schema changes */
@@ -0,0 +1 @@
/* 02.52.24 — no schema changes */
@@ -0,0 +1,31 @@
-- Remove legacy single-remote storage columns (superseded by #__mokosuitebackup_remotes).
-- Plain DROP COLUMN (no IF EXISTS): all columns are created by install.mysql.sql and
-- earlier updates, so they always exist here. `DROP COLUMN IF EXISTS` is a MariaDB-only
-- extension and errors on Oracle MySQL 8.x, which Joomla also supports.
ALTER TABLE `#__mokosuitebackup_profiles`
DROP COLUMN `remote_storage`,
DROP COLUMN `ftp_host`,
DROP COLUMN `ftp_port`,
DROP COLUMN `ftp_username`,
DROP COLUMN `ftp_password`,
DROP COLUMN `ftp_path`,
DROP COLUMN `ftp_passive`,
DROP COLUMN `ftp_ssl`,
DROP COLUMN `sftp_host`,
DROP COLUMN `sftp_port`,
DROP COLUMN `sftp_username`,
DROP COLUMN `sftp_auth_type`,
DROP COLUMN `sftp_password`,
DROP COLUMN `sftp_key_data`,
DROP COLUMN `sftp_passphrase`,
DROP COLUMN `sftp_path`,
DROP COLUMN `gdrive_client_id`,
DROP COLUMN `gdrive_client_secret`,
DROP COLUMN `gdrive_refresh_token`,
DROP COLUMN `gdrive_folder_id`,
DROP COLUMN `s3_endpoint`,
DROP COLUMN `s3_region`,
DROP COLUMN `s3_access_key`,
DROP COLUMN `s3_secret_key`,
DROP COLUMN `s3_bucket`,
DROP COLUMN `s3_path`;
@@ -0,0 +1 @@
/* 02.52.27 — no schema changes */
@@ -0,0 +1 @@
/* 02.53.00 — no schema changes */
@@ -0,0 +1 @@
/* 02.54.00 — no schema changes */
@@ -0,0 +1 @@
/* 02.55.00 — no schema changes */
@@ -0,0 +1 @@
/* 02.55.03 — no schema changes */
@@ -0,0 +1 @@
/* 02.56.00 — no schema changes */
@@ -0,0 +1,13 @@
-- Legacy single-remote storage columns are now purged by the package installer
-- script (Pkg_MokoSuiteBackupInstallerScript::dropLegacyRemoteColumns()), NOT here.
--
-- The 26 legacy remote_storage/ftp_*/sftp_*/gdrive_*/s3_* columns must be removed
-- portably across MariaDB and MySQL 8. `DROP COLUMN IF EXISTS` is MariaDB-only
-- (errors on MySQL 8); plain `DROP COLUMN` errors when a column is absent. The
-- previous version gated the ALTER on INFORMATION_SCHEMA and ran it via
-- PREPARE/EXECUTE/DEALLOCATE — but those statements are rejected by Joomla's
-- installer SQL path (MySQL error 1295: "This command is not supported in the
-- prepared statement protocol yet"), which ABORTED the whole component install.
--
-- The drop is now done in PHP (INFORMATION_SCHEMA gate + a plain ALTER for only the
-- columns that still exist), so this migration is intentionally a no-op.
@@ -0,0 +1 @@
/* 02.56.05 — no schema changes */
@@ -0,0 +1 @@
/* 02.56.07 — no schema changes */
@@ -0,0 +1 @@
/* 02.56.08 — no schema changes */
@@ -0,0 +1 @@
/* 02.56.11 — no schema changes */
@@ -0,0 +1 @@
/* 02.57.00 — no schema changes */
@@ -0,0 +1 @@
/* 02.57.01 — no schema changes */
@@ -0,0 +1 @@
/* 02.57.02 — no schema changes */
@@ -0,0 +1 @@
/* 02.57.04 — no schema changes */
@@ -0,0 +1 @@
/* 02.57.05 — no schema changes */
@@ -0,0 +1 @@
/* 02.57.06 — no schema changes */
@@ -0,0 +1 @@
/* 02.57.07 — no schema changes */
@@ -0,0 +1 @@
/* 02.57.08 — no schema changes */
@@ -0,0 +1 @@
/* 02.57.09 — no schema changes */
@@ -0,0 +1 @@
/* 02.57.10 — no schema changes */
@@ -0,0 +1 @@
/* 02.57.11 — no schema changes */
@@ -0,0 +1 @@
/* 02.57.12 — no schema changes */

Some files were not shown because too many files have changed in this diff Show More