Compare commits

..

8 Commits

Author SHA1 Message Date
jmiller 4422e3f39f chore: add .mokogitea/branch-protection.yml from moko-platform [skip ci] 2026-05-29 10:30:02 +00:00
jmiller ed8c7cadc7 chore: sync CONTRIBUTING.md from moko-platform [skip ci] 2026-05-29 10:27:30 +00:00
jmiller 08aab4a422 chore: sync .mokogitea/workflows/branch-cleanup.yml from moko-platform [skip ci] 2026-05-29 10:25:53 +00:00
jmiller 14e2e5df64 chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-29 10:24:23 +00:00
jmiller 2b1eb43345 chore: sync .mokogitea/workflows/auto-bump.yml from moko-platform [skip ci] 2026-05-29 10:22:54 +00:00
gitea-actions[bot] 0033dae38b chore: update stable channel 02.20.00 [skip ci] 2026-05-28 22:32:07 +00:00
gitea-actions[bot] 75cc05c8d5 chore(release): build 02.20.00 [skip ci] 2026-05-28 22:32:04 +00:00
jmiller 3d99cb7906 Merge pull request 'fix: test release with restored manifest.xml' (#86) from dev into main
Generic: Repo Health / Release configuration (push) Blocked by required conditions
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 3s
2026-05-28 22:31:50 +00:00
12 changed files with 969 additions and 643 deletions
+251
View File
@@ -0,0 +1,251 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.Automation
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
# PATH: /.gitea/workflows/branch-protection.yml
# BRIEF: Apply standardised branch protection rules to all governed repositories
#
# +========================================================================+
# | BRANCH PROTECTION SETUP |
# +========================================================================+
# | |
# | Applies protection rules for: main, dev, rc, beta, alpha |
# | |
# | main — Require PR, block rejected reviews, no force push |
# | dev — Allow push, no force push, no delete |
# | rc — Allow push, no force push, no delete |
# | beta — Allow push, no force push, no delete |
# | alpha — Allow push, no force push, no delete |
# | |
# | jmiller has override authority on all branches. |
# | |
# +========================================================================+
name: Branch Protection Setup
on:
schedule:
- cron: '0 2 * * 1' # Weekly Monday 02:00 UTC
workflow_dispatch:
inputs:
dry_run:
description: 'Preview mode (no changes)'
required: false
type: boolean
default: false
repos:
description: 'Comma-separated repo names (empty = all governed repos)'
required: false
type: string
default: ''
env:
GITEA_URL: https://git.mokoconsulting.tech
GITEA_ORG: MokoConsulting
permissions:
contents: read
jobs:
protect:
name: Apply Branch Protection Rules
runs-on: ubuntu-latest
steps:
- name: Determine target repos
id: repos
env:
GA_TOKEN: ${{ secrets.GA_TOKEN }}
run: |
API="${GITEA_URL}/api/v1"
# Platform/standards/infra repos to exclude
EXCLUDE="gitea-org-config org-profile gitea-private .mokogitea-private MokoStandards moko-platform MokoTesting"
EXCLUDE="$EXCLUDE MokoStandards-Template-Client MokoStandards-Template-Dolibarr MokoStandards-Template-Generic MokoStandards-Template-Joomla MokoDoliProjTemplate"
if [ -n "${{ inputs.repos }}" ]; then
# User-specified repos
REPOS=$(echo "${{ inputs.repos }}" | tr ',' ' ')
else
# Fetch all org repos
PAGE=1
REPOS=""
while true; do
BATCH=$(curl -sS \
-H "Authorization: token ${GA_TOKEN}" \
"${API}/orgs/${GITEA_ORG}/repos?page=${PAGE}&limit=50" \
| jq -r '.[].name // empty')
[ -z "$BATCH" ] && break
REPOS="$REPOS $BATCH"
PAGE=$((PAGE + 1))
done
# Filter out excluded repos
FILTERED=""
for REPO in $REPOS; do
SKIP=false
for EX in $EXCLUDE; do
if [ "$REPO" = "$EX" ]; then
SKIP=true
break
fi
done
if [ "$SKIP" = "false" ]; then
FILTERED="$FILTERED $REPO"
fi
done
REPOS="$FILTERED"
fi
echo "repos=$REPOS" >> "$GITHUB_OUTPUT"
COUNT=$(echo "$REPOS" | wc -w)
echo "📋 Target repos (${COUNT}): $REPOS"
- name: Apply protection rules
env:
GA_TOKEN: ${{ secrets.GA_TOKEN }}
DRY_RUN: ${{ inputs.dry_run || 'false' }}
run: |
API="${GITEA_URL}/api/v1"
REPOS="${{ steps.repos.outputs.repos }}"
SUCCESS=0
FAILED=0
SKIPPED=0
# ── Rule definitions ──────────────────────────────────────
# Only the CI bot (jmiller token) can push directly.
# All human contributors must use PRs.
# Force push disabled on all branches.
RULE_MAIN='{
"rule_name": "main",
"enable_push": true,
"enable_push_whitelist": true,
"push_whitelist_usernames": ["jmiller"],
"enable_force_push": false,
"enable_force_push_allowlist": false,
"force_push_allowlist_usernames": [],
"enable_merge_whitelist": false,
"required_approvals": 0,
"dismiss_stale_approvals": true,
"block_on_rejected_reviews": true,
"block_on_outdated_branch": false,
"priority": 1
}'
RULE_DEV='{
"rule_name": "dev",
"enable_push": true,
"enable_push_whitelist": true,
"push_whitelist_usernames": ["jmiller"],
"enable_force_push": false,
"enable_force_push_allowlist": false,
"force_push_allowlist_usernames": [],
"enable_merge_whitelist": false,
"required_approvals": 0,
"block_on_rejected_reviews": false,
"priority": 2
}'
RULE_RC='{
"rule_name": "rc",
"enable_push": true,
"enable_push_whitelist": true,
"push_whitelist_usernames": ["jmiller"],
"enable_force_push": false,
"enable_force_push_allowlist": false,
"force_push_allowlist_usernames": [],
"enable_merge_whitelist": false,
"required_approvals": 0,
"block_on_rejected_reviews": false,
"priority": 3
}'
RULE_BETA='{
"rule_name": "beta",
"enable_push": true,
"enable_push_whitelist": true,
"push_whitelist_usernames": ["jmiller"],
"enable_force_push": false,
"enable_force_push_allowlist": false,
"force_push_allowlist_usernames": [],
"enable_merge_whitelist": false,
"required_approvals": 0,
"block_on_rejected_reviews": false,
"priority": 4
}'
RULE_ALPHA='{
"rule_name": "alpha",
"enable_push": true,
"enable_push_whitelist": true,
"push_whitelist_usernames": ["jmiller"],
"enable_force_push": false,
"enable_force_push_allowlist": false,
"force_push_allowlist_usernames": [],
"enable_merge_whitelist": false,
"required_approvals": 0,
"block_on_rejected_reviews": false,
"priority": 5
}'
RULES=("$RULE_MAIN" "$RULE_DEV" "$RULE_RC" "$RULE_BETA" "$RULE_ALPHA")
RULE_NAMES=("main" "dev" "rc" "beta" "alpha")
# ── Apply rules to each repo ──────────────────────────────
for REPO in $REPOS; do
echo ""
echo "═══ ${REPO} ═══"
for i in "${!RULES[@]}"; do
RULE="${RULES[$i]}"
NAME="${RULE_NAMES[$i]}"
if [ "$DRY_RUN" = "true" ]; then
echo " [DRY RUN] Would apply rule: ${NAME}"
SKIPPED=$((SKIPPED + 1))
continue
fi
# Delete existing rule if present (idempotent recreate)
ENCODED_NAME=$(echo "$NAME" | sed 's|/|%2F|g')
curl -sS -o /dev/null -w "" \
-X DELETE \
-H "Authorization: token ${GA_TOKEN}" \
"${API}/repos/${GITEA_ORG}/${REPO}/branch_protections/${ENCODED_NAME}" 2>/dev/null || true
# Create rule
RESPONSE=$(curl -sS -w "\n%{http_code}" \
-X POST \
-H "Authorization: token ${GA_TOKEN}" \
-H "Content-Type: application/json" \
-d "$RULE" \
"${API}/repos/${GITEA_ORG}/${REPO}/branch_protections")
HTTP=$(echo "$RESPONSE" | tail -1)
BODY=$(echo "$RESPONSE" | sed '$d')
if [ "$HTTP" = "201" ]; then
echo " ✅ ${NAME}"
SUCCESS=$((SUCCESS + 1))
else
echo " ❌ ${NAME} (HTTP ${HTTP}): $(echo "$BODY" | jq -r '.message // .' 2>/dev/null | head -1)"
FAILED=$((FAILED + 1))
fi
done
done
# ── Summary ───────────────────────────────────────────────
echo ""
echo "════════════════════════════════════════"
echo " ✅ Success: ${SUCCESS}"
echo " ❌ Failed: ${FAILED}"
echo " ⏭️ Skipped: ${SKIPPED}"
echo "════════════════════════════════════════"
if [ "$FAILED" -gt 0 ]; then
echo "::warning::${FAILED} rule(s) failed to apply"
fi
+62 -14
View File
@@ -82,14 +82,56 @@ jobs:
cd /tmp/moko-platform-api cd /tmp/moko-platform-api
composer install --no-dev --no-interaction --quiet composer install --no-dev --no-interaction --quiet
- name: Promote to release-candidate - name: Rename source branch to rc
run: | run: |
SOURCE_BRANCH="${{ github.event.pull_request.head.ref || 'dev' }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
php /tmp/moko-platform-api/cli/release_promote.php \ PR_NUM="${{ github.event.pull_request.number }}"
--from auto --to release-candidate \ php /tmp/moko-platform-api/cli/branch_rename.php \
--from "$SOURCE_BRANCH" --to rc \
--token "${{ secrets.MOKOGITEA_TOKEN }}" \ --token "${{ secrets.MOKOGITEA_TOKEN }}" \
--api-base "${API_BASE}" \ --api-base "${API_BASE}" \
--branch "${{ github.event.pull_request.head.ref || 'dev' }}" --pr "$PR_NUM"
- name: Set RC version on renamed branch
run: |
# Checkout the new rc branch
git fetch origin rc
git checkout rc
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
MOKO_CLI="/tmp/moko-platform-api/cli"
VERSION=$(php ${MOKO_CLI}/version_read.php --path .) || true
[ -z "$VERSION" ] && { echo "No version — skipping"; exit 0; }
php ${MOKO_CLI}/version_set_platform.php \
--path . --version "$VERSION" --branch rc --stability rc 2>/dev/null || true
php ${MOKO_CLI}/version_check.php --path . --fix 2>/dev/null || true
if ! git diff --quiet || ! git diff --cached --quiet; then
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "gitea-actions[bot]"
git add -A
git commit -m "chore(version): set RC stability suffix [skip ci]" \
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>"
git push origin rc
fi
- name: Build RC release
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
MOKO_CLI="/tmp/moko-platform-api/cli"
VERSION=$(php ${MOKO_CLI}/version_read.php --path .) || true
php ${MOKO_CLI}/release_create.php \
--path . --version "$VERSION" --tag "release-candidate" \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
--repo "${GITEA_REPO}" --branch rc 2>&1 || true
php ${MOKO_CLI}/release_package.php \
--path . --version "$VERSION" --tag "release-candidate" \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
--repo "${GITEA_REPO}" --output /tmp 2>&1 || true
- name: Cascade lesser channels - name: Cascade lesser channels
continue-on-error: true continue-on-error: true
@@ -104,7 +146,7 @@ jobs:
if: always() if: always()
run: | run: |
echo "## Promoted to Release Candidate" >> $GITHUB_STEP_SUMMARY echo "## Promoted to Release Candidate" >> $GITHUB_STEP_SUMMARY
echo "Draft PR opened — promoted highest pre-release to RC" >> $GITHUB_STEP_SUMMARY echo "Draft PR opened — branch renamed to rc, RC release built" >> $GITHUB_STEP_SUMMARY
# ── Merged PR → Build & Release (or promote RC to stable) ──────────────────── # ── Merged PR → Build & Release (or promote RC to stable) ────────────────────
release: release:
@@ -165,9 +207,8 @@ jobs:
echo "skip=true" >> "$GITHUB_OUTPUT" echo "skip=true" >> "$GITHUB_OUTPUT"
exit 0 exit 0
fi fi
# Strip any pre-release suffix merged from dev (e.g. 01.02.20-dev → 01.02.20) # version_set_platform strips suffixes internally when --stability stable
VERSION=$(echo "$VERSION" | sed 's/-\(dev\|alpha\|beta\|rc\)$//') MAJOR=$(echo "$VERSION" | cut -d. -f1 | sed 's/-.*//')
MAJOR=$(echo "$VERSION" | cut -d. -f1)
echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "release_tag=stable" >> "$GITHUB_OUTPUT" echo "release_tag=stable" >> "$GITHUB_OUTPUT"
echo "skip=false" >> "$GITHUB_OUTPUT" echo "skip=false" >> "$GITHUB_OUTPUT"
@@ -181,7 +222,7 @@ jobs:
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
RC_JSON=$(curl -sf -H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \ RC_JSON=$(curl -sf -H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
"${API_BASE}/releases/tags/release-candidate" 2>/dev/null || echo "{}") "${API_BASE}/releases/tags/release-candidate" 2>/dev/null || echo "{}")
RC_ID=$(echo "$RC_JSON" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('id',''))" 2>/dev/null || true) RC_ID=$(echo "$RC_JSON" | php -r "\$d=json_decode(file_get_contents('php://stdin'),true); echo \$d['id'] ?? '';" 2>/dev/null || true)
if [ -n "$RC_ID" ] && [ "$RC_ID" != "None" ] && [ "$RC_ID" != "" ]; then if [ -n "$RC_ID" ] && [ "$RC_ID" != "None" ] && [ "$RC_ID" != "" ]; then
echo "promote=true" >> "$GITHUB_OUTPUT" echo "promote=true" >> "$GITHUB_OUTPUT"
@@ -201,8 +242,7 @@ jobs:
MOKO_API="/tmp/moko-platform-api/cli" MOKO_API="/tmp/moko-platform-api/cli"
php ${MOKO_API}/version_bump.php --path . --minor 2>&1 || true php ${MOKO_API}/version_bump.php --path . --minor 2>&1 || true
VERSION=$(php ${MOKO_API}/version_read.php --path .) VERSION=$(php ${MOKO_API}/version_read.php --path .)
# Strip any pre-release suffix — stable releases have no suffix # version_set_platform handles suffix stripping — just pass clean base version
VERSION=$(echo "$VERSION" | sed 's/-\(dev\|alpha\|beta\|rc\)$//')
echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "Bumped to: ${VERSION}" echo "Bumped to: ${VERSION}"
@@ -376,7 +416,7 @@ jobs:
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}" API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
curl -sf -H "Authorization: token ${GITEA_TOKEN}" \ curl -sf -H "Authorization: token ${GITEA_TOKEN}" \
"${API}/contents/updates.xml?ref=main" 2>/dev/null | \ "${API}/contents/updates.xml?ref=main" 2>/dev/null | \
python3 -c "import sys,json,base64; print(base64.b64decode(json.load(sys.stdin)['content']).decode())" \ php -r "\$d=json_decode(file_get_contents('php://stdin'),true); echo base64_decode(\$d['content'] ?? '');" \
> updates.xml 2>/dev/null || true > updates.xml 2>/dev/null || true
SHA_FLAG="" SHA_FLAG=""
@@ -457,13 +497,21 @@ jobs:
--token "${{ secrets.MOKOGITEA_TOKEN }}" \ --token "${{ secrets.MOKOGITEA_TOKEN }}" \
--api-base "${API_BASE}" 2>/dev/null || true --api-base "${API_BASE}" 2>/dev/null || true
- name: "Step 11: Delete and recreate dev branch from main" - name: "Step 11: Clean up pre-release branches and recreate dev from main"
if: steps.version.outputs.skip != 'true' if: steps.version.outputs.skip != 'true'
continue-on-error: true continue-on-error: true
run: | run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}" TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
# Delete ephemeral pre-release branches (rc, alpha, beta)
for EPHEMERAL in rc alpha beta; do
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
"${API_BASE}/branches/${EPHEMERAL}" 2>/dev/null \
&& echo "Deleted ${EPHEMERAL} branch" \
|| echo "${EPHEMERAL} branch not found"
done
# Delete dev branch # Delete dev branch
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \ curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
"${API_BASE}/branches/dev" 2>/dev/null && echo "Deleted dev branch" "${API_BASE}/branches/dev" 2>/dev/null && echo "Deleted dev branch"
@@ -474,7 +522,7 @@ jobs:
"${API_BASE}/branches" \ "${API_BASE}/branches" \
-d '{"new_branch_name":"dev","old_branch_name":"main"}' 2>/dev/null && echo "Recreated dev from main" -d '{"new_branch_name":"dev","old_branch_name":"main"}' 2>/dev/null && echo "Recreated dev from main"
echo "Dev branch reset from main (keeps dev ahead after release)" >> $GITHUB_STEP_SUMMARY echo "Pre-release branches cleaned, dev reset from main" >> $GITHUB_STEP_SUMMARY
- name: "Step 12: Create version branch from main" - name: "Step 12: Create version branch from main"
if: steps.version.outputs.skip != 'true' if: steps.version.outputs.skip != 'true'
+1 -1
View File
@@ -33,7 +33,7 @@ jobs:
run: | run: |
BRANCH="${{ github.event.pull_request.head.ref }}" BRANCH="${{ github.event.pull_request.head.ref }}"
API="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}/api/v1/repos/${{ github.repository }}/branches" API="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}/api/v1/repos/${{ github.repository }}/branches"
ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('${BRANCH}', safe=''))") ENCODED=$(php -r "echo rawurlencode('${BRANCH}');")
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X DELETE \ STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X DELETE \
-H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \ -H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
+2 -23
View File
@@ -23,6 +23,8 @@
## [02.20.00] --- 2026-05-28 ## [02.20.00] --- 2026-05-28
## [02.20.00] --- 2026-05-28
## [02.19.00] --- 2026-05-28 ## [02.19.00] --- 2026-05-28
## [02.18.00] --- 2026-05-28 ## [02.18.00] --- 2026-05-28
@@ -59,26 +61,3 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- updates.xml: removed stale pre-release entries pointing to non-existent dev artifacts, legacy plugin update entry that caused stable sites to attempt dev downloads - updates.xml: removed stale pre-release entries pointing to non-existent dev artifacts, legacy plugin update entry that caused stable sites to attempt dev downloads
- Removed duplicate `<updateservers>` from inner plugin manifest — only the package-level manifest should register the update server - Removed duplicate `<updateservers>` from inner plugin manifest — only the package-level manifest should register the update server
- Auto-cleanup of stale plugin-level update site entries on install/update (cleans `#__update_sites` and `#__update_sites_extensions`) - Auto-cleanup of stale plugin-level update site entries on install/update (cleans `#__update_sites` and `#__update_sites_extensions`)
## [02.06.00] - 2026-05-25
### Added
- Alias offline bypass: aliases with offline=No override Joomla's global offline setting, allowing access via alias domain while main site is down
- Block non-master users from viewing or editing MokoWaaS plugin settings
- Master user bypasses ALL tenant restrictions (install from URL, global config, sysinfo, installer, templates)
- Admin Help menu redirected to configured support URL (replaces help.joomla.org)
### Fixed
- Install API endpoint: extract ZIP to temp directory before passing to Joomla Installer (was passing ZIP path directly)
- Clean up extracted temp directory on success or failure
- Update site disabled by Joomla when protected=1 — ensureProtectedFlag() now re-enables it
- CI: auto-release fetches updates.xml from main before building (preserves all channels)
- CI: version_check.php --fix runs after version bump in both workflows
- CI: checksums attached as `[filename].sha256` files instead of in release body
- CI: auto-release cleaned up — removed duplicate asset loops, inline Python updater, dead code
- CI: Step 8b uses `release_body_update.php` CLI instead of inline Python
- CI: Step 6 tag creation no longer gated by `is_minor` (was never set)
### Changed
- CI: auto-release uses stream tag `stable` instead of version tag `vXX`
- CI: pre-release package build uses absolute paths (fixes relative path zip error)
+125 -77
View File
@@ -1,93 +1,141 @@
<!-- # Contributing to Moko Consulting Projects
Copyright (C) 2025 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 (./LICENSE.md).
# FILE INFORMATION Thank you for your interest in contributing. All Moko Consulting repositories follow this universal workflow and version policy.
DEFGROUP: Joomla.Plugin
INGROUP: MokoWaaS.Contributing
REPO: https://github.com/mokoconsulting-tech/mokowaas
VERSION: 02.01.08
PATH: /CONTRIBUTING.md
BRIEF: Contribution guidelines for the MokoWaaS plugin
-->
# Contributing to MokoWaaS (VERSION: 02.01.08) ## Branching Workflow
## Overview ```
Contributions to the MokoWaaS plugin follow standardized development, governance, and quality control expectations defined by Moko Consulting. This document outlines contribution requirements, acceptable change types, branch management, testing expectations, and release readiness standards. feature/* ──PR──> dev ──draft PR──> (renamed to rc) ──merge──> main
```
## 1. Contribution Workflow ### Step by step
All contributions must follow the established workflow:
1. Fork the repository or create a feature branch (if internal).
2. Ensure your environment matches the supported Joomla and PHP versions.
3. Implement changes following coding, documentation, and metadata standards.
4. Validate plugin functionality locally.
5. Submit a Pull Request (PR) for review.
## 2. Branching Model 1. **Create a feature branch** from `dev`:
- `main`: Production stable branch. ```bash
- `develop`: Aggregates work for the next minor release. git checkout dev && git pull
- `feature/*`: New enhancements or changes. git checkout -b feature/my-change
- `bugfix/*`: Hotfixes and corrections. ```
Internal teams must coordinate with governance before creating major feature branches. 2. **Work and commit** on your feature branch. Push to origin.
## 3. Coding and Documentation Standards 3. **Open a PR**: `feature/my-change` → `dev`. After review and checks, merge it.
All code must:
- Follow [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) coding standards
- Include the unified SPDX license header
- Include a FILE INFORMATION metadata block
- Avoid deprecated Joomla APIs
- Preserve load order compatibility with other system plugins
Documentation must: 4. **When ready for release**, open a **draft PR**: `dev` → `main`.
- Include metadata - This automatically renames the source branch to `rc` (release candidate)
- Maintain revision history - An RC pre-release is built and uploaded
- Use consistent formatting as defined by Moko documentation standards
## 4. Testing Requirements 5. **Alpha and beta branches** are created by manually renaming the branch before the RC stage:
Before submitting a PR, contributors must verify: - Rename `dev` to `alpha` for early testing → alpha pre-release is built
- Plugin installs successfully in Joomla 5.x - Rename `alpha` to `beta` for feature-complete testing → beta pre-release is built
- No load errors appear in logs - When the draft PR is created, the branch is renamed to `rc`
- Branding replacements appear as expected
- Terminology strings are correct
- No regressions in administrator UI
Automated testing coverage will expand as part of future roadmap enhancements. 6. **Once PR checks pass** on the `rc` branch, mark the PR as ready and merge to `main`.
## 5. Pull Request Requirements 7. **Merging to main** triggers the stable release pipeline:
A PR must include: - Minor version bump (e.g., `02.09.xx` → `02.10.00`)
- Description of change - Stability suffix stripped (clean version)
- Screenshots for UI related updates - Gitea release created with ZIP/tar.gz packages
- Version updates when appropriate - `updates.xml` updated (Joomla extensions)
- Notes for documentation changes - `dev` branch recreated from `main`
- Reference to related issues or tasks
PRs lacking required information may be flagged or delayed. ### Branch summary
## 6. Release Versioning | Branch | Purpose | Created by |
Changes must follow semantic versioning: |--------|---------|-----------|
- MAJOR: Structural branding or architectural changes | `feature/*` | New features and fixes | Developer |
- MINOR: Feature updates or terminology expansion | `dev` | Integration branch | Auto-recreated after release |
- PATCH: Bug fixes or language corrections | `alpha` | Alpha pre-release testing | Manual rename from `dev` |
| `beta` | Beta pre-release testing | Manual rename from `alpha` |
| `rc` | Release candidate | Auto-renamed on draft PR to main |
| `main` | Stable releases | Protected, merge only |
| `version/XX.YY.ZZ` | Archived release snapshots | Auto-created by CI |
Version updates must be reflected in: ### Protected branches
- Manifest files
- PHP headers
- Documentation metadata
## 7. Code Review Standards | Branch | Direct push | Merge via |
Reviewers validate: |--------|------------|-----------|
- Code quality and clarity | `main` | Blocked (CI bot whitelisted) | PR merge only |
- Compliance with [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) coding standards | `dev` | Blocked (CI bot whitelisted) | PR merge from feature/* |
- Impact to templates and WaaS branding rules | `rc` | Blocked (CI bot whitelisted) | Auto-created on draft PR |
- Backwards compatibility expectations | `alpha` | Blocked (CI bot whitelisted) | Manual rename |
| `beta` | Blocked (CI bot whitelisted) | Manual rename |
| `feature/*` | Open | N/A (source branch) |
## Revision History ## Version Policy
| Date | Author | Description |
| ------ | -------- | ----------- | ### Format
| 2025-12-11 | Jonathan Miller (@jmiller-moko) | Initial creation of contribution guidelines |
All versions use `XX.YY.ZZ` — three two-digit segments, zero-padded:
- **XX** — Major version (breaking changes)
- **YY** — Minor version (new features, bumped on release to main)
- **ZZ** — Patch version (auto-incremented on every push to dev/feature branches)
Rollover: patch `99` → `00` increments minor; minor `99` → `00` increments major.
### Stability suffixes
Each branch appends a suffix to indicate stability:
| Branch | Suffix | Example |
|--------|--------|---------|
| `main` | (none) | `02.09.00` |
| `dev` | `-dev` | `02.09.01-dev` |
| `feature/*` | `-dev` | `02.09.01-dev` |
| `alpha` | `-alpha` | `02.09.01-alpha` |
| `beta` | `-beta` | `02.09.01-beta` |
| `rc` | `-rc` | `02.09.01-rc` |
### Auto version bump
On every push to `dev`, `alpha`, `beta`, `rc`, or `feature/*`:
1. Patch version incremented
2. Stability suffix applied based on branch name
3. All version-bearing files updated (manifests, CHANGELOG, PHP headers, etc.)
4. Commit created with `[skip ci]` to avoid loops
### Version files
The version tools update all files containing version stamps:
- `.mokogitea/manifest.xml` (canonical source)
- Joomla XML manifests (`<version>` tag)
- `README.md`, `CHANGELOG.md` (`VERSION:` pattern)
- `package.json`, `pyproject.toml`
- Any text file with a `VERSION: XX.YY.ZZ` label
Files synced from other repos (with a `# REPO:` header) are not touched.
## Code Standards
- **PHP**: PSR-12, tabs for indentation
- **Copyright**: all files must include the Moko Consulting copyright header
- **License**: SPDX identifier `GPL-3.0-or-later` (or as specified per repo)
- **Attribution**: use `Authored-by: Moko Consulting` in commits, not individual names
## Commit Messages
Use conventional commit format:
```
type(scope): short description
Optional body with context.
Authored-by: Moko Consulting
```
Types: `feat`, `fix`, `chore`, `docs`, `style`, `refactor`, `test`, `ci`
Special flags in commit messages:
- `[skip ci]` — skip all CI workflows
- `[skip bump]` — skip auto version bump only
## Reporting Issues
Use the repository's issue tracker with the appropriate template.
---
*Moko Consulting <hello@mokoconsulting.tech>*
+1 -1
View File
@@ -9,7 +9,7 @@
DEFGROUP: Joomla.Plugin DEFGROUP: Joomla.Plugin
INGROUP: MokoWaaS INGROUP: MokoWaaS
REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS
VERSION: 02.20.01 VERSION: 02.21.00
PATH: /README.md PATH: /README.md
BRIEF: MokoWaaS platform plugin for Joomla BRIEF: MokoWaaS platform plugin for Joomla
--> -->
+1 -1
View File
@@ -7,7 +7,7 @@
<license>GPL-3.0-or-later</license> <license>GPL-3.0-or-later</license>
<authorEmail>hello@mokoconsulting.tech</authorEmail> <authorEmail>hello@mokoconsulting.tech</authorEmail>
<authorUrl>https://mokoconsulting.tech</authorUrl> <authorUrl>https://mokoconsulting.tech</authorUrl>
<version>02.20.01-dev</version> <version>02.20.00</version>
<description>Minimal API-only component for MokoWaaS. Provides REST endpoints for site health, cache, updates, and backups.</description> <description>Minimal API-only component for MokoWaaS. Provides REST endpoints for site health, cache, updates, and backups.</description>
<namespace path="api/src">Moko\Component\MokoWaaS\Api</namespace> <namespace path="api/src">Moko\Component\MokoWaaS\Api</namespace>
<administration> <administration>
@@ -30,7 +30,7 @@
<license>GNU General Public License version 3 or later; see LICENSE.md</license> <license>GNU General Public License version 3 or later; see LICENSE.md</license>
<authorEmail>hello@mokoconsulting.tech</authorEmail> <authorEmail>hello@mokoconsulting.tech</authorEmail>
<authorUrl>https://mokoconsulting.tech</authorUrl> <authorUrl>https://mokoconsulting.tech</authorUrl>
<version>02.20.01-dev</version> <version>02.20.00</version>
<description>This plugin rebrands the Joomla system interface with MokoWaaS identity. It applies language overrides and ensures consistent branding across the platform.</description> <description>This plugin rebrands the Joomla system interface with MokoWaaS identity. It applies language overrides and ensures consistent branding across the platform.</description>
<namespace path=".">Moko\Plugin\System\MokoWaaS</namespace> <namespace path=".">Moko\Plugin\System\MokoWaaS</namespace>
<scriptfile>script.php</scriptfile> <scriptfile>script.php</scriptfile>
@@ -7,7 +7,7 @@
<license>GPL-3.0-or-later</license> <license>GPL-3.0-or-later</license>
<authorEmail>hello@mokoconsulting.tech</authorEmail> <authorEmail>hello@mokoconsulting.tech</authorEmail>
<authorUrl>https://mokoconsulting.tech</authorUrl> <authorUrl>https://mokoconsulting.tech</authorUrl>
<version>02.20.01-dev</version> <version>02.20.00</version>
<description>Joomla Web Services API routes for MokoWaaS site management — health checks, cache, updates, backups, and site info.</description> <description>Joomla Web Services API routes for MokoWaaS site management — health checks, cache, updates, backups, and site info.</description>
<namespace path="src">Moko\Plugin\WebServices\MokoWaaS</namespace> <namespace path="src">Moko\Plugin\WebServices\MokoWaaS</namespace>
<files> <files>
@@ -7,7 +7,7 @@
<license>GPL-3.0-or-later</license> <license>GPL-3.0-or-later</license>
<authorEmail>hello@mokoconsulting.tech</authorEmail> <authorEmail>hello@mokoconsulting.tech</authorEmail>
<authorUrl>https://mokoconsulting.tech</authorUrl> <authorUrl>https://mokoconsulting.tech</authorUrl>
<version>02.20.01-dev</version> <version>02.20.00</version>
<description>Joomla Web Services API routes for Perfect Publisher (com_autotweet) — channels, posts, requests, rules, and feeds.</description> <description>Joomla Web Services API routes for Perfect Publisher (com_autotweet) — channels, posts, requests, rules, and feeds.</description>
<namespace path="src">Moko\Plugin\WebServices\PerfectPublisher</namespace> <namespace path="src">Moko\Plugin\WebServices\PerfectPublisher</namespace>
<files> <files>
+1 -1
View File
@@ -2,7 +2,7 @@
<extension type="package" method="upgrade"> <extension type="package" method="upgrade">
<name>MokoWaaS</name> <name>MokoWaaS</name>
<packagename>mokowaas</packagename> <packagename>mokowaas</packagename>
<version>02.20.01-dev</version> <version>02.20.00</version>
<creationDate>2026-05-23</creationDate> <creationDate>2026-05-23</creationDate>
<author>Moko Consulting</author> <author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail> <authorEmail>hello@mokoconsulting.tech</authorEmail>
+5 -5
View File
@@ -17,7 +17,7 @@
<downloads> <downloads>
<downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/pkg_mokowaas-02.20.00.zip</downloadurl> <downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/pkg_mokowaas-02.20.00.zip</downloadurl>
</downloads> </downloads>
<sha256>71a9f9d03810499992771fc505b9caf08191e8d9596963ab135d92abf836d6cc</sha256> <sha256>4f893125c1f66d5c8545191d081a3f8abf555a7c0fe84f00b3be3cdda532b38f</sha256>
<tags><tag>dev</tag></tags> <tags><tag>dev</tag></tags>
<maintainer>Moko Consulting</maintainer> <maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl> <maintainerurl>https://mokoconsulting.tech</maintainerurl>
@@ -35,7 +35,7 @@
<downloads> <downloads>
<downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/pkg_mokowaas-02.20.00.zip</downloadurl> <downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/pkg_mokowaas-02.20.00.zip</downloadurl>
</downloads> </downloads>
<sha256>71a9f9d03810499992771fc505b9caf08191e8d9596963ab135d92abf836d6cc</sha256> <sha256>4f893125c1f66d5c8545191d081a3f8abf555a7c0fe84f00b3be3cdda532b38f</sha256>
<tags><tag>alpha</tag></tags> <tags><tag>alpha</tag></tags>
<maintainer>Moko Consulting</maintainer> <maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl> <maintainerurl>https://mokoconsulting.tech</maintainerurl>
@@ -53,7 +53,7 @@
<downloads> <downloads>
<downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/pkg_mokowaas-02.20.00.zip</downloadurl> <downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/pkg_mokowaas-02.20.00.zip</downloadurl>
</downloads> </downloads>
<sha256>71a9f9d03810499992771fc505b9caf08191e8d9596963ab135d92abf836d6cc</sha256> <sha256>4f893125c1f66d5c8545191d081a3f8abf555a7c0fe84f00b3be3cdda532b38f</sha256>
<tags><tag>beta</tag></tags> <tags><tag>beta</tag></tags>
<maintainer>Moko Consulting</maintainer> <maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl> <maintainerurl>https://mokoconsulting.tech</maintainerurl>
@@ -71,7 +71,7 @@
<downloads> <downloads>
<downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/pkg_mokowaas-02.20.00.zip</downloadurl> <downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/pkg_mokowaas-02.20.00.zip</downloadurl>
</downloads> </downloads>
<sha256>71a9f9d03810499992771fc505b9caf08191e8d9596963ab135d92abf836d6cc</sha256> <sha256>4f893125c1f66d5c8545191d081a3f8abf555a7c0fe84f00b3be3cdda532b38f</sha256>
<tags><tag>rc</tag></tags> <tags><tag>rc</tag></tags>
<maintainer>Moko Consulting</maintainer> <maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl> <maintainerurl>https://mokoconsulting.tech</maintainerurl>
@@ -89,7 +89,7 @@
<downloads> <downloads>
<downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/pkg_mokowaas-02.20.00.zip</downloadurl> <downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/pkg_mokowaas-02.20.00.zip</downloadurl>
</downloads> </downloads>
<sha256>71a9f9d03810499992771fc505b9caf08191e8d9596963ab135d92abf836d6cc</sha256> <sha256>4f893125c1f66d5c8545191d081a3f8abf555a7c0fe84f00b3be3cdda532b38f</sha256>
<tags><tag>stable</tag></tags> <tags><tag>stable</tag></tags>
<maintainer>Moko Consulting</maintainer> <maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl> <maintainerurl>https://mokoconsulting.tech</maintainerurl>