Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3b2fe37ce1 | |||
| 9a356cdd04 | |||
| 69ff510bac |
@@ -1,73 +0,0 @@
|
|||||||
# 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
|
|
||||||
# VERSION: 01.00.00
|
|
||||||
# BRIEF: Auto-create feature branch when an issue is opened
|
|
||||||
|
|
||||||
name: "Universal: Issue Branch"
|
|
||||||
|
|
||||||
on:
|
|
||||||
issues:
|
|
||||||
types: [opened]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
issues: write
|
|
||||||
|
|
||||||
env:
|
|
||||||
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
create-branch:
|
|
||||||
name: Create feature branch
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Create branch and comment
|
|
||||||
run: |
|
|
||||||
TOKEN="${{ secrets.GA_TOKEN }}"
|
|
||||||
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
|
|
||||||
ISSUE_NUM="${{ github.event.issue.number }}"
|
|
||||||
ISSUE_TITLE="${{ github.event.issue.title }}"
|
|
||||||
|
|
||||||
# Build slug from title: lowercase, replace non-alnum with dash, trim
|
|
||||||
SLUG=$(echo "${ISSUE_TITLE}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//' | cut -c1-40)
|
|
||||||
BRANCH="feature/${ISSUE_NUM}-${SLUG}"
|
|
||||||
|
|
||||||
# Check dev branch exists
|
|
||||||
DEV_EXISTS=$(curl -sf -o /dev/null -w '%{http_code}' \
|
|
||||||
-H "Authorization: token ${TOKEN}" \
|
|
||||||
"${API}/branches/dev" 2>/dev/null || echo "000")
|
|
||||||
|
|
||||||
if [ "${DEV_EXISTS}" != "200" ]; then
|
|
||||||
echo "No dev branch -- skipping"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create branch from dev
|
|
||||||
HTTP=$(curl -sf -o /dev/null -w '%{http_code}' -X POST \
|
|
||||||
-H "Authorization: token ${TOKEN}" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
"${API}/branches" \
|
|
||||||
-d "{\"new_branch_name\":\"${BRANCH}\",\"old_branch_name\":\"dev\"}" 2>/dev/null || echo "000")
|
|
||||||
|
|
||||||
if [ "${HTTP}" = "201" ]; then
|
|
||||||
echo "Created branch: ${BRANCH}"
|
|
||||||
|
|
||||||
# Comment on issue with branch link
|
|
||||||
REPO_URL="${GITEA_URL}/${{ github.repository }}"
|
|
||||||
BODY="Branch created: [\`${BRANCH}\`](${REPO_URL}/src/branch/${BRANCH})\n\n\`\`\`bash\ngit fetch origin\ngit checkout ${BRANCH}\n\`\`\`"
|
|
||||||
|
|
||||||
curl -sf -X POST \
|
|
||||||
-H "Authorization: token ${TOKEN}" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
"${API}/issues/${ISSUE_NUM}/comments" \
|
|
||||||
-d "{\"body\":\"${BODY}\"}" > /dev/null 2>&1
|
|
||||||
|
|
||||||
echo "Commented on issue #${ISSUE_NUM}"
|
|
||||||
else
|
|
||||||
echo "Failed to create branch (HTTP ${HTTP}) -- may already exist"
|
|
||||||
fi
|
|
||||||
@@ -7,8 +7,8 @@
|
|||||||
# INGROUP: moko-platform.Release
|
# INGROUP: moko-platform.Release
|
||||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
|
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
|
||||||
# PATH: /templates/workflows/universal/pre-release.yml.template
|
# PATH: /templates/workflows/universal/pre-release.yml.template
|
||||||
# VERSION: 05.01.00
|
# VERSION: 05.00.00
|
||||||
# BRIEF: Manual pre-release -- builds dev/alpha/beta/rc packages from any branch
|
# BRIEF: Manual pre-release — builds dev/alpha/beta/rc packages from any branch
|
||||||
|
|
||||||
name: "Universal: Pre-Release"
|
name: "Universal: Pre-Release"
|
||||||
|
|
||||||
@@ -45,46 +45,30 @@ jobs:
|
|||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
token: ${{ secrets.GA_TOKEN }}
|
token: ${{ secrets.GA_TOKEN }}
|
||||||
|
|
||||||
- name: Setup tools
|
- name: Setup PHP
|
||||||
run: |
|
run: |
|
||||||
# Update moko-platform CLI tools if available; install PHP if missing
|
if ! command -v php &> /dev/null; then
|
||||||
if command -v moko-platform-update &> /dev/null; then
|
sudo apt-get update -qq
|
||||||
moko-platform-update
|
sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl >/dev/null 2>&1
|
||||||
elif [ -d "/opt/moko-platform" ]; then
|
|
||||||
cd /opt/moko-platform && git pull origin main --quiet 2>/dev/null || true
|
|
||||||
else
|
|
||||||
if ! command -v php &> /dev/null; then
|
|
||||||
sudo apt-get update -qq
|
|
||||||
sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl >/dev/null 2>&1
|
|
||||||
fi
|
|
||||||
git clone --depth 1 --branch main --quiet \
|
|
||||||
"https://x-access-token:${{ secrets.GA_TOKEN }}@git.mokoconsulting.tech/MokoConsulting/moko-platform.git" \
|
|
||||||
/tmp/moko-platform-api
|
|
||||||
fi
|
|
||||||
# Set MOKO_CLI to whichever path exists
|
|
||||||
if [ -d "/opt/moko-platform/cli" ]; then
|
|
||||||
echo "MOKO_CLI=/opt/moko-platform/cli" >> "$GITHUB_ENV"
|
|
||||||
else
|
|
||||||
echo "MOKO_CLI=/tmp/moko-platform-api/cli" >> "$GITHUB_ENV"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
- name: Setup moko-platform tools
|
||||||
|
env:
|
||||||
|
MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN }}
|
||||||
|
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||||
|
run: |
|
||||||
|
git clone --depth 1 --branch main --quiet "https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git" /tmp/moko-platform-api
|
||||||
|
|
||||||
- name: Detect platform
|
- name: Detect platform
|
||||||
id: platform
|
id: platform
|
||||||
run: |
|
run: |
|
||||||
PLATFORM=$(sed -n 's/.*<platform>\([^<]*\)<\/platform>.*/\1/p' .mokogitea/manifest.xml 2>/dev/null | head -1 | tr -d '[:space:]')
|
php /tmp/moko-platform-api/cli/manifest_read.php --path . --github-output
|
||||||
[ -z "$PLATFORM" ] && PLATFORM="generic"
|
|
||||||
echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT"
|
|
||||||
MANIFEST=$(find ./src -maxdepth 1 -name "pkg_*.xml" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
|
|
||||||
[ -z "$MANIFEST" ] && MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" ! -path "*/packages/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
|
|
||||||
[ -z "$MANIFEST" ] && MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
|
|
||||||
MOD_FILE=$(find . -maxdepth 4 -name "mod*.class.php" ! -path "./.git/*" -exec grep -l 'extends DolibarrModules' {} \; 2>/dev/null | head -1)
|
|
||||||
echo "manifest=${MANIFEST}" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "mod_file=${MOD_FILE}" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
- name: Resolve metadata and bump version
|
- name: Resolve metadata
|
||||||
id: meta
|
id: meta
|
||||||
run: |
|
run: |
|
||||||
STABILITY="${{ inputs.stability }}"
|
STABILITY="${{ inputs.stability }}"
|
||||||
|
MOKO_API="/tmp/moko-platform-api/cli"
|
||||||
|
|
||||||
case "$STABILITY" in
|
case "$STABILITY" in
|
||||||
development) SUFFIX="-dev"; TAG="development" ;;
|
development) SUFFIX="-dev"; TAG="development" ;;
|
||||||
@@ -93,58 +77,32 @@ jobs:
|
|||||||
release-candidate) SUFFIX="-rc"; TAG="release-candidate" ;;
|
release-candidate) SUFFIX="-rc"; TAG="release-candidate" ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Patch bump via CLI tool
|
# Read current version from manifest (priority) or README — no bump yet
|
||||||
php ${MOKO_CLI}/version_bump.php --path .
|
VERSION=$(php ${MOKO_API}/version_read.php --path .)
|
||||||
VERSION=$(php ${MOKO_CLI}/version_read.php --path . 2>/dev/null)
|
echo "Version: ${VERSION}"
|
||||||
[ -z "$VERSION" ] && VERSION="00.00.01"
|
|
||||||
TODAY=$(date +%Y-%m-%d)
|
|
||||||
|
|
||||||
# Update platform-specific manifest
|
# Ensure platform-specific manifest matches
|
||||||
PLATFORM="${{ steps.platform.outputs.platform }}"
|
php ${MOKO_API}/version_set_platform.php --path . --version "${VERSION}"
|
||||||
MANIFEST="${{ steps.platform.outputs.manifest }}"
|
|
||||||
MOD_FILE="${{ steps.platform.outputs.mod_file }}"
|
|
||||||
|
|
||||||
php ${MOKO_CLI}/version_set_platform.php \
|
# Git setup for later commits
|
||||||
--path . --version "$VERSION" --branch "${{ github.ref_name }}" 2>/dev/null || true
|
|
||||||
|
|
||||||
# Commit version bump
|
|
||||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
||||||
git config --local user.name "gitea-actions[bot]"
|
git config --local user.name "gitea-actions[bot]"
|
||||||
git remote set-url origin "https://jmiller:${{ secrets.GA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
git remote set-url origin "https://jmiller:${{ secrets.GA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
||||||
git add -A
|
|
||||||
git diff --cached --quiet || {
|
|
||||||
git commit -m "chore(version): pre-release bump to ${VERSION} [skip ci]"
|
|
||||||
git push origin HEAD 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Auto-detect element (platform-aware)
|
# Detect element from Joomla/Dolibarr manifest
|
||||||
EXT_ELEMENT=""
|
set +o pipefail
|
||||||
case "$PLATFORM" in
|
PLATFORM="${{ steps.platform.outputs.platform }}"
|
||||||
joomla)
|
EXT_ELEMENT=$(php ${MOKO_API}/manifest_read.php --path . --field name 2>/dev/null | tr -d ' ' | tr '[:upper:]' '[:lower:]' || true)
|
||||||
if [ -n "$MANIFEST" ]; then
|
# For Joomla, prefer <element> tag
|
||||||
EXT_ELEMENT=$(sed -n 's/.*<element>\([^<]*\)<\/element>.*/\1/p' "$MANIFEST" 2>/dev/null | head -1)
|
if [ "$PLATFORM" = "joomla" ]; then
|
||||||
if [ -z "$EXT_ELEMENT" ]; then
|
MANIFEST=$(find . -maxdepth 4 -name "*.xml" ! -path "./.git/*" -print0 2>/dev/null | xargs -0 grep -l '<extension' 2>/dev/null | head -1 || true)
|
||||||
EXT_ELEMENT=$(basename "$MANIFEST" .xml | tr '[:upper:]' '[:lower:]')
|
if [ -n "$MANIFEST" ]; then
|
||||||
case "$EXT_ELEMENT" in
|
ELEM=$(grep -oP "<element>\K[^<]+" "$MANIFEST" 2>/dev/null | head -1 || true)
|
||||||
templatedetails|manifest) EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -') ;;
|
[ -n "$ELEM" ] && EXT_ELEMENT="$ELEM"
|
||||||
esac
|
fi
|
||||||
fi
|
fi
|
||||||
else
|
[ -z "$EXT_ELEMENT" ] && EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
|
||||||
EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
|
set -o pipefail
|
||||||
fi
|
|
||||||
;;
|
|
||||||
dolibarr)
|
|
||||||
if [ -n "$MOD_FILE" ]; then
|
|
||||||
MOD_BASENAME=$(basename "$MOD_FILE" .class.php)
|
|
||||||
EXT_ELEMENT=$(echo "$MOD_BASENAME" | sed 's/^mod//' | tr '[:upper:]' '[:lower:]')
|
|
||||||
else
|
|
||||||
EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
ZIP_NAME="${EXT_ELEMENT}-${VERSION}${SUFFIX}.zip"
|
ZIP_NAME="${EXT_ELEMENT}-${VERSION}${SUFFIX}.zip"
|
||||||
|
|
||||||
@@ -154,76 +112,42 @@ jobs:
|
|||||||
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
|
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
|
||||||
echo "zip_name=${ZIP_NAME}" >> "$GITHUB_OUTPUT"
|
echo "zip_name=${ZIP_NAME}" >> "$GITHUB_OUTPUT"
|
||||||
echo "ext_element=${EXT_ELEMENT}" >> "$GITHUB_OUTPUT"
|
echo "ext_element=${EXT_ELEMENT}" >> "$GITHUB_OUTPUT"
|
||||||
echo "manifest=${MANIFEST}" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
echo "=== Pre-Release: ${EXT_ELEMENT} ${VERSION}${SUFFIX} ==="
|
echo "=== Pre-Release: ${EXT_ELEMENT} ${VERSION}${SUFFIX} ==="
|
||||||
|
|
||||||
- name: Build package
|
- name: Build package
|
||||||
run: |
|
|
||||||
SOURCE_DIR="src"
|
|
||||||
[ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs"
|
|
||||||
if [ ! -d "$SOURCE_DIR" ]; then
|
|
||||||
echo "::error::No src/ or htdocs/ directory"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
MANIFEST="${{ steps.meta.outputs.manifest }}"
|
|
||||||
EXT_TYPE=""
|
|
||||||
if [ -n "$MANIFEST" ]; then
|
|
||||||
EXT_TYPE=$(sed -n 's/.*<extension[^>]*type="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
|
|
||||||
fi
|
|
||||||
|
|
||||||
EXCLUDES="sftp-config* .ftpignore *.ppk *.pem *.key .env* *.local .build-trigger"
|
|
||||||
|
|
||||||
mkdir -p build/package
|
|
||||||
|
|
||||||
if [ "$EXT_TYPE" = "package" ] && [ -d "${SOURCE_DIR}/packages" ]; then
|
|
||||||
echo "=== Building Joomla PACKAGE (multi-extension) ==="
|
|
||||||
for ext_dir in "${SOURCE_DIR}"/packages/*/; do
|
|
||||||
[ ! -d "$ext_dir" ] && continue
|
|
||||||
EXT_NAME=$(basename "$ext_dir")
|
|
||||||
echo " Packaging sub-extension: ${EXT_NAME}"
|
|
||||||
cd "$ext_dir"
|
|
||||||
zip -r "../../build/package/${EXT_NAME}.zip" . -x $EXCLUDES
|
|
||||||
cd "$OLDPWD"
|
|
||||||
done
|
|
||||||
for f in "${SOURCE_DIR}"/*.xml "${SOURCE_DIR}"/*.php; do
|
|
||||||
[ -f "$f" ] && cp "$f" build/package/
|
|
||||||
done
|
|
||||||
else
|
|
||||||
echo "=== Building standard extension ==="
|
|
||||||
rsync -a \
|
|
||||||
--exclude='sftp-config*' \
|
|
||||||
--exclude='.ftpignore' \
|
|
||||||
--exclude='*.ppk' \
|
|
||||||
--exclude='*.pem' \
|
|
||||||
--exclude='*.key' \
|
|
||||||
--exclude='.env*' \
|
|
||||||
--exclude='*.local' \
|
|
||||||
--exclude='.build-trigger' \
|
|
||||||
"${SOURCE_DIR}/" build/package/
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Create ZIP
|
|
||||||
id: zip
|
id: zip
|
||||||
run: |
|
run: |
|
||||||
ZIP_NAME="${{ steps.meta.outputs.zip_name }}"
|
VERSION="${{ steps.meta.outputs.version }}"
|
||||||
cd build/package
|
SUFFIX="${{ steps.meta.outputs.suffix }}"
|
||||||
zip -r "../${ZIP_NAME}" .
|
PLATFORM="${{ steps.platform.outputs.platform }}"
|
||||||
cd ..
|
|
||||||
|
|
||||||
SHA256=$(sha256sum "${ZIP_NAME}" | cut -d' ' -f1)
|
if [ "$PLATFORM" = "joomla" ]; then
|
||||||
echo "sha256=${SHA256}" >> "$GITHUB_OUTPUT"
|
php /tmp/moko-platform-api/cli/joomla_build.php --path . --version "${VERSION}" --suffix "${SUFFIX}" --output build --github-output
|
||||||
echo "ZIP: ${ZIP_NAME} (SHA: ${SHA256:0:16}...)"
|
else
|
||||||
|
# Generic build: zip src/ directory
|
||||||
|
SOURCE_DIR="src"
|
||||||
|
[ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs"
|
||||||
|
[ ! -d "$SOURCE_DIR" ] && { echo "::error::No src/ or htdocs/"; exit 1; }
|
||||||
|
EXT_ELEMENT="${{ steps.meta.outputs.ext_element }}"
|
||||||
|
ZIP_NAME="${EXT_ELEMENT}-${VERSION}${SUFFIX}.zip"
|
||||||
|
mkdir -p build
|
||||||
|
cd "$SOURCE_DIR" && zip -r "../build/${ZIP_NAME}" . && cd ..
|
||||||
|
SHA256=$(sha256sum "build/${ZIP_NAME}" | cut -d' ' -f1)
|
||||||
|
echo "zip_name=${ZIP_NAME}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "zip_path=build/${ZIP_NAME}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "sha256=${SHA256}" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Create or replace Gitea release
|
- name: Create or replace Gitea release
|
||||||
id: release
|
id: release
|
||||||
|
continue-on-error: true
|
||||||
run: |
|
run: |
|
||||||
TAG="${{ steps.meta.outputs.tag }}"
|
TAG="${{ steps.meta.outputs.tag }}"
|
||||||
VERSION="${{ steps.meta.outputs.version }}"
|
VERSION="${{ steps.meta.outputs.version }}"
|
||||||
STABILITY="${{ steps.meta.outputs.stability }}"
|
STABILITY="${{ steps.meta.outputs.stability }}"
|
||||||
SHA256="${{ steps.zip.outputs.sha256 }}"
|
SHA256="${{ steps.zip.outputs.sha256 }}"
|
||||||
ZIP_NAME="${{ steps.meta.outputs.zip_name }}"
|
ZIP_NAME="${{ steps.zip.outputs.zip_name }}"
|
||||||
EXT_ELEMENT="${{ steps.meta.outputs.ext_element }}"
|
EXT_ELEMENT="${{ steps.meta.outputs.ext_element }}"
|
||||||
TOKEN="${{ secrets.GA_TOKEN }}"
|
TOKEN="${{ secrets.GA_TOKEN }}"
|
||||||
API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||||
@@ -261,115 +185,76 @@ jobs:
|
|||||||
curl -sS -X POST -H "Authorization: token ${TOKEN}" \
|
curl -sS -X POST -H "Authorization: token ${TOKEN}" \
|
||||||
-H "Content-Type: application/octet-stream" \
|
-H "Content-Type: application/octet-stream" \
|
||||||
"${API}/releases/${RELEASE_ID}/assets?name=${ZIP_NAME}" \
|
"${API}/releases/${RELEASE_ID}/assets?name=${ZIP_NAME}" \
|
||||||
--data-binary "@build/${ZIP_NAME}"
|
--data-binary "@${{ steps.zip.outputs.zip_path }}"
|
||||||
|
|
||||||
echo "Released: ${EXT_ELEMENT} ${VERSION} (${STABILITY})"
|
echo "Released: ${EXT_ELEMENT} ${VERSION} (${STABILITY})"
|
||||||
|
|
||||||
- name: Update updates.xml
|
- name: "Update updates.xml"
|
||||||
if: steps.platform.outputs.platform == 'joomla'
|
if: steps.platform.outputs.platform == 'joomla'
|
||||||
run: |
|
run: |
|
||||||
STABILITY="${{ steps.meta.outputs.stability }}"
|
|
||||||
VERSION="${{ steps.meta.outputs.version }}"
|
VERSION="${{ steps.meta.outputs.version }}"
|
||||||
|
STABILITY="${{ steps.meta.outputs.stability }}"
|
||||||
SHA256="${{ steps.zip.outputs.sha256 }}"
|
SHA256="${{ steps.zip.outputs.sha256 }}"
|
||||||
ZIP_NAME="${{ steps.meta.outputs.zip_name }}"
|
php /tmp/moko-platform-api/cli/updates_xml_build.php --path . --version "$VERSION" --stability "$STABILITY" --sha "$SHA256" --gitea-url "$GITEA_URL" --org "$GITEA_ORG" --repo "$GITEA_REPO"
|
||||||
TAG="${{ steps.meta.outputs.tag }}"
|
|
||||||
|
|
||||||
if [ ! -f "updates.xml" ]; then
|
|
||||||
echo "No updates.xml -- skipping"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Map stability to XML tag name
|
|
||||||
case "$STABILITY" in
|
|
||||||
development) XML_TAG="development" ;;
|
|
||||||
alpha) XML_TAG="alpha" ;;
|
|
||||||
beta) XML_TAG="beta" ;;
|
|
||||||
release-candidate) XML_TAG="rc" ;;
|
|
||||||
*) XML_TAG="$STABILITY" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
DOWNLOAD_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${TAG}/${ZIP_NAME}"
|
|
||||||
|
|
||||||
# Use PHP to update the channel in updates.xml
|
|
||||||
php -r '
|
|
||||||
$xml_tag = $argv[1];
|
|
||||||
$version = $argv[2];
|
|
||||||
$sha256 = $argv[3];
|
|
||||||
$url = $argv[4];
|
|
||||||
$date = date("Y-m-d");
|
|
||||||
|
|
||||||
$content = file_get_contents("updates.xml");
|
|
||||||
$pattern = "/(<update>(?:(?!<\/update>).)*?<tag>" . preg_quote($xml_tag) . "<\/tag>.*?<\/update>)/s";
|
|
||||||
|
|
||||||
$content = preg_replace_callback($pattern, function($m) use ($version, $sha256, $url, $date) {
|
|
||||||
$block = $m[0];
|
|
||||||
$block = preg_replace("/<version>[^<]*<\/version>/", "<version>{$version}</version>", $block);
|
|
||||||
if (strpos($block, "<sha256>") !== false) {
|
|
||||||
$block = preg_replace("/<sha256>[^<]*<\/sha256>/", "<sha256>{$sha256}</sha256>", $block);
|
|
||||||
} else {
|
|
||||||
$block = str_replace("</downloads>", "</downloads>\n <sha256>{$sha256}</sha256>", $block);
|
|
||||||
}
|
|
||||||
$block = preg_replace("/(<downloadurl[^>]*>)[^<]*(<\/downloadurl>)/", "\${1}{$url}\${2}", $block);
|
|
||||||
return $block;
|
|
||||||
}, $content);
|
|
||||||
|
|
||||||
file_put_contents("updates.xml", $content);
|
|
||||||
echo "Updated {$xml_tag} channel: version={$version}\n";
|
|
||||||
' "$XML_TAG" "$VERSION" "$SHA256" "$DOWNLOAD_URL"
|
|
||||||
|
|
||||||
# Commit and push
|
|
||||||
if ! git diff --quiet updates.xml 2>/dev/null; then
|
if ! git diff --quiet updates.xml 2>/dev/null; then
|
||||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
||||||
git config --local user.name "gitea-actions[bot]"
|
git config --local user.name "gitea-actions[bot]"
|
||||||
git add updates.xml
|
git add updates.xml
|
||||||
git commit -m "chore: update ${STABILITY} channel ${VERSION} [skip ci]"
|
git commit -m "chore: update $STABILITY channel $VERSION [skip ci]"
|
||||||
git push origin HEAD 2>&1 || echo "WARNING: push failed"
|
git push origin HEAD 2>&1 || echo "WARNING: push failed"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: "Sync updates.xml to all branches"
|
- name: "Sync updates.xml to all branches"
|
||||||
if: steps.platform.outputs.platform == 'joomla'
|
if: steps.platform.outputs.platform == 'joomla'
|
||||||
run: |
|
run: |
|
||||||
CURRENT_BRANCH="${{ github.ref_name }}"
|
php /tmp/moko-platform-api/cli/updates_xml_sync.php --path . --current "${{ github.ref_name }}" --branches main,dev --version "${{ steps.meta.outputs.version }}" --token "${{ secrets.GA_TOKEN }}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}" --gitea-url "${GITEA_URL}"
|
||||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
|
||||||
git config --local user.name "gitea-actions[bot]"
|
|
||||||
|
|
||||||
for BRANCH in main dev; do
|
|
||||||
[ "$BRANCH" = "$CURRENT_BRANCH" ] && continue
|
|
||||||
echo "Syncing updates.xml -> ${BRANCH}"
|
|
||||||
git fetch origin "${BRANCH}" 2>/dev/null || continue
|
|
||||||
git checkout "origin/${BRANCH}" -- . 2>/dev/null || continue
|
|
||||||
git checkout "${CURRENT_BRANCH}" -- updates.xml
|
|
||||||
if ! git diff --quiet updates.xml 2>/dev/null; then
|
|
||||||
git add updates.xml
|
|
||||||
git commit -m "chore: sync updates.xml from ${CURRENT_BRANCH} [skip ci]"
|
|
||||||
git push origin HEAD:refs/heads/${BRANCH} 2>&1 || echo "WARNING: push to ${BRANCH} failed"
|
|
||||||
fi
|
|
||||||
git checkout "${CURRENT_BRANCH}" 2>/dev/null
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: "Delete lesser pre-release channels (cascade)"
|
- name: "Delete lesser pre-release channels (cascade)"
|
||||||
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.GA_TOKEN }}"
|
TOKEN="${{ secrets.GA_TOKEN }}"
|
||||||
|
|
||||||
php ${MOKO_CLI}/release_cascade.php \
|
|
||||||
--stability "${{ steps.meta.outputs.stability }}" \
|
|
||||||
--token "${TOKEN}" \
|
|
||||||
--api-base "${API_BASE}"
|
|
||||||
|
|
||||||
- name: Summary
|
|
||||||
if: always()
|
|
||||||
run: |
|
|
||||||
VERSION="${{ steps.meta.outputs.version }}"
|
|
||||||
STABILITY="${{ steps.meta.outputs.stability }}"
|
STABILITY="${{ steps.meta.outputs.stability }}"
|
||||||
ZIP_NAME="${{ steps.meta.outputs.zip_name }}"
|
|
||||||
SHA256="${{ steps.zip.outputs.sha256 }}"
|
# Cascade: rc → beta,alpha,dev | beta → alpha,dev | alpha → dev | dev → nothing
|
||||||
echo "## Pre-Release Complete" >> $GITHUB_STEP_SUMMARY
|
case "$STABILITY" in
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
release-candidate) TAGS_TO_DELETE="beta alpha development" ;;
|
||||||
echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
|
beta) TAGS_TO_DELETE="alpha development" ;;
|
||||||
echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY
|
alpha) TAGS_TO_DELETE="development" ;;
|
||||||
echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
|
*) TAGS_TO_DELETE="" ;;
|
||||||
echo "| Channel | ${STABILITY} |" >> $GITHUB_STEP_SUMMARY
|
esac
|
||||||
echo "| Package | \`${ZIP_NAME}\` |" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "| SHA-256 | \`${SHA256:-n/a}\` |" >> $GITHUB_STEP_SUMMARY
|
[ -z "$TAGS_TO_DELETE" ] && exit 0
|
||||||
|
|
||||||
|
for TAG in $TAGS_TO_DELETE; do
|
||||||
|
RELEASE_ID=$(curl -sS -H "Authorization: token ${TOKEN}" \
|
||||||
|
"${API_BASE}/releases/tags/${TAG}" 2>/dev/null | \
|
||||||
|
python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
|
||||||
|
|
||||||
|
if [ -n "$RELEASE_ID" ] && [ "$RELEASE_ID" != "None" ]; then
|
||||||
|
curl -sS -X DELETE -H "Authorization: token ${TOKEN}" \
|
||||||
|
"${API_BASE}/releases/${RELEASE_ID}" 2>/dev/null || true
|
||||||
|
curl -sS -X DELETE -H "Authorization: token ${TOKEN}" \
|
||||||
|
"${API_BASE}/tags/${TAG}" 2>/dev/null || true
|
||||||
|
echo "Deleted: ${TAG} (id: ${RELEASE_ID})"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: "Post-release version bump"
|
||||||
|
run: |
|
||||||
|
MOKO_API="/tmp/moko-platform-api/cli"
|
||||||
|
VERSION="${{ steps.meta.outputs.version }}"
|
||||||
|
|
||||||
|
# Bump patch for next dev cycle
|
||||||
|
BUMP_OUTPUT=$(php ${MOKO_API}/version_bump.php --path .)
|
||||||
|
NEXT=$(echo "$BUMP_OUTPUT" | grep -oP '\d{2}\.\d{2}\.\d{2}$' || true)
|
||||||
|
[ -z "$NEXT" ] && exit 0
|
||||||
|
|
||||||
|
# Update platform-specific manifest to next version
|
||||||
|
php ${MOKO_API}/version_set_platform.php --path . --version "${NEXT}"
|
||||||
|
|
||||||
|
git add -A
|
||||||
|
git diff --cached --quiet || {
|
||||||
|
git commit -m "chore: update development channel ${VERSION} [skip ci]"
|
||||||
|
git push origin HEAD 2>&1
|
||||||
|
}
|
||||||
|
|||||||
@@ -31,6 +31,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- License/subscription check
|
- License/subscription check
|
||||||
- System email template branding (DB approach)
|
- System email template branding (DB approach)
|
||||||
|
|
||||||
|
## [02.05.00] - 2026-05-24
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Joomla `protected=1` flag on all MokoWaaS extensions (framework-level disable/uninstall prevention)
|
||||||
|
- Self-healing protected flag — restored each admin session if cleared
|
||||||
|
- Block non-master disable via plugin list toggle (`plugins.publish`)
|
||||||
|
- Package script sets `protected=1, locked=0` on every install/update
|
||||||
|
- Legacy plugin entry in updates.xml for sites upgrading from standalone plugin
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- CI: auto-release workflow `pkg_pkg_` duplication in release names, ZIP filenames, and SHA256 paths
|
||||||
|
- CI: auto-release now strips existing type prefix and uses `<packagename>` for packages
|
||||||
|
- CI: `updates_xml_build` was cascading entries for all lower channels on stable release — now writes only current channel
|
||||||
|
- CI: `targetplatform` regex `((5.[0-9])|(6.[0-9]))` caused Gitea 500 on XML render — simplified to `(5|6)\..*`
|
||||||
|
- updates.xml stable entry now has correct `<tag>stable</tag>` and download URL
|
||||||
|
- README slimmed to overview, detailed content moved to wiki
|
||||||
|
|
||||||
## [02.03.10] - 2026-05-24
|
## [02.03.10] - 2026-05-24
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -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.05.00
|
VERSION: 02.04.00
|
||||||
PATH: /README.md
|
PATH: /README.md
|
||||||
BRIEF: MokoWaaS platform plugin for Joomla
|
BRIEF: MokoWaaS platform plugin for Joomla
|
||||||
-->
|
-->
|
||||||
|
|||||||
@@ -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.05.00</version>
|
<version>02.04.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.05.00</version>
|
<version>02.04.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.05.00</version>
|
<version>02.04.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>
|
||||||
|
|||||||
@@ -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.05.00</version>
|
<version>02.04.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>
|
||||||
|
|||||||
+59
-16
@@ -1,37 +1,80 @@
|
|||||||
<?xml version='1.0' encoding='UTF-8'?>
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
SPDX-License-Identifier: GPL-3.0-or-later
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
VERSION: 02.05.00
|
VERSION: 02.04.00
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<updates>
|
<updates>
|
||||||
<update>
|
<update>
|
||||||
<name>MokoWaaS</name>
|
<name>MokoWaaS</name>
|
||||||
<description>MokoWaaS stable update</description>
|
<description>MokoWaaS update</description>
|
||||||
<element>pkg_mokowaas</element>
|
<element>mokowaas</element>
|
||||||
<type>package</type>
|
<type>package</type>
|
||||||
<version>02.05.00</version>
|
<version>02.04.00-dev</version>
|
||||||
<tags><tag>stable</tag></tags>
|
<tags><tag>development</tag></tags>
|
||||||
<infourl title="MokoWaaS">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/v02</infourl>
|
<infourl title="MokoWaaS">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/development</infourl>
|
||||||
<downloads>
|
<downloads>
|
||||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/v02/pkg_mokowaas-02.05.00.zip</downloadurl>
|
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/development/pkg_mokowaas-02.04.00-dev.zip</downloadurl>
|
||||||
</downloads>
|
</downloads>
|
||||||
<targetplatform name="joomla" version="(5|6)\..*" />
|
<targetplatform name="joomla" version="(5|6)\..*" />
|
||||||
<maintainer>Moko Consulting</maintainer>
|
<maintainer>Moko Consulting</maintainer>
|
||||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||||
</update>
|
</update>
|
||||||
<update>
|
<update>
|
||||||
<name>System - MokoWaaS</name>
|
<name>MokoWaaS</name>
|
||||||
<description>MokoWaaS stable update (legacy plugin upgrade)</description>
|
<description>MokoWaaS update</description>
|
||||||
<element>mokowaas</element>
|
<element>mokowaas</element>
|
||||||
<type>plugin</type>
|
<type>package</type>
|
||||||
<folder>system</folder>
|
<version>02.04.00-alpha</version>
|
||||||
<client>site</client>
|
<tags><tag>alpha</tag></tags>
|
||||||
<version>02.05.00</version>
|
<infourl title="MokoWaaS">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/alpha</infourl>
|
||||||
<tags><tag>stable</tag></tags>
|
|
||||||
<infourl title="MokoWaaS">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/v02</infourl>
|
|
||||||
<downloads>
|
<downloads>
|
||||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/v02/pkg_mokowaas-02.05.00.zip</downloadurl>
|
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/alpha/pkg_mokowaas-02.04.00-alpha.zip</downloadurl>
|
||||||
|
</downloads>
|
||||||
|
<targetplatform name="joomla" version="(5|6)\..*" />
|
||||||
|
<maintainer>Moko Consulting</maintainer>
|
||||||
|
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||||
|
</update>
|
||||||
|
<update>
|
||||||
|
<name>MokoWaaS</name>
|
||||||
|
<description>MokoWaaS update</description>
|
||||||
|
<element>mokowaas</element>
|
||||||
|
<type>package</type>
|
||||||
|
<version>02.04.00-beta</version>
|
||||||
|
<tags><tag>beta</tag></tags>
|
||||||
|
<infourl title="MokoWaaS">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/beta</infourl>
|
||||||
|
<downloads>
|
||||||
|
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/beta/pkg_mokowaas-02.04.00-beta.zip</downloadurl>
|
||||||
|
</downloads>
|
||||||
|
<targetplatform name="joomla" version="(5|6)\..*" />
|
||||||
|
<maintainer>Moko Consulting</maintainer>
|
||||||
|
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||||
|
</update>
|
||||||
|
<update>
|
||||||
|
<name>MokoWaaS</name>
|
||||||
|
<description>MokoWaaS update</description>
|
||||||
|
<element>mokowaas</element>
|
||||||
|
<type>package</type>
|
||||||
|
<version>02.04.00-rc</version>
|
||||||
|
<tags><tag>rc</tag></tags>
|
||||||
|
<infourl title="MokoWaaS">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/rc</infourl>
|
||||||
|
<downloads>
|
||||||
|
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/rc/pkg_mokowaas-02.04.00-rc.zip</downloadurl>
|
||||||
|
</downloads>
|
||||||
|
<targetplatform name="joomla" version="(5|6)\..*" />
|
||||||
|
<maintainer>Moko Consulting</maintainer>
|
||||||
|
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||||
|
</update>
|
||||||
|
<update>
|
||||||
|
<name>MokoWaaS</name>
|
||||||
|
<description>MokoWaaS update</description>
|
||||||
|
<element>mokowaas</element>
|
||||||
|
<type>package</type>
|
||||||
|
<version>02.04.00</version>
|
||||||
|
<tags><tag>stable</tag></tags>
|
||||||
|
<infourl title="MokoWaaS">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/stable</infourl>
|
||||||
|
<downloads>
|
||||||
|
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/pkg_mokowaas-02.04.00.zip</downloadurl>
|
||||||
</downloads>
|
</downloads>
|
||||||
<targetplatform name="joomla" version="(5|6)\..*" />
|
<targetplatform name="joomla" version="(5|6)\..*" />
|
||||||
<maintainer>Moko Consulting</maintainer>
|
<maintainer>Moko Consulting</maintainer>
|
||||||
|
|||||||
Reference in New Issue
Block a user