Compare commits
147 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f6e8c2f171 | |||
| ed2156738a | |||
| cc9f8acfd2 | |||
| 00e082c352 | |||
| 5259e5ab24 | |||
| 096353c674 | |||
| 3724766f9f | |||
| cd14727fb3 | |||
| 6408004f45 | |||
| 7ac27f7f62 | |||
| f14fdc7f82 | |||
| af6a34fc8c | |||
| d010978307 | |||
| efe5203cce | |||
| ec2788dfe9 | |||
| 9981d71b83 | |||
| e129310586 | |||
| d7c8dbf9dc | |||
| 7c2e08c755 | |||
| 84712bc4b6 | |||
| 861cd5074b | |||
| 3e360d12da | |||
| 8708f7342a | |||
| b1e0c0e213 | |||
| e9999e71d8 | |||
| 39d1d86df5 | |||
| 7235035595 | |||
| 0cba7e7bb1 | |||
| 9dd96f610e | |||
| 7b144ffcaa | |||
| 09b4052920 | |||
| cd2c3d1b4a | |||
| c83aac0da4 | |||
| 057b3602c6 | |||
| 6c14ce52bb | |||
| de80f94b0c | |||
| ea64c6d70e | |||
| feca69f108 | |||
| 0a44476126 | |||
| b809e492a7 | |||
| 12c4c5c2a3 | |||
| 5253708c29 | |||
| 280e2ca4bb | |||
| 279961461b | |||
| b6f6b91763 | |||
| c4726bf442 | |||
| 27645d667e | |||
| fbaa2964a3 | |||
| 0b72ab7c1a | |||
| 51b68b99d0 | |||
| 6082f011dd | |||
| 17a0018419 | |||
| 14006b21d4 | |||
| 63f6e67878 | |||
| f9491537ee | |||
| 10a6858962 | |||
| 6ed5de58d6 | |||
| 104ed887e6 | |||
| 4c2e7c6623 | |||
| 2540d41ca3 | |||
| 78aca3d849 | |||
| 325238a24e | |||
| 5c249f05f7 | |||
| 2f9200a6c7 | |||
| 189b261c56 | |||
| efa5efca50 | |||
| 8615916c3b | |||
| 86e7d28acc | |||
| b520f7b8a2 | |||
| 5ab85fbce2 | |||
| 5fc6a4aff1 | |||
| 137377c61f | |||
| 682df20677 | |||
| 0a279fab67 | |||
| 4cce6d14a9 | |||
| 91c52a9d5c | |||
| 5875e7fd5a | |||
| 1ebd5a519a | |||
| 2a405cf231 | |||
| 593d27ce25 | |||
| 9913453a33 | |||
| dc95fe0560 | |||
| 52174cbb74 | |||
| dee12fb03a | |||
| d2a799f677 | |||
| 1f5d8541b8 | |||
| 26ba828ac8 | |||
| b5564a636d | |||
| c79123f0bb | |||
| 979db94865 | |||
| 81615d5c93 | |||
| 9236ce3218 | |||
| 9f8acef8ef | |||
| eede28f61e | |||
| 1e050eafe9 | |||
| c3fdae922d | |||
| 80ae6a8b6c | |||
| 5619aa43c7 | |||
| 928fdfaec0 | |||
| 027ff96416 | |||
| 4d3fcfdf88 | |||
| 2415d40416 | |||
| 848ab06119 | |||
| f3f7324ee8 | |||
| 3c9a512f00 | |||
| fe278d8ce4 | |||
| 9745038fd2 | |||
| e2c0163658 | |||
| 188b03b01c | |||
| 45de3fcaf8 | |||
| 4def27d800 | |||
| 8c69351274 | |||
| ed1c44ab51 | |||
| ec2ca34602 | |||
| 15f4dc5949 | |||
| ae69f2a809 | |||
| 54f3f66a7c | |||
| 027330db4e | |||
| 76c928892c | |||
| 6310a49bce | |||
| d4cce151e6 | |||
| b29f43e736 | |||
| 4b51b7f0ea | |||
| c00b6fb64c | |||
| 74ba63b5bf | |||
| 10cdf40d91 | |||
| 955537be1b | |||
| c8fec37bf2 | |||
| 33be2ccf65 | |||
| 430c3d1f1c | |||
| 330635c260 | |||
| 7117159bf6 | |||
| 20c297180b | |||
| 689bf5456d | |||
| 8353651f8d | |||
| 116a037e4d | |||
| 5ecdd364be | |||
| 1bb1c55c30 | |||
| 2e44c01088 | |||
| d8131e8900 | |||
| 9d1fabc605 | |||
| 1f1de164fd | |||
| 8b750f0e2e | |||
| a786cfcecd | |||
| c05b2f9841 | |||
| a641a564e2 | |||
| f42c06e42d |
@@ -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
|
||||
+5
-210
@@ -1,213 +1,8 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: MokoStandards.Maintenance
|
||||
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API
|
||||
# PATH: /templates/workflows/cascade-dev.yml.template
|
||||
# VERSION: 02.00.00
|
||||
# BRIEF: Forward-merge main all open branches after every push to main
|
||||
#
|
||||
# +========================================================================+
|
||||
# | CASCADE MAIN ALL BRANCHES |
|
||||
# +========================================================================+
|
||||
# | |
|
||||
# | Triggers on every push to main (PR merges, bot commits, etc.) |
|
||||
# | |
|
||||
# | 1. List all branches matching: dev, rc/*, beta/*, alpha/* |
|
||||
# | 2. For each: create PR (main branch), auto-merge if clean |
|
||||
# | 3. On conflict: leave PR open for manual resolution |
|
||||
# | |
|
||||
# +========================================================================+
|
||||
|
||||
name: Cascade Main Dev
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
GITEA_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 }}
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
# DISABLED - auto-release handles dev recreation from main
|
||||
name: Cascade (DISABLED)
|
||||
on: workflow_dispatch
|
||||
jobs:
|
||||
cascade:
|
||||
name: Cascade main branches
|
||||
noop:
|
||||
runs-on: ubuntu-latest
|
||||
if: >-
|
||||
!contains(github.event.head_commit.message, '[skip ci]') &&
|
||||
!contains(github.event.head_commit.message, '[skip cascade]')
|
||||
|
||||
steps:
|
||||
- name: Discover target branches
|
||||
id: branches
|
||||
env:
|
||||
GA_TOKEN: ${{ secrets.GA_TOKEN }}
|
||||
run: |
|
||||
API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
|
||||
# Fetch all branches (paginated)
|
||||
PAGE=1
|
||||
ALL_BRANCHES=""
|
||||
while true; do
|
||||
BATCH=$(curl -sS \
|
||||
-H "Authorization: token ${GA_TOKEN}" \
|
||||
"${API}/branches?page=${PAGE}&limit=50" \
|
||||
| jq -r '.[].name // empty')
|
||||
[ -z "$BATCH" ] && break
|
||||
ALL_BRANCHES="$ALL_BRANCHES $BATCH"
|
||||
PAGE=$((PAGE + 1))
|
||||
done
|
||||
|
||||
# Filter to cascade targets: dev, dev/*, rc/*, beta/*, alpha/*
|
||||
TARGETS=""
|
||||
for BRANCH in $ALL_BRANCHES; do
|
||||
case "$BRANCH" in
|
||||
dev|dev/*|rc/*|beta/*|alpha/*)
|
||||
TARGETS="$TARGETS $BRANCH"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
TARGETS=$(echo "$TARGETS" | xargs) # trim whitespace
|
||||
|
||||
if [ -z "$TARGETS" ]; then
|
||||
echo "targets=" >> "$GITHUB_OUTPUT"
|
||||
echo " No cascade target branches found"
|
||||
else
|
||||
echo "targets=$TARGETS" >> "$GITHUB_OUTPUT"
|
||||
COUNT=$(echo "$TARGETS" | wc -w)
|
||||
echo " Found ${COUNT} target branch(es): ${TARGETS}"
|
||||
fi
|
||||
|
||||
- name: Cascade to all target branches
|
||||
if: steps.branches.outputs.targets != ''
|
||||
env:
|
||||
GA_TOKEN: ${{ secrets.GA_TOKEN }}
|
||||
run: |
|
||||
API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
SHORT_SHA="${GITHUB_SHA:0:7}"
|
||||
TARGETS="${{ steps.branches.outputs.targets }}"
|
||||
|
||||
SUCCESS=0
|
||||
CONFLICTS=0
|
||||
SKIPPED=0
|
||||
FAILED=0
|
||||
|
||||
for BRANCH in $TARGETS; do
|
||||
echo ""
|
||||
echo " main ${BRANCH} "
|
||||
|
||||
# Check if branch is already up to date
|
||||
ENCODED_BRANCH=$(echo "$BRANCH" | sed 's|/|%2F|g')
|
||||
RESPONSE=$(curl -sS \
|
||||
-H "Authorization: token ${GA_TOKEN}" \
|
||||
"${API}/compare/${ENCODED_BRANCH}...main")
|
||||
|
||||
AHEAD=$(echo "$RESPONSE" | jq '.total_commits // 0')
|
||||
|
||||
if [ "$AHEAD" -eq 0 ]; then
|
||||
echo " Already up to date"
|
||||
SKIPPED=$((SKIPPED + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
echo " main is ${AHEAD} commit(s) ahead"
|
||||
|
||||
# Check for existing cascade PR
|
||||
EXISTING=$(curl -sS \
|
||||
-H "Authorization: token ${GA_TOKEN}" \
|
||||
"${API}/pulls?state=open&head=${GITEA_ORG}:main&base=${ENCODED_BRANCH}&limit=1")
|
||||
|
||||
EXISTING_COUNT=$(echo "$EXISTING" | jq 'length')
|
||||
PR_NUMBER=""
|
||||
|
||||
if [ "$EXISTING_COUNT" -gt 0 ]; then
|
||||
PR_NUMBER=$(echo "$EXISTING" | jq -r '.[0].number')
|
||||
echo " Reusing existing PR #${PR_NUMBER}"
|
||||
else
|
||||
# Create cascade PR
|
||||
PR_RESPONSE=$(curl -sS -w "\n%{http_code}" \
|
||||
-X POST \
|
||||
-H "Authorization: token ${GA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"title\": \"chore: cascade main ${BRANCH} (${SHORT_SHA}) [skip ci]\",
|
||||
\"body\": \"## Automatic cascade\\n\\nForward-merging \`main\` (${SHORT_SHA}) into \`${BRANCH}\`.\\n\\nIf conflicts exist, resolve manually and merge.\\n\\n> Auto-created by **Cascade Main Dev**.\",
|
||||
\"head\": \"main\",
|
||||
\"base\": \"${BRANCH}\"
|
||||
}" \
|
||||
"${API}/pulls")
|
||||
|
||||
HTTP_CODE=$(echo "$PR_RESPONSE" | tail -1)
|
||||
BODY=$(echo "$PR_RESPONSE" | sed '$d')
|
||||
PR_NUMBER=$(echo "$BODY" | jq -r '.number // empty')
|
||||
|
||||
if [ "$HTTP_CODE" != "201" ] || [ -z "$PR_NUMBER" ]; then
|
||||
MSG=$(echo "$BODY" | jq -r '.message // .' 2>/dev/null | head -1)
|
||||
echo " Failed to create PR (HTTP ${HTTP_CODE}): ${MSG}"
|
||||
FAILED=$((FAILED + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
echo " Created PR #${PR_NUMBER}"
|
||||
fi
|
||||
|
||||
# Try auto-merge
|
||||
PR_DATA=$(curl -sS \
|
||||
-H "Authorization: token ${GA_TOKEN}" \
|
||||
"${API}/pulls/${PR_NUMBER}")
|
||||
|
||||
MERGEABLE=$(echo "$PR_DATA" | jq -r '.mergeable // false')
|
||||
|
||||
if [ "$MERGEABLE" != "true" ]; then
|
||||
echo " Conflicts PR #${PR_NUMBER} left open"
|
||||
CONFLICTS=$((CONFLICTS + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
MERGE_RESPONSE=$(curl -sS -w "\n%{http_code}" \
|
||||
-X POST \
|
||||
-H "Authorization: token ${GA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"Do\": \"merge\",
|
||||
\"merge_message_field\": \"chore: cascade main ${BRANCH} [skip ci]\",
|
||||
\"delete_branch_after_merge\": false
|
||||
}" \
|
||||
"${API}/pulls/${PR_NUMBER}/merge")
|
||||
|
||||
MERGE_HTTP=$(echo "$MERGE_RESPONSE" | tail -1)
|
||||
|
||||
if [ "$MERGE_HTTP" = "200" ] || [ "$MERGE_HTTP" = "204" ]; then
|
||||
echo " Merged ${BRANCH} is in sync"
|
||||
SUCCESS=$((SUCCESS + 1))
|
||||
else
|
||||
MERGE_BODY=$(echo "$MERGE_RESPONSE" | sed '$d')
|
||||
echo " Merge failed (HTTP ${MERGE_HTTP}) PR #${PR_NUMBER} left open"
|
||||
CONFLICTS=$((CONFLICTS + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
# Summary
|
||||
echo ""
|
||||
echo ""
|
||||
echo " Merged: ${SUCCESS}"
|
||||
echo " Conflicts: ${CONFLICTS}"
|
||||
echo " Up to date: ${SKIPPED}"
|
||||
echo " Failed: ${FAILED}"
|
||||
echo ""
|
||||
|
||||
if [ "$FAILED" -gt 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
- run: echo disabled
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
-->
|
||||
<moko-platform xmlns="https://standards.mokoconsulting.tech/moko-platform/1.0" schema-version="1.0">
|
||||
<identity>
|
||||
<name>Template - MokoOnyx</name>
|
||||
<name>MokoOnyx</name>
|
||||
<display-name>Template - MokoOnyx</display-name>
|
||||
<org>MokoConsulting</org>
|
||||
<description>MokoOnyx - Joomla site template (successor to MokoCassiopeia)</description>
|
||||
<version>02.09.03</version>
|
||||
<version>02.17.00</version>
|
||||
<license spdx="GPL-3.0-or-later">GNU General Public License v3</license>
|
||||
</identity>
|
||||
<governance>
|
||||
|
||||
@@ -16,10 +16,9 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
- alpha
|
||||
- beta
|
||||
- rc
|
||||
- 'feature/**'
|
||||
- 'patch/**'
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
@@ -82,71 +82,33 @@ jobs:
|
||||
cd /tmp/moko-platform-api
|
||||
composer install --no-dev --no-interaction --quiet
|
||||
|
||||
- name: Rename source branch to rc
|
||||
- name: Rename branch to rc
|
||||
run: |
|
||||
SOURCE_BRANCH="${{ github.event.pull_request.head.ref || 'dev' }}"
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
PR_NUM="${{ github.event.pull_request.number }}"
|
||||
php /tmp/moko-platform-api/cli/branch_rename.php \
|
||||
--from "$SOURCE_BRANCH" --to rc \
|
||||
--from "${{ github.event.pull_request.head.ref || 'dev' }}" --to rc \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
|
||||
--api-base "${API_BASE}" \
|
||||
--pr "$PR_NUM"
|
||||
--api-base "${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" \
|
||||
--pr "${{ github.event.pull_request.number }}"
|
||||
|
||||
- name: Set RC version on renamed branch
|
||||
- name: Checkout rc and configure git
|
||||
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"
|
||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
||||
git config --local user.name "gitea-actions[bot]"
|
||||
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
||||
|
||||
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
|
||||
- name: Publish 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
|
||||
continue-on-error: true
|
||||
run: |
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
php /tmp/moko-platform-api/cli/release_cascade.php \
|
||||
--stability release-candidate \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
|
||||
--api-base "${API_BASE}"
|
||||
php /tmp/moko-platform-api/cli/release_publish.php \
|
||||
--path . --stability rc --bump minor --branch rc \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
|
||||
- name: Summary
|
||||
if: always()
|
||||
run: |
|
||||
echo "## Promoted to Release Candidate" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Draft PR opened — branch renamed to rc, RC release built" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Branch renamed to rc, minor bump, RC + lesser stream releases built, updates.xml synced" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# ── Merged PR → Build & Release (or promote RC to stable) ────────────────────
|
||||
release:
|
||||
@@ -188,266 +150,11 @@ jobs:
|
||||
composer install --no-dev --no-interaction --quiet
|
||||
|
||||
|
||||
# -- PLATFORM DETECTION ---------------------------------------------------
|
||||
- name: Detect platform
|
||||
id: platform
|
||||
- name: "Publish stable release"
|
||||
run: |
|
||||
php /tmp/moko-platform-api/cli/manifest_read.php --path . --github-output
|
||||
MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1 || true)
|
||||
MOD_FILE=$(find . -maxdepth 4 -name "mod*.class.php" ! -path "./.git/*" -exec grep -l 'extends DolibarrModules' {} \; 2>/dev/null | head -1 || true)
|
||||
echo "manifest=${MANIFEST}" >> "$GITHUB_OUTPUT"
|
||||
echo "mod_file=${MOD_FILE}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: "Step 1: Read version"
|
||||
id: version
|
||||
run: |
|
||||
VERSION=$(php /tmp/moko-platform-api/cli/version_read.php --path .)
|
||||
if [ -z "$VERSION" ]; then
|
||||
echo "::error::No VERSION in README.md"
|
||||
echo "skip=true" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
# version_set_platform strips suffixes internally when --stability stable
|
||||
MAJOR=$(echo "$VERSION" | cut -d. -f1 | sed 's/-.*//')
|
||||
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
echo "release_tag=stable" >> "$GITHUB_OUTPUT"
|
||||
echo "skip=false" >> "$GITHUB_OUTPUT"
|
||||
echo "branch=main" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# -- CHECK FOR RC PROMOTION ------------------------------------------------
|
||||
- name: "Check for RC release"
|
||||
id: rc
|
||||
if: steps.version.outputs.skip != 'true'
|
||||
run: |
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
RC_JSON=$(curl -sf -H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
|
||||
"${API_BASE}/releases/tags/release-candidate" 2>/dev/null || echo "{}")
|
||||
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
|
||||
echo "promote=true" >> "$GITHUB_OUTPUT"
|
||||
echo "release_id=${RC_ID}" >> "$GITHUB_OUTPUT"
|
||||
echo "::notice::RC release found (id: ${RC_ID}) — will promote to stable"
|
||||
else
|
||||
echo "promote=false" >> "$GITHUB_OUTPUT"
|
||||
echo "::notice::No RC release — full build pipeline"
|
||||
fi
|
||||
|
||||
- name: "Step 1b: Minor bump version"
|
||||
id: bump
|
||||
if: >-
|
||||
steps.version.outputs.skip != 'true' &&
|
||||
steps.rc.outputs.promote != 'true'
|
||||
run: |
|
||||
MOKO_API="/tmp/moko-platform-api/cli"
|
||||
php ${MOKO_API}/version_bump.php --path . --minor 2>&1 || true
|
||||
VERSION=$(php ${MOKO_API}/version_read.php --path .)
|
||||
# version_set_platform handles suffix stripping — just pass clean base version
|
||||
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
echo "Bumped to: ${VERSION}"
|
||||
|
||||
- name: Check if already released
|
||||
if: steps.version.outputs.skip != 'true'
|
||||
id: check
|
||||
run: |
|
||||
TAG="${{ steps.version.outputs.release_tag }}"
|
||||
BRANCH="${{ steps.version.outputs.branch }}"
|
||||
|
||||
TAG_EXISTS=false
|
||||
BRANCH_EXISTS=false
|
||||
|
||||
git rev-parse "$TAG" >/dev/null 2>&1 && TAG_EXISTS=true
|
||||
git ls-remote --heads origin "$BRANCH" 2>/dev/null | grep -q "$BRANCH" && BRANCH_EXISTS=true
|
||||
|
||||
echo "tag_exists=$TAG_EXISTS" >> "$GITHUB_OUTPUT"
|
||||
echo "branch_exists=$BRANCH_EXISTS" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Tag and branch may persist across patch releases — never skip
|
||||
echo "already_released=false" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# -- SANITY CHECKS -------------------------------------------------------
|
||||
- name: "Sanity: Pre-release validation"
|
||||
if: >-
|
||||
steps.version.outputs.skip != 'true' &&
|
||||
steps.check.outputs.already_released != 'true'
|
||||
run: |
|
||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||
php /tmp/moko-platform-api/cli/release_validate.php \
|
||||
--path . --version "$VERSION" --output-summary --github-output || true
|
||||
|
||||
# -- STEP 2: Create or update version/XX.YY archive branch ---------------
|
||||
# Always runs — every version change on main archives to version/XX.YY
|
||||
- name: "Step 2: Version archive branch"
|
||||
if: steps.check.outputs.already_released != 'true'
|
||||
run: |
|
||||
BRANCH="${{ steps.version.outputs.branch }}"
|
||||
IS_MINOR="${{ steps.version.outputs.is_minor }}"
|
||||
PATCH="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||
PATCH_NUM=$(echo "$PATCH" | awk -F. '{print $3}')
|
||||
|
||||
# Check if branch exists
|
||||
if git ls-remote --heads origin "$BRANCH" | grep -q "$BRANCH"; then
|
||||
git push origin HEAD:"$BRANCH" --force
|
||||
echo "Updated archive branch: ${BRANCH} (patch ${PATCH_NUM})" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
git checkout -b "$BRANCH" 2>/dev/null || git checkout "$BRANCH"
|
||||
git push origin "$BRANCH" --force
|
||||
echo "Created archive branch: ${BRANCH}" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
# -- STEP 3: Set platform version ----------------------------------------
|
||||
- name: "Step 3: Set platform version"
|
||||
if: >-
|
||||
steps.version.outputs.skip != 'true' &&
|
||||
steps.check.outputs.already_released != 'true'
|
||||
run: |
|
||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||
php /tmp/moko-platform-api/cli/version_set_platform.php \
|
||||
--path . --version "$VERSION" --branch main
|
||||
|
||||
# -- STEP 4: Update version badges ----------------------------------------
|
||||
- name: "Step 4: Update version badges"
|
||||
if: steps.version.outputs.skip != 'true'
|
||||
run: |
|
||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||
php /tmp/moko-platform-api/cli/badge_update.php --path . --version "${VERSION}" 2>/dev/null || true
|
||||
php /tmp/moko-platform-api/cli/version_check.php --path . --fix 2>/dev/null || true
|
||||
|
||||
# Step 5 (updates.xml) moved after Step 8 to include SHA-256 checksum
|
||||
|
||||
- name: "Step 4b: Promote and prune CHANGELOG"
|
||||
if: >-
|
||||
steps.version.outputs.skip != 'true' &&
|
||||
steps.check.outputs.already_released != 'true'
|
||||
run: |
|
||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||
MOKO_API="/tmp/moko-platform-api/cli"
|
||||
if [ -f "CHANGELOG.md" ]; then
|
||||
php ${MOKO_API}/changelog_promote.php --path . --version "$VERSION" 2>&1 || true
|
||||
php ${MOKO_API}/changelog_prune.php --path . --keep 5 2>&1 || true
|
||||
fi
|
||||
|
||||
- name: Commit release changes
|
||||
if: >-
|
||||
steps.version.outputs.skip != 'true' &&
|
||||
steps.check.outputs.already_released != 'true'
|
||||
run: |
|
||||
if git diff --quiet && git diff --cached --quiet; then
|
||||
echo "No changes to commit"
|
||||
exit 0
|
||||
fi
|
||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||
git add -A
|
||||
git commit -m "chore(release): build ${VERSION} [skip ci]" \
|
||||
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>"
|
||||
# Detached HEAD on PR merge — push explicitly to main
|
||||
git push origin HEAD:refs/heads/main
|
||||
|
||||
# -- STEP 6: Create tag ---------------------------------------------------
|
||||
- name: "Step 6: Create git tag"
|
||||
if: >-
|
||||
steps.version.outputs.skip != 'true'
|
||||
run: |
|
||||
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
|
||||
# Only create the major release tag if it doesn't exist yet
|
||||
if ! git rev-parse "$RELEASE_TAG" >/dev/null 2>&1; then
|
||||
git tag "$RELEASE_TAG"
|
||||
git push origin "$RELEASE_TAG"
|
||||
echo "Tag created: ${RELEASE_TAG}" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "Tag ${RELEASE_TAG} already exists" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
echo "Tag: ${TAG}" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# -- STEP 7a: Promote RC to stable (skip build) ----------------------------
|
||||
- name: "Step 7a: Promote RC to stable"
|
||||
if: >-
|
||||
steps.version.outputs.skip != 'true' &&
|
||||
steps.rc.outputs.promote == 'true'
|
||||
run: |
|
||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
php /tmp/moko-platform-api/cli/release_promote.php \
|
||||
--from release-candidate --to stable \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
|
||||
--api-base "${API_BASE}" \
|
||||
--path . --branch main
|
||||
echo "Promoted RC → stable (${VERSION})" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# -- STEP 7b: Create or update Gitea Release (full build path) -------------
|
||||
- name: "Step 7b: Gitea Release"
|
||||
if: >-
|
||||
steps.version.outputs.skip != 'true' &&
|
||||
steps.rc.outputs.promote != 'true'
|
||||
run: |
|
||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
php /tmp/moko-platform-api/cli/release_create.php \
|
||||
--path . --version "$VERSION" --tag "$RELEASE_TAG" \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
|
||||
--repo "${GITEA_REPO}" --branch main
|
||||
echo "Release created: ${VERSION}" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# -- STEP 8: Build packages and upload to release ----------------------------
|
||||
- name: "Step 8: Build package and upload"
|
||||
id: package
|
||||
if: >-
|
||||
steps.version.outputs.skip != 'true' &&
|
||||
steps.rc.outputs.promote != 'true'
|
||||
run: |
|
||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
php /tmp/moko-platform-api/cli/release_package.php \
|
||||
--path . --version "$VERSION" --tag "$RELEASE_TAG" \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
|
||||
--repo "${GITEA_REPO}" --output /tmp || true
|
||||
|
||||
# -- STEP 5: Write update stream (after build so SHA-256 is available) -----
|
||||
- name: "Step 5: Write update stream"
|
||||
if: steps.version.outputs.skip != 'true'
|
||||
run: |
|
||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||
SHA256="${{ steps.package.outputs.sha256_zip }}"
|
||||
|
||||
# Fetch latest updates.xml from main so preserve logic has all channels
|
||||
GITEA_TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
|
||||
curl -sf -H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${API}/contents/updates.xml?ref=main" 2>/dev/null | \
|
||||
php -r "\$d=json_decode(file_get_contents('php://stdin'),true); echo base64_decode(\$d['content'] ?? '');" \
|
||||
> updates.xml 2>/dev/null || true
|
||||
|
||||
SHA_FLAG=""
|
||||
[ -n "$SHA256" ] && SHA_FLAG="--sha ${SHA256}"
|
||||
|
||||
php /tmp/moko-platform-api/cli/updates_xml_build.php \
|
||||
--path . --version "${VERSION}" --stability stable \
|
||||
--gitea-url "${GITEA_URL}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}" \
|
||||
${SHA_FLAG} --github-output
|
||||
|
||||
# Commit updates.xml if changed
|
||||
if ! git diff --quiet updates.xml 2>/dev/null; then
|
||||
git add updates.xml
|
||||
git commit -m "chore: update stable channel ${VERSION} [skip ci]" \
|
||||
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>"
|
||||
git push origin HEAD:refs/heads/main 2>&1 || true
|
||||
fi
|
||||
|
||||
# -- STEP 8b: Update release description with changelog ----------------------
|
||||
- name: "Step 8b: Update release body"
|
||||
if: steps.version.outputs.skip != 'true'
|
||||
continue-on-error: true
|
||||
run: |
|
||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
|
||||
php /tmp/moko-platform-api/cli/release_body_update.php \
|
||||
--path . --version "${VERSION}" --tag "${RELEASE_TAG}" \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
|
||||
--gitea-url "${GITEA_URL}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}" \
|
||||
2>&1 || true
|
||||
echo "Release body updated" >> $GITHUB_STEP_SUMMARY
|
||||
php /tmp/moko-platform-api/cli/release_publish.php \
|
||||
--path . --stability stable --bump minor --branch main \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}"
|
||||
|
||||
# -- STEP 9: Mirror to GitHub (stable only) --------------------------------
|
||||
- name: "Step 9: Mirror release to GitHub"
|
||||
@@ -484,33 +191,17 @@ jobs:
|
||||
&& echo "main branch pushed to GitHub mirror" \
|
||||
|| echo "WARNING: GitHub mirror push failed"
|
||||
|
||||
# -- Clean up lesser pre-releases (cascade) ---------------------------------
|
||||
# stable → deletes all | rc → beta,alpha,dev | beta → alpha,dev | alpha → dev
|
||||
- name: "Delete lesser pre-release channels"
|
||||
continue-on-error: true
|
||||
run: |
|
||||
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
php /tmp/moko-platform-api/cli/release_cascade.php \
|
||||
--stability stable \
|
||||
--version "${VERSION}" \
|
||||
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
|
||||
--api-base "${API_BASE}" 2>/dev/null || true
|
||||
|
||||
- name: "Step 11: Clean up pre-release branches and recreate dev from main"
|
||||
- name: "Step 11: Delete rc branch and recreate dev from main"
|
||||
if: steps.version.outputs.skip != 'true'
|
||||
continue-on-error: true
|
||||
run: |
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
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 rc branch (ephemeral — created by promote-rc)
|
||||
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
|
||||
"${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}" \
|
||||
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
run: |
|
||||
BRANCH="${{ github.event.pull_request.head.ref }}"
|
||||
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 \
|
||||
-H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
|
||||
|
||||
@@ -1,213 +1,8 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: moko-platform.Maintenance
|
||||
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/moko-platform
|
||||
# PATH: /templates/workflows/cascade-dev.yml.template
|
||||
# VERSION: 02.00.00
|
||||
# BRIEF: Forward-merge main → all open branches after every push to main
|
||||
#
|
||||
# +========================================================================+
|
||||
# | CASCADE MAIN → ALL BRANCHES |
|
||||
# +========================================================================+
|
||||
# | |
|
||||
# | Triggers on every push to main (PR merges, bot commits, etc.) |
|
||||
# | |
|
||||
# | 1. List all branches matching: dev, rc/*, beta/*, alpha/* |
|
||||
# | 2. For each: create PR (main → branch), auto-merge if clean |
|
||||
# | 3. On conflict: leave PR open for manual resolution |
|
||||
# | |
|
||||
# +========================================================================+
|
||||
|
||||
name: "Universal: Cascade Main → Dev"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
GITEA_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 }}
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
# DISABLED - auto-release handles dev recreation from main
|
||||
name: Cascade (DISABLED)
|
||||
on: workflow_dispatch
|
||||
jobs:
|
||||
cascade:
|
||||
name: Cascade main → branches
|
||||
noop:
|
||||
runs-on: ubuntu-latest
|
||||
if: >-
|
||||
!contains(github.event.head_commit.message, '[skip ci]') &&
|
||||
!contains(github.event.head_commit.message, '[skip cascade]')
|
||||
|
||||
steps:
|
||||
- name: Discover target branches
|
||||
id: branches
|
||||
env:
|
||||
GA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
run: |
|
||||
API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
|
||||
# Fetch all branches (paginated)
|
||||
PAGE=1
|
||||
ALL_BRANCHES=""
|
||||
while true; do
|
||||
BATCH=$(curl -sS \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${API}/branches?page=${PAGE}&limit=50" \
|
||||
| jq -r '.[].name // empty')
|
||||
[ -z "$BATCH" ] && break
|
||||
ALL_BRANCHES="$ALL_BRANCHES $BATCH"
|
||||
PAGE=$((PAGE + 1))
|
||||
done
|
||||
|
||||
# Filter to cascade targets: dev, dev/*, rc/*, beta/*, alpha/*
|
||||
TARGETS=""
|
||||
for BRANCH in $ALL_BRANCHES; do
|
||||
case "$BRANCH" in
|
||||
dev|dev/*|rc/*|beta/*|alpha/*)
|
||||
TARGETS="$TARGETS $BRANCH"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
TARGETS=$(echo "$TARGETS" | xargs) # trim whitespace
|
||||
|
||||
if [ -z "$TARGETS" ]; then
|
||||
echo "targets=" >> "$GITHUB_OUTPUT"
|
||||
echo "ℹ️ No cascade target branches found"
|
||||
else
|
||||
echo "targets=$TARGETS" >> "$GITHUB_OUTPUT"
|
||||
COUNT=$(echo "$TARGETS" | wc -w)
|
||||
echo "📋 Found ${COUNT} target branch(es): ${TARGETS}"
|
||||
fi
|
||||
|
||||
- name: Cascade to all target branches
|
||||
if: steps.branches.outputs.targets != ''
|
||||
env:
|
||||
GA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
|
||||
run: |
|
||||
API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
SHORT_SHA="${GITHUB_SHA:0:7}"
|
||||
TARGETS="${{ steps.branches.outputs.targets }}"
|
||||
|
||||
SUCCESS=0
|
||||
CONFLICTS=0
|
||||
SKIPPED=0
|
||||
FAILED=0
|
||||
|
||||
for BRANCH in $TARGETS; do
|
||||
echo ""
|
||||
echo "═══ main → ${BRANCH} ═══"
|
||||
|
||||
# Check if branch is already up to date
|
||||
ENCODED_BRANCH=$(echo "$BRANCH" | sed 's|/|%2F|g')
|
||||
RESPONSE=$(curl -sS \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${API}/compare/${ENCODED_BRANCH}...main")
|
||||
|
||||
AHEAD=$(echo "$RESPONSE" | jq '.total_commits // 0')
|
||||
|
||||
if [ "$AHEAD" -eq 0 ]; then
|
||||
echo " ✅ Already up to date"
|
||||
SKIPPED=$((SKIPPED + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
echo " ℹ️ main is ${AHEAD} commit(s) ahead"
|
||||
|
||||
# Check for existing cascade PR
|
||||
EXISTING=$(curl -sS \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${API}/pulls?state=open&head=${GITEA_ORG}:main&base=${ENCODED_BRANCH}&limit=1")
|
||||
|
||||
EXISTING_COUNT=$(echo "$EXISTING" | jq 'length')
|
||||
PR_NUMBER=""
|
||||
|
||||
if [ "$EXISTING_COUNT" -gt 0 ]; then
|
||||
PR_NUMBER=$(echo "$EXISTING" | jq -r '.[0].number')
|
||||
echo " ℹ️ Reusing existing PR #${PR_NUMBER}"
|
||||
else
|
||||
# Create cascade PR
|
||||
PR_RESPONSE=$(curl -sS -w "\n%{http_code}" \
|
||||
-X POST \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"title\": \"chore: cascade main → ${BRANCH} (${SHORT_SHA}) [skip ci]\",
|
||||
\"body\": \"## Automatic cascade\\n\\nForward-merging \`main\` (${SHORT_SHA}) into \`${BRANCH}\`.\\n\\nIf conflicts exist, resolve manually and merge.\\n\\n> Auto-created by **Cascade Main → Dev**.\",
|
||||
\"head\": \"main\",
|
||||
\"base\": \"${BRANCH}\"
|
||||
}" \
|
||||
"${API}/pulls")
|
||||
|
||||
HTTP_CODE=$(echo "$PR_RESPONSE" | tail -1)
|
||||
BODY=$(echo "$PR_RESPONSE" | sed '$d')
|
||||
PR_NUMBER=$(echo "$BODY" | jq -r '.number // empty')
|
||||
|
||||
if [ "$HTTP_CODE" != "201" ] || [ -z "$PR_NUMBER" ]; then
|
||||
MSG=$(echo "$BODY" | jq -r '.message // .' 2>/dev/null | head -1)
|
||||
echo " ❌ Failed to create PR (HTTP ${HTTP_CODE}): ${MSG}"
|
||||
FAILED=$((FAILED + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
echo " ✅ Created PR #${PR_NUMBER}"
|
||||
fi
|
||||
|
||||
# Try auto-merge
|
||||
PR_DATA=$(curl -sS \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${API}/pulls/${PR_NUMBER}")
|
||||
|
||||
MERGEABLE=$(echo "$PR_DATA" | jq -r '.mergeable // false')
|
||||
|
||||
if [ "$MERGEABLE" != "true" ]; then
|
||||
echo " ⚠️ Conflicts — PR #${PR_NUMBER} left open"
|
||||
CONFLICTS=$((CONFLICTS + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
MERGE_RESPONSE=$(curl -sS -w "\n%{http_code}" \
|
||||
-X POST \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"Do\": \"merge\",
|
||||
\"merge_message_field\": \"chore: cascade main → ${BRANCH} [skip ci]\",
|
||||
\"delete_branch_after_merge\": false
|
||||
}" \
|
||||
"${API}/pulls/${PR_NUMBER}/merge")
|
||||
|
||||
MERGE_HTTP=$(echo "$MERGE_RESPONSE" | tail -1)
|
||||
|
||||
if [ "$MERGE_HTTP" = "200" ] || [ "$MERGE_HTTP" = "204" ]; then
|
||||
echo " ✅ Merged — ${BRANCH} is in sync"
|
||||
SUCCESS=$((SUCCESS + 1))
|
||||
else
|
||||
MERGE_BODY=$(echo "$MERGE_RESPONSE" | sed '$d')
|
||||
echo " ⚠️ Merge failed (HTTP ${MERGE_HTTP}) — PR #${PR_NUMBER} left open"
|
||||
CONFLICTS=$((CONFLICTS + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
# Summary
|
||||
echo ""
|
||||
echo "════════════════════════════════════════"
|
||||
echo " ✅ Merged: ${SUCCESS}"
|
||||
echo " ⚠️ Conflicts: ${CONFLICTS}"
|
||||
echo " ⏭️ Up to date: ${SKIPPED}"
|
||||
echo " ❌ Failed: ${FAILED}"
|
||||
echo "════════════════════════════════════════"
|
||||
|
||||
if [ "$FAILED" -gt 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
- run: echo disabled
|
||||
|
||||
@@ -5,7 +5,17 @@
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: moko-platform.Automation
|
||||
# VERSION: 02.09.03
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
# VERSION: 02.17.00
|
||||
=======
|
||||
# VERSION: 02.17.00
|
||||
=======
|
||||
# VERSION: 02.17.00
|
||||
=======
|
||||
# VERSION: 02.17.00
|
||||
>>>>>>> origin/main
|
||||
>>>>>>> origin/main
|
||||
# BRIEF: Auto-create feature branch when an issue is opened
|
||||
|
||||
name: "Universal: Issue Branch"
|
||||
|
||||
@@ -52,22 +52,22 @@ jobs:
|
||||
REASON="Fix branches must target 'dev', not '${BASE}'"
|
||||
fi
|
||||
;;
|
||||
patch/*)
|
||||
if [ "$BASE" != "dev" ] && [ "$BASE" != "rc" ]; then
|
||||
ALLOWED=false
|
||||
REASON="Patch branches must target 'dev' or 'rc', not '${BASE}'"
|
||||
fi
|
||||
;;
|
||||
hotfix/*)
|
||||
if [ "$BASE" != "dev" ] && [ "$BASE" != "main" ]; then
|
||||
ALLOWED=false
|
||||
REASON="Hotfix branches can only target 'dev' or 'main', not '${BASE}'"
|
||||
fi
|
||||
;;
|
||||
alpha/*|beta/*)
|
||||
if [ "$BASE" != "dev" ]; then
|
||||
ALLOWED=false
|
||||
REASON="Pre-release branches must target 'dev', not '${BASE}'"
|
||||
fi
|
||||
;;
|
||||
rc/*)
|
||||
rc)
|
||||
if [ "$BASE" != "main" ]; then
|
||||
ALLOWED=false
|
||||
REASON="Release candidate branches must target 'main', not '${BASE}'"
|
||||
REASON="RC branch can only merge into 'main', not '${BASE}'"
|
||||
fi
|
||||
;;
|
||||
dev)
|
||||
@@ -183,6 +183,28 @@ jobs:
|
||||
;;
|
||||
esac
|
||||
|
||||
- name: Check changelog has unreleased entry
|
||||
run: |
|
||||
if [ ! -f "CHANGELOG.md" ]; then
|
||||
echo "::warning::No CHANGELOG.md found"
|
||||
exit 0
|
||||
fi
|
||||
# Check for content under [Unreleased] section
|
||||
if ! grep -q "## \[Unreleased\]" CHANGELOG.md; then
|
||||
echo "::error::CHANGELOG.md missing [Unreleased] section"
|
||||
exit 1
|
||||
fi
|
||||
# Check there's at least one entry (Added/Changed/Fixed/Removed) under Unreleased
|
||||
UNRELEASED_CONTENT=$(sed -n '/## \[Unreleased\]/,/## \[/p' CHANGELOG.md | grep -cE '^\s*-\s' || true)
|
||||
if [ "$UNRELEASED_CONTENT" -eq 0 ]; then
|
||||
echo "::error::CHANGELOG.md [Unreleased] section has no entries. Add a changelog entry describing your changes."
|
||||
echo "## Changelog Check: Failed" >> $GITHUB_STEP_SUMMARY
|
||||
echo "The \`[Unreleased]\` section in CHANGELOG.md has no entries." >> $GITHUB_STEP_SUMMARY
|
||||
echo "Add a line like \`- Description of your change\` under a heading (\`### Added\`, \`### Changed\`, \`### Fixed\`, etc.)" >> $GITHUB_STEP_SUMMARY
|
||||
exit 1
|
||||
fi
|
||||
echo "Changelog: ${UNRELEASED_CONTENT} entry/entries in [Unreleased]"
|
||||
|
||||
- name: Verify package source
|
||||
run: |
|
||||
SOURCE_DIR="src"
|
||||
|
||||
+45
-32
@@ -8,52 +8,65 @@
|
||||
DEFGROUP: Joomla.Template.Site
|
||||
INGROUP: MokoOnyx.Documentation
|
||||
PATH: ./CHANGELOG.md
|
||||
VERSION: 02.09.03
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
VERSION: 02.17.00
|
||||
BRIEF: Changelog file documenting version history of MokoOnyx
|
||||
-->
|
||||
|
||||
# Changelog — MokoOnyx (VERSION: 02.09.03)
|
||||
# Changelog — MokoOnyx (VERSION: 02.17.00)
|
||||
## [Unreleased]
|
||||
|
||||
## [02.08.00] --- 2026-05-29
|
||||
=======
|
||||
VERSION: 02.17.00
|
||||
BRIEF: Changelog file documenting version history of MokoOnyx
|
||||
-->
|
||||
|
||||
## [02.08.00] --- 2026-05-29
|
||||
# Changelog — MokoOnyx (VERSION: 02.17.00)
|
||||
>>>>>>> origin/main
|
||||
=======
|
||||
VERSION: 02.17.00
|
||||
BRIEF: Changelog file documenting version history of MokoOnyx
|
||||
-->
|
||||
|
||||
## [02.08.00] --- 2026-05-29
|
||||
# Changelog — MokoOnyx (VERSION: 02.17.00)
|
||||
>>>>>>> origin/main
|
||||
## [02.17.00] --- 2026-05-30
|
||||
|
||||
## [02.08.00] --- 2026-05-28
|
||||
## [02.15.00] --- 2026-05-30
|
||||
|
||||
=======
|
||||
VERSION: 02.17.00
|
||||
BRIEF: Changelog file documenting version history of MokoOnyx
|
||||
-->
|
||||
|
||||
All notable changes to the MokoOnyx Joomla template are documented in this file.
|
||||
# Changelog — MokoOnyx (VERSION: 02.17.00)
|
||||
>>>>>>> origin/main
|
||||
## [02.14.00] --- 2026-05-30
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [02.08.01] --- 2026-05-28
|
||||
|
||||
### Changed
|
||||
- Migrated all workflow and template paths from `.github/` to `.mokogitea/`
|
||||
- Template source paths updated: `templates/gitea/` to `templates/mokogitea/`
|
||||
- HCL definition files removed -- Template repos are now the canonical source
|
||||
## [02.13.00] --- 2026-05-30
|
||||
|
||||
### Added
|
||||
- `branch-cleanup.yml`: auto-delete merged feature branches after PR merge
|
||||
|
||||
### Removed
|
||||
- Removed deploy-manual.yml workflow -- switching to Joomla update server method for extension distribution
|
||||
- Removed deploy variables and secrets (DEV_FTP_*)
|
||||
- **Theme preview removed** -- Removed unused language strings for theme preview feature (never wired into config)
|
||||
- **Repo cleanup** -- Removed 38 unused files: Fredoka/Pacifico fonts, dead npm tooling (package.json, scripts/), tmp-overrides/, placeholder tests, orphaned workflow copies, stale READMEs
|
||||
- **Broken font options removed** -- Removed Noto Sans and Fira Sans from font selector (CSS files never existed)
|
||||
- **Docs moved to wiki** -- CONTRIBUTING.md, CODE_OF_CONDUCT.md, GOVERNANCE.md migrated to Gitea wiki
|
||||
- Hero image (`hero.jpg`) to template images
|
||||
- `.fa-solid`, `.fa-regular`, `.fa-brands`, `.fa-light` icon margin spacing
|
||||
- `.blog-item .item-image` fixed 250px height with object-fit cover
|
||||
- Hide header on home page option (`hideHeaderHome` template param)
|
||||
- Hide main menu on home page option (`hideMenuHome` template param)
|
||||
- Three distinct menu overrides: mainmenu (collapsible), horizontal (always visible), default (vertical)
|
||||
- `<php_minimum>8.1.0</php_minimum>` to templateDetails.xml
|
||||
- `<changelogurl>` support in updates.xml
|
||||
- CONTRIBUTING.md with universal workflow and version policy
|
||||
|
||||
### Changed
|
||||
- **repo-health.yml** -- Wiki-preferred documentation checks via Gitea API (wiki = full credit, repo file = advisory)
|
||||
- **auto-release.yml Step 8b** -- Replaced inline Python with release_body_update.php CLI tool (fixes SIGPIPE exit 141)
|
||||
- **pre-release.yml rewritten** -- Uses moko-platform CLI tools, PHP instead of Python, fixed broken platform detection
|
||||
- **All workflow YAML files** -- Stripped non-ASCII characters (em dashes, arrows, emoji) for Gitea YAML parser compatibility
|
||||
- Release pipeline rework: independent update streams, CLI-driven workflows
|
||||
- Version bumps only trigger on `src/` changes (not docs/config)
|
||||
- Branch protection: CI bot only for push, force push disabled
|
||||
- Auto-bump supports dev, rc, feature/*, patch/* branches
|
||||
|
||||
### Fixed
|
||||
- **Menu icon padding removed** -- Removed hardcoded `p-2` class from all mod_menu icon spans (horizontal + mainmenu layouts); icons now inherit spacing from the parent link
|
||||
- **Runner checkout failures** -- Fixed MySQL deadlocks in Gitea actions scheduler by restarting Gitea and recreating runners with --privileged flag
|
||||
- **workflow_dispatch 500 error** -- Stripped UTF-8 multibyte characters from all YAML files that Gitea's Go parser rejected as control characters
|
||||
- Joomla update loop caused by version mismatch between ZIP and updates.xml
|
||||
- Duplicate hamburger menu on mobile
|
||||
- Stacked version suffixes (-dev-dev-dev)
|
||||
- Template name doubling (Template - Template - MokoOnyx)
|
||||
|
||||
## [02.08.00] --- 2026-05-29
|
||||
|
||||
+147
-16
@@ -1,29 +1,160 @@
|
||||
# Contributing to MokoOnyx
|
||||
# Contributing to Moko Consulting Projects
|
||||
|
||||
See the [universal contributing guide](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/blob/main/CONTRIBUTING.md) for branching workflow, version policy, and code standards.
|
||||
Thank you for your interest in contributing. All Moko Consulting repositories follow this universal workflow and version policy.
|
||||
|
||||
## Repo-specific setup
|
||||
## Branching Workflow
|
||||
|
||||
```bash
|
||||
composer install
|
||||
```
|
||||
feature/* ──PR──> dev ──draft PR──> (renamed to rc) ──merge──> main
|
||||
```
|
||||
|
||||
## Building
|
||||
### Step by step
|
||||
|
||||
This is a Joomla site template. The source lives in `src/` and is packaged into a ZIP for installation.
|
||||
1. **Create a feature branch** from `dev`:
|
||||
```bash
|
||||
git checkout dev && git pull
|
||||
git checkout -b feature/my-change
|
||||
```
|
||||
|
||||
- CSS/JS minification is handled at build time (CI) and runtime (`MokoMinifyHelper`)
|
||||
- Custom theme CSS goes in `src/media/css/theme/`
|
||||
- Template overrides go in `src/html/`
|
||||
2. **Work and commit** on your feature branch. Push to origin.
|
||||
|
||||
## Testing
|
||||
3. **Open a PR**: `feature/my-change` → `dev`. After review and checks, merge it.
|
||||
|
||||
Install the template on a Joomla 5.x or 6.x site and verify:
|
||||
4. **When ready for release**, open a **draft PR**: `dev` → `main`.
|
||||
- This automatically renames the source branch to `rc` (release candidate)
|
||||
- An RC pre-release is built and uploaded
|
||||
|
||||
- Theme switching (light/dark/custom)
|
||||
- Mobile responsive behaviour (hamburger menu, layout)
|
||||
- Font Awesome icons render correctly
|
||||
- Table of Contents auto-generation works
|
||||
5. **Alpha and beta branches** are created by manually renaming the branch before the RC stage:
|
||||
- Rename `dev` to `alpha` for early testing → alpha pre-release is built
|
||||
- Rename `alpha` to `beta` for feature-complete testing → beta pre-release is built
|
||||
- When the draft PR is created, the branch is renamed to `rc`
|
||||
|
||||
6. **Once PR checks pass** on the `rc` branch, mark the PR as ready and merge to `main`.
|
||||
|
||||
7. **Merging to main** triggers the stable release pipeline:
|
||||
- Minor version bump (e.g., `02.09.xx` → `02.10.00`)
|
||||
- Stability suffix stripped (clean version)
|
||||
- Gitea release created with ZIP/tar.gz packages
|
||||
- `updates.xml` updated (Joomla extensions)
|
||||
- `dev` branch recreated from `main`
|
||||
|
||||
### Branch summary
|
||||
|
||||
| Branch | Purpose | Created by |
|
||||
|--------|---------|-----------|
|
||||
| `feature/*` | New features and fixes | Developer |
|
||||
| `dev` | Integration branch | Auto-recreated after release |
|
||||
| `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 |
|
||||
|
||||
### Protected branches
|
||||
|
||||
| Branch | Direct push | Merge via |
|
||||
|--------|------------|-----------|
|
||||
| `main` | Blocked (CI bot whitelisted) | PR merge only |
|
||||
| `dev` | Blocked (CI bot whitelisted) | PR merge from feature/* |
|
||||
| `rc` | Blocked (CI bot whitelisted) | Auto-created on draft PR |
|
||||
| `alpha` | Blocked (CI bot whitelisted) | Manual rename |
|
||||
| `beta` | Blocked (CI bot whitelisted) | Manual rename |
|
||||
| `feature/*` | Open | N/A (source branch) |
|
||||
|
||||
## Version Policy
|
||||
|
||||
### Format
|
||||
|
||||
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`, `feature/*`, or `patch/*`:
|
||||
|
||||
1. Patch version incremented
|
||||
2. Stability suffix `-dev` applied
|
||||
3. All version-bearing files updated (manifests, CHANGELOG, PHP headers, etc.)
|
||||
4. Commit created with `[skip ci]` to avoid loops
|
||||
|
||||
### Release version flow
|
||||
|
||||
Version bumps happen at specific release events:
|
||||
|
||||
| Event | Bump | Example |
|
||||
|-------|------|---------|
|
||||
| Feature merged to dev | Patch bump after dev release | `02.09.01-dev` → release → `02.09.02-dev` |
|
||||
| Dev promoted to RC | Minor bump | `02.09.02-dev` → `02.10.00-rc` |
|
||||
| RC merged to main | Minor bump | `02.10.00-rc` → `02.11.00` (stable) |
|
||||
| Dev recreated from main | Patch bump | `02.11.00` → `02.11.01-dev` |
|
||||
|
||||
### Release stream copies
|
||||
|
||||
When a higher-stability release is published, copies are created for all lesser streams with the same base version:
|
||||
|
||||
- **RC `02.10.00-rc`** also creates: `02.10.00-dev`, `02.10.00-alpha`, `02.10.00-beta`
|
||||
- **Stable `02.11.00`** also creates: `02.11.00-dev`, `02.11.00-alpha`, `02.11.00-beta`, `02.11.00-rc`
|
||||
|
||||
This ensures Joomla sites on ANY stability channel see the update (Joomla only shows versions higher than what's installed).
|
||||
|
||||
### 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.
|
||||
|
||||
---
|
||||
|
||||
|
||||
+11
-1
@@ -10,7 +10,17 @@
|
||||
INGROUP: MokoOnyx.Governance
|
||||
REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
|
||||
FILE: SECURITY.md
|
||||
VERSION: 02.09.03
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
VERSION: 02.17.00
|
||||
=======
|
||||
VERSION: 02.17.00
|
||||
=======
|
||||
VERSION: 02.17.00
|
||||
=======
|
||||
VERSION: 02.17.00
|
||||
>>>>>>> origin/main
|
||||
>>>>>>> origin/main
|
||||
BRIEF: Security policy and vulnerability reporting process for MokoOnyx.
|
||||
PATH: /SECURITY.md
|
||||
NOTE: This policy is process oriented and does not replace secure engineering practices.
|
||||
|
||||
@@ -11,7 +11,17 @@
|
||||
* INGROUP: MokoOnyx
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
|
||||
* PATH: /html/com_joomgallery/category/default.php
|
||||
* VERSION: 02.09.03
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
* VERSION: 02.17.00
|
||||
=======
|
||||
* VERSION: 02.17.00
|
||||
=======
|
||||
* VERSION: 02.17.00
|
||||
=======
|
||||
* VERSION: 02.17.00
|
||||
>>>>>>> origin/main
|
||||
>>>>>>> origin/main
|
||||
* BRIEF: Category view override — password gate then loads default_cat sub-layout
|
||||
*/
|
||||
|
||||
|
||||
@@ -11,7 +11,17 @@
|
||||
* INGROUP: MokoOnyx
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
|
||||
* PATH: /html/com_joomgallery/category/default_cat.php
|
||||
* VERSION: 02.09.03
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
* VERSION: 02.17.00
|
||||
=======
|
||||
* VERSION: 02.17.00
|
||||
=======
|
||||
* VERSION: 02.17.00
|
||||
=======
|
||||
* VERSION: 02.17.00
|
||||
>>>>>>> origin/main
|
||||
>>>>>>> origin/main
|
||||
* BRIEF: Category sub-layout — subcategories grid + images grid with pagination
|
||||
*/
|
||||
|
||||
|
||||
@@ -11,7 +11,17 @@
|
||||
* INGROUP: MokoOnyx
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
|
||||
* PATH: /html/com_joomgallery/gallery/default.php
|
||||
* VERSION: 02.09.03
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
* VERSION: 02.17.00
|
||||
=======
|
||||
* VERSION: 02.17.00
|
||||
=======
|
||||
* VERSION: 02.17.00
|
||||
=======
|
||||
* VERSION: 02.17.00
|
||||
>>>>>>> origin/main
|
||||
>>>>>>> origin/main
|
||||
* BRIEF: Gallery view override — main image grid with masonry/justified layout
|
||||
*/
|
||||
|
||||
|
||||
@@ -11,7 +11,17 @@
|
||||
* INGROUP: MokoOnyx
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
|
||||
* PATH: /html/com_joomgallery/image/default.php
|
||||
* VERSION: 02.09.03
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
* VERSION: 02.17.00
|
||||
=======
|
||||
* VERSION: 02.17.00
|
||||
=======
|
||||
* VERSION: 02.17.00
|
||||
=======
|
||||
* VERSION: 02.17.00
|
||||
>>>>>>> origin/main
|
||||
>>>>>>> origin/main
|
||||
* BRIEF: Image detail view override — single image with metadata, tags, custom fields
|
||||
*/
|
||||
|
||||
|
||||
@@ -10,7 +10,17 @@
|
||||
* INGROUP: MokoOnyx
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
|
||||
* PATH: /html/layouts/joomla/module/card.php
|
||||
* VERSION: 02.09.03
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
* VERSION: 02.17.00
|
||||
=======
|
||||
* VERSION: 02.17.00
|
||||
=======
|
||||
* VERSION: 02.17.00
|
||||
=======
|
||||
* VERSION: 02.17.00
|
||||
>>>>>>> origin/main
|
||||
>>>>>>> origin/main
|
||||
* BRIEF: Custom card module chrome — renders module titles for all modules
|
||||
*/
|
||||
|
||||
|
||||
@@ -11,7 +11,17 @@
|
||||
* INGROUP: MokoOnyx.Layouts
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
|
||||
* PATH: /src/html/layouts/mokoonyx/article-metadata.php
|
||||
* VERSION: 02.09.03
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
* VERSION: 02.17.00
|
||||
=======
|
||||
* VERSION: 02.17.00
|
||||
=======
|
||||
* VERSION: 02.17.00
|
||||
=======
|
||||
* VERSION: 02.17.00
|
||||
>>>>>>> origin/main
|
||||
>>>>>>> origin/main
|
||||
* BRIEF: Article metadata footer layout -- renders jcfields grouped by field group
|
||||
*/
|
||||
|
||||
|
||||
+7
-2
@@ -205,7 +205,10 @@ if ($this->countModules('drawer-left', true) || $this->countModules('drawer-righ
|
||||
|
||||
// Container
|
||||
$wrapper = $this->params->get('fluidContainer') ? 'wrapper-fluid' : 'wrapper-static';
|
||||
$stickyHeader = $this->params->get('stickyHeader') ? 'position-sticky sticky-top' : '';
|
||||
$stickyHeader = $this->params->get('stickyHeader') ? 'position-sticky sticky-top' : '';
|
||||
$isHomePage = Factory::getApplication()->getMenu()->getActive() === Factory::getApplication()->getMenu()->getDefault();
|
||||
$hideHeaderHome = $isHomePage && (int) $this->params->get('hideHeaderHome', 0);
|
||||
$hideMenuHome = $isHomePage && (int) $this->params->get('hideMenuHome', 0);
|
||||
|
||||
// Meta
|
||||
$this->setMetaData('viewport', 'width=device-width, initial-scale=1');
|
||||
@@ -430,6 +433,7 @@ $wa->useScript('user.js'); // js/user.js
|
||||
<!-- End Google Analytics -->
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!$hideHeaderHome) : ?>
|
||||
<header id="top" class="header container-header full-width<?php echo $stickyHeader ? ' ' . $stickyHeader : ''; ?>" role="banner">
|
||||
|
||||
<?php if ($this->countModules('topbar')) : ?>
|
||||
@@ -493,7 +497,7 @@ $wa->useScript('user.js'); // js/user.js
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($this->countModules('menu', true) || $this->countModules('search', true)) : ?>
|
||||
<?php if (($this->countModules('menu', true) || $this->countModules('search', true)) && !$hideMenuHome) : ?>
|
||||
<div class="grid-child container-nav">
|
||||
<?php // Mobile: hamburger (left) + search icon (right) on one line ?>
|
||||
<div class="nav-mobile-bar d-lg-none">
|
||||
@@ -521,6 +525,7 @@ $wa->useScript('user.js'); // js/user.js
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</header>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="site-grid">
|
||||
<?php if ($this->countModules('banner', true)) : ?>
|
||||
|
||||
@@ -61,6 +61,10 @@ TPL_MOKOONYX_FONT_NOTE_TEXT="Loading fonts from external sources might be agains
|
||||
|
||||
; ===== Header & navigation (Theme tab) =====
|
||||
TPL_MOKOONYX_STICKY_LABEL="Sticky Header"
|
||||
TPL_MOKOONYX_HIDE_HEADER_HOME_LABEL="Hide Header on Home Page"
|
||||
TPL_MOKOONYX_HIDE_HEADER_HOME_DESC="Hide the site header (logo, branding) on the front page only."
|
||||
TPL_MOKOONYX_HIDE_MENU_HOME_LABEL="Hide Main Menu on Home Page"
|
||||
TPL_MOKOONYX_HIDE_MENU_HOME_DESC="Hide the main navigation menu on the front page only."
|
||||
TPL_MOKOONYX_BACKTOTOP="Back to Top"
|
||||
TPL_MOKOONYX_TOC_TITLE="Table of Contents"
|
||||
TPL_MOKOONYX_BACKTOTOP_LABEL="Back-to-top Link"
|
||||
|
||||
@@ -61,6 +61,10 @@ TPL_MOKOONYX_FONT_NOTE_TEXT="Loading fonts from external sources might be agains
|
||||
|
||||
; ===== Header & navigation (Theme tab) =====
|
||||
TPL_MOKOONYX_STICKY_LABEL="Sticky Header"
|
||||
TPL_MOKOONYX_HIDE_HEADER_HOME_LABEL="Hide Header on Home Page"
|
||||
TPL_MOKOONYX_HIDE_HEADER_HOME_DESC="Hide the site header (logo, branding) on the front page only."
|
||||
TPL_MOKOONYX_HIDE_MENU_HOME_LABEL="Hide Main Menu on Home Page"
|
||||
TPL_MOKOONYX_HIDE_MENU_HOME_DESC="Hide the main navigation menu on the front page only."
|
||||
TPL_MOKOONYX_BACKTOTOP="Back to Top"
|
||||
TPL_MOKOONYX_TOC_TITLE="Table of Contents"
|
||||
TPL_MOKOONYX_BACKTOTOP_LABEL="Back-to-top Link"
|
||||
|
||||
@@ -10,7 +10,17 @@
|
||||
* INGROUP: MokoOnyx.Accessibility
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
|
||||
* PATH: ./media/css/a11y-high-contrast.css
|
||||
* VERSION: 02.09.03
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
* VERSION: 02.17.00
|
||||
=======
|
||||
* VERSION: 02.17.00
|
||||
=======
|
||||
* VERSION: 02.17.00
|
||||
=======
|
||||
* VERSION: 02.17.00
|
||||
>>>>>>> origin/main
|
||||
>>>>>>> origin/main
|
||||
* BRIEF: High-contrast stylesheet for accessibility toolbar
|
||||
*/
|
||||
|
||||
|
||||
@@ -23514,4 +23514,18 @@ font-size: 0.8125rem;
|
||||
.fa-regular {
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
/* pipeline test */
|
||||
.blog-item .item-image {
|
||||
height: 250px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.blog-item .item-image img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.fa-brands {
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
/* patch release test */
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 168 KiB |
+14
-2
@@ -35,8 +35,12 @@
|
||||
https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/raw/branch/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
<name>Template - MokoOnyx</name>
|
||||
<version>02.09.03-dev</version>
|
||||
<name>mokoonyx</name>
|
||||
<<<<<<< HEAD
|
||||
<version>02.17.00-rc</version>
|
||||
=======
|
||||
<version>02.17.00-rc</version>
|
||||
>>>>>>> origin/main
|
||||
<scriptfile>script.php</scriptfile>
|
||||
<creationDate>2026-05-16</creationDate>
|
||||
<author>Jonathan Miller || Moko Consulting</author>
|
||||
@@ -238,6 +242,14 @@
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
<field name="hideHeaderHome" type="radio" label="TPL_MOKOONYX_HIDE_HEADER_HOME_LABEL" description="TPL_MOKOONYX_HIDE_HEADER_HOME_DESC" layout="joomla.form.field.radio.switcher" default="0" filter="integer">
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
<field name="hideMenuHome" type="radio" label="TPL_MOKOONYX_HIDE_MENU_HOME_LABEL" description="TPL_MOKOONYX_HIDE_MENU_HOME_DESC" layout="joomla.form.field.radio.switcher" default="0" filter="integer">
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
|
||||
<!-- Accessibility -->
|
||||
<field name="theme_sep_a11y" type="spacer" label="Accessibility" hr="false" class="text fw-bold" />
|
||||
|
||||
+50
-46
@@ -1,104 +1,108 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
VERSION: 02.09.03
|
||||
VERSION: 02.17.00
|
||||
-->
|
||||
|
||||
<updates>
|
||||
<update>
|
||||
<name>Template - MokoOnyx</name>
|
||||
<description>Template - MokoOnyx update</description>
|
||||
<description>Template - MokoOnyx dev build.</description>
|
||||
<element>mokoonyx</element>
|
||||
<type>template</type>
|
||||
<version>02.09.02</version>
|
||||
<client>site</client>
|
||||
<version>02.16.00-dev</version>
|
||||
<creationDate>2026-05-30</creationDate>
|
||||
<infourl title="Template - MokoOnyx">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/development</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/development/tpl_mokoonyx-02.16.00-dev.zip</downloadurl>
|
||||
</downloads>
|
||||
<sha256>f8eb73b0a0b61a9f37ee5b720182374cb0b2495fda5e1198711d1298ef5bbd67</sha256>
|
||||
<tags><tag>dev</tag></tags>
|
||||
<infourl title="Template - MokoOnyx">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/stable</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/stable/tpl_mokoonyx-02.09.02.zip</downloadurl>
|
||||
</downloads>
|
||||
<sha256>6dc580dd57c94d5cd276544dabdbe472717089e99217a2634f04b5c9a4f395b8</sha256>
|
||||
<changelogurl>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/raw/branch/main/CHANGELOG.md</changelogurl>
|
||||
<php_minimum>8.1.0</php_minimum>
|
||||
<targetplatform name="joomla" version="(5|6)\..*" />
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
<targetplatform name="joomla" version="(5|6)\..*"/>
|
||||
<php_minimum>8.1.0</php_minimum>
|
||||
</update>
|
||||
<update>
|
||||
<name>Template - MokoOnyx</name>
|
||||
<description>Template - MokoOnyx update</description>
|
||||
<description>Template - MokoOnyx alpha build.</description>
|
||||
<element>mokoonyx</element>
|
||||
<type>template</type>
|
||||
<version>02.09.02</version>
|
||||
<client>site</client>
|
||||
<version>02.16.00-alpha</version>
|
||||
<creationDate>2026-05-30</creationDate>
|
||||
<infourl title="Template - MokoOnyx">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/alpha</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/alpha/tpl_mokoonyx-02.16.00-alpha.zip</downloadurl>
|
||||
</downloads>
|
||||
<sha256>f8eb73b0a0b61a9f37ee5b720182374cb0b2495fda5e1198711d1298ef5bbd67</sha256>
|
||||
<tags><tag>alpha</tag></tags>
|
||||
<infourl title="Template - MokoOnyx">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/stable</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/stable/tpl_mokoonyx-02.09.02.zip</downloadurl>
|
||||
</downloads>
|
||||
<sha256>6dc580dd57c94d5cd276544dabdbe472717089e99217a2634f04b5c9a4f395b8</sha256>
|
||||
<changelogurl>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/raw/branch/main/CHANGELOG.md</changelogurl>
|
||||
<php_minimum>8.1.0</php_minimum>
|
||||
<targetplatform name="joomla" version="(5|6)\..*" />
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
<targetplatform name="joomla" version="(5|6)\..*"/>
|
||||
<php_minimum>8.1.0</php_minimum>
|
||||
</update>
|
||||
<update>
|
||||
<name>Template - MokoOnyx</name>
|
||||
<description>Template - MokoOnyx update</description>
|
||||
<description>Template - MokoOnyx beta build.</description>
|
||||
<element>mokoonyx</element>
|
||||
<type>template</type>
|
||||
<version>02.09.02</version>
|
||||
<client>site</client>
|
||||
<version>02.16.00-beta</version>
|
||||
<creationDate>2026-05-30</creationDate>
|
||||
<infourl title="Template - MokoOnyx">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/beta</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/beta/tpl_mokoonyx-02.16.00-beta.zip</downloadurl>
|
||||
</downloads>
|
||||
<sha256>f8eb73b0a0b61a9f37ee5b720182374cb0b2495fda5e1198711d1298ef5bbd67</sha256>
|
||||
<tags><tag>beta</tag></tags>
|
||||
<infourl title="Template - MokoOnyx">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/stable</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/stable/tpl_mokoonyx-02.09.02.zip</downloadurl>
|
||||
</downloads>
|
||||
<sha256>6dc580dd57c94d5cd276544dabdbe472717089e99217a2634f04b5c9a4f395b8</sha256>
|
||||
<changelogurl>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/raw/branch/main/CHANGELOG.md</changelogurl>
|
||||
<php_minimum>8.1.0</php_minimum>
|
||||
<targetplatform name="joomla" version="(5|6)\..*" />
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
<targetplatform name="joomla" version="(5|6)\..*"/>
|
||||
<php_minimum>8.1.0</php_minimum>
|
||||
</update>
|
||||
<update>
|
||||
<name>Template - MokoOnyx</name>
|
||||
<description>Template - MokoOnyx update</description>
|
||||
<description>Template - MokoOnyx rc build.</description>
|
||||
<element>mokoonyx</element>
|
||||
<type>template</type>
|
||||
<version>02.09.02</version>
|
||||
<client>site</client>
|
||||
<version>02.16.00-rc</version>
|
||||
<creationDate>2026-05-30</creationDate>
|
||||
<infourl title="Template - MokoOnyx">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/release-candidate</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/release-candidate/tpl_mokoonyx-02.16.00-rc.zip</downloadurl>
|
||||
</downloads>
|
||||
<sha256>f8eb73b0a0b61a9f37ee5b720182374cb0b2495fda5e1198711d1298ef5bbd67</sha256>
|
||||
<tags><tag>rc</tag></tags>
|
||||
<infourl title="Template - MokoOnyx">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/stable</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/stable/tpl_mokoonyx-02.09.02.zip</downloadurl>
|
||||
</downloads>
|
||||
<sha256>6dc580dd57c94d5cd276544dabdbe472717089e99217a2634f04b5c9a4f395b8</sha256>
|
||||
<changelogurl>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/raw/branch/main/CHANGELOG.md</changelogurl>
|
||||
<php_minimum>8.1.0</php_minimum>
|
||||
<targetplatform name="joomla" version="(5|6)\..*" />
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
<targetplatform name="joomla" version="(5|6)\..*"/>
|
||||
<php_minimum>8.1.0</php_minimum>
|
||||
</update>
|
||||
<update>
|
||||
<name>Template - MokoOnyx</name>
|
||||
<description>Template - MokoOnyx update</description>
|
||||
<description>Template - MokoOnyx stable build.</description>
|
||||
<element>mokoonyx</element>
|
||||
<type>template</type>
|
||||
<version>02.09.02</version>
|
||||
<client>site</client>
|
||||
<tags><tag>stable</tag></tags>
|
||||
<infourl title="Template - MokoOnyx">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/stable</infourl>
|
||||
<version>02.16.00</version>
|
||||
<creationDate>2026-05-30</creationDate>
|
||||
<infourl title='Template - MokoOnyx'>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/stable</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/stable/tpl_mokoonyx-02.09.02.zip</downloadurl>
|
||||
<downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/stable/tpl_mokoonyx-02.16.00.zip</downloadurl>
|
||||
</downloads>
|
||||
<sha256>6dc580dd57c94d5cd276544dabdbe472717089e99217a2634f04b5c9a4f395b8</sha256>
|
||||
<sha256>f8eb73b0a0b61a9f37ee5b720182374cb0b2495fda5e1198711d1298ef5bbd67</sha256>
|
||||
<tags><tag>stable</tag></tags>
|
||||
<changelogurl>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/raw/branch/main/CHANGELOG.md</changelogurl>
|
||||
<php_minimum>8.1.0</php_minimum>
|
||||
<targetplatform name="joomla" version="(5|6)\..*" />
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
<targetplatform name="joomla" version="(5|6)\..*" />
|
||||
<php_minimum>8.1.0</php_minimum>
|
||||
</update>
|
||||
</updates>
|
||||
|
||||
|
||||
@@ -286,3 +286,4 @@ vendor/bin/codecept run
|
||||
| Revision | Date | Author | Description |
|
||||
|---|---|---|---|
|
||||
| 1.0 | 2026-05-09 | Moko Consulting | Initial version |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user